replace JavaScript and C# packaging tools with Rust

This commit is contained in:
曾志威
2026-08-14 17:07:27 +08:00
parent b18125bf04
commit b92c57ef44
26 changed files with 530 additions and 442 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ windows = { version = "0.62.2", features = [
[target.'cfg(windows)'.dependencies]
cpal = "0.17.3"
opus2 = { version = "0.4.0", features = ["bundled"] }
opus2 = { version = "0.4.0", default-features = false, features = ["backend-mousiki"] }
windows-sys = { version = "0.61.2", features = [
"Win32_Foundation",
"Win32_Security",
+66 -2
View File
@@ -2,6 +2,9 @@ use clap::{Parser, Subcommand};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::SocketAddr;
use std::path::Path;
#[cfg(windows)]
use std::process::Command as ProcessCommand;
#[cfg(windows)]
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
@@ -40,7 +43,7 @@ static ENCODED_SESSIONS: OnceLock<Mutex<HashMap<String, EncodedSessionRoute>>> =
)]
struct Cli {
#[command(subcommand)]
command: Command,
command: Option<Command>,
}
#[derive(Debug, Subcommand)]
@@ -60,6 +63,7 @@ enum Command {
#[arg(long)]
allow_unauthenticated: bool,
},
ConfigureHost,
}
#[derive(Debug, Serialize)]
@@ -88,7 +92,14 @@ struct Status {
fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
let command = match cli.command {
Some(command) => command,
None if is_portable_host_executable(std::env::current_exe()?.as_path()) => {
Command::ConfigureHost
}
None => anyhow::bail!("a command is required; use --help to list available commands"),
};
match command {
Command::Status { json } => {
let capabilities = capability::snapshot();
let status = Status {
@@ -140,10 +151,50 @@ fn main() -> anyhow::Result<()> {
name,
allow_unauthenticated,
} => run_pipe_server(name, allow_unauthenticated)?,
Command::ConfigureHost => configure_host()?,
}
Ok(())
}
fn is_portable_host_executable(path: &Path) -> bool {
path.file_stem()
.and_then(|name| name.to_str())
.is_some_and(|name| name.eq_ignore_ascii_case("RemoteDesk-Host"))
}
#[cfg(windows)]
fn configure_host() -> anyhow::Result<()> {
let executable = std::env::current_exe()?;
let root = executable
.parent()
.ok_or_else(|| anyhow::anyhow!("unable to locate the portable Host directory"))?;
let script = root.join("Configure-RemoteDeskHost.ps1");
anyhow::ensure!(script.is_file(), "Configure-RemoteDeskHost.ps1 is missing");
let status = ProcessCommand::new("powershell.exe")
.current_dir(root)
.arg("-NoProfile")
.arg("-ExecutionPolicy")
.arg("Bypass")
.arg("-File")
.arg(&script)
.arg("-Action")
.arg("Enable")
.arg("-AcceptRemoteDesktopChanges")
.status()
.map_err(|error| anyhow::anyhow!("unable to start Host configuration: {error}"))?;
anyhow::ensure!(
status.success(),
"Host configuration exited with {}",
status.code().unwrap_or(-1)
);
Ok(())
}
#[cfg(not(windows))]
fn configure_host() -> anyhow::Result<()> {
anyhow::bail!("Host configuration is only available on Windows")
}
fn run_server(listen: SocketAddr) -> anyhow::Result<()> {
let runtime = tokio::runtime::Runtime::new()?;
runtime.block_on(async move {
@@ -1384,6 +1435,19 @@ mod fallback {
mod tests {
use super::*;
#[test]
fn portable_host_alias_selects_the_rust_launcher() {
assert!(is_portable_host_executable(Path::new(
r"C:\RemoteDesk\RemoteDesk-Host.exe"
)));
assert!(is_portable_host_executable(Path::new(
r"C:\RemoteDesk\remotedesk-host.EXE"
)));
assert!(!is_portable_host_executable(Path::new(
r"C:\RemoteDesk\remotedesk-windows-agent.exe"
)));
}
#[test]
fn legacy_software_fallback_field_does_not_enable_compatibility() {
let default: AgentCommand = serde_json::from_str(r#"{"kind":"open_desktop"}"#).unwrap();