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:
DavitoandCopilot committed 2026-10-30 15:58:58 +01:00
commit e0773ba299
84 files changed
+12688

No files matched your search

+68
View File
@@ -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),
})
}