Erste Version: Tauri-Grundgerüst, WinGet-Anbindung, Selbst-Updater und Release-Skript
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
commit
e0773ba299
84 files changed
+12688
No files matched your search
@@ -0,0 +1,68 @@
|
||||
//! Start externer Prozesse ohne Konsolenfenster, mit Zeitlimit und UTF-8-Dekodierung.
|
||||
|
||||
use std::path::Path;
|
||||
use std::process::Stdio;
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::process::Command;
|
||||
|
||||
use crate::error::{AppError, AppResult};
|
||||
|
||||
/// Ergebnis eines beendeten Prozesses.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CmdOutput {
|
||||
/// Exit-Code (`None`, wenn der Prozess beendet wurde).
|
||||
pub code: Option<i32>,
|
||||
pub stdout: String,
|
||||
pub stderr: String,
|
||||
}
|
||||
|
||||
/// Dekodiert Prozessausgabe als UTF-8 und entfernt ein führendes BOM.
|
||||
pub fn decode(bytes: &[u8]) -> String {
|
||||
let text = String::from_utf8_lossy(bytes);
|
||||
text.trim_start_matches('\u{feff}').to_owned()
|
||||
}
|
||||
|
||||
/// Erzeugt ein Kommando, das unter Windows kein Konsolenfenster öffnet.
|
||||
pub fn command(program: &Path) -> Command {
|
||||
let mut cmd = Command::new(program);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
|
||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
}
|
||||
cmd.kill_on_drop(true)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped());
|
||||
cmd
|
||||
}
|
||||
|
||||
/// Führt ein Programm aus und wartet höchstens `timeout`.
|
||||
pub async fn run(program: &Path, args: &[&str], timeout: Duration) -> AppResult<CmdOutput> {
|
||||
run_env(program, args, &[], timeout).await
|
||||
}
|
||||
|
||||
/// Wie [`run`], setzt zusätzlich Umgebungsvariablen (z. B. um Benutzereingaben sicher zu übergeben).
|
||||
pub async fn run_env(
|
||||
program: &Path,
|
||||
args: &[&str],
|
||||
envs: &[(&str, &str)],
|
||||
timeout: Duration,
|
||||
) -> AppResult<CmdOutput> {
|
||||
let mut cmd = command(program);
|
||||
cmd.args(args).envs(envs.iter().copied());
|
||||
tracing::debug!(program = %program.display(), ?args, "Prozess wird gestartet");
|
||||
let child = cmd.spawn().map_err(|source| AppError::Spawn {
|
||||
program: program.display().to_string(),
|
||||
source,
|
||||
})?;
|
||||
let output = tokio::time::timeout(timeout, child.wait_with_output())
|
||||
.await
|
||||
.map_err(|_| AppError::Timeout(timeout.as_secs()))??;
|
||||
Ok(CmdOutput {
|
||||
code: output.status.code(),
|
||||
stdout: decode(&output.stdout),
|
||||
stderr: decode(&output.stderr),
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user