fix(rustdesk): reaplica install-service e valida estado RUNNING

This commit is contained in:
Esdras Renan 2025-11-25 13:18:10 -03:00
parent 56cd5fa344
commit e9ba1790fb
2 changed files with 42 additions and 1 deletions

View file

@ -431,6 +431,23 @@ fn ensure_service_running(exe_path: &Path) -> Result<(), RustdeskError> {
}
Err(error) => Err(error),
}
// Revalida se o serviço realmente subiu; se não, reinstala e tenta novamente.
match query_service_state() {
Some(state) if state.eq_ignore_ascii_case("running") => Ok(()),
_ => {
log_event("Serviço RustDesk não está em execução após tentativa de start; reaplicando --install-service e start");
let _ = run_with_args(exe_path, &["--install-service"]);
let _ = run_sc(&["config", SERVICE_NAME, &format!("start= {}", "auto")]);
start_sequence().or_else(|error| {
log_event(&format!(
"Falha ao subir o serviço RustDesk mesmo após reinstalação: {error}"
));
Ok(())
})?;
Ok(())
}
}
}
fn configure_service_startup() -> Result<(), RustdeskError> {
@ -451,6 +468,30 @@ fn configure_service_startup() -> Result<(), RustdeskError> {
Ok(())
}
fn query_service_state() -> Option<String> {
let output = hidden_command("sc")
.args(["query", SERVICE_NAME])
.output()
.ok()?;
if !output.status.success() {
return None;
}
let stdout = String::from_utf8_lossy(&output.stdout);
for line in stdout.lines() {
if let Some(pos) = line.find("STATE") {
// Example: " STATE : 4 RUNNING"
let state = line[pos..].to_string();
if state.to_lowercase().contains("running") {
return Some("running".to_string());
}
if state.to_lowercase().contains("stopped") {
return Some("stopped".to_string());
}
}
}
None
}
fn stop_rustdesk_processes() -> Result<(), RustdeskError> {
if let Err(error) = try_stop_service() {
log_event(&format!(

View file

@ -54,7 +54,7 @@ Fluxo ideal:
- Reinicia serviço `RustDesk` (`sc start RustDesk` — pode falhar com `status Some(5)` se não há privilégio admin). Mesmo com falha, a CLI continua e grava o ID nos arquivos.
- **Autoelevação única**: na primeira execução do botão “Preparar”, o Raven dispara um PowerShell elevado (`takeown + icacls`) para liberar ACL dos perfis `LocalService` e `LocalSystem`. O sucesso grava `rustdeskAclUnlockedAt` dentro de `%LOCALAPPDATA%\br.com.esdrasrenan.sistemadechamados\machine-agent.json` e cria o flag `rustdesk_acl_unlocked.flag`, evitando novos prompts de UAC nas execuções seguintes.
- **Kill/restart seguro**: antes de tocar nos TOML, o Raven roda `sc stop RustDesk` + `taskkill /F /T /IM rustdesk.exe`. Isso garante que nenhum cliente sobrescreva o `RustDesk_local.toml` enquanto aplicamos a senha.
- **Serviço em background reforçado**: `ensure_service_running` sempre instala o serviço, força `start= auto` e aplica `sc failure ... actions= restart/5000/...` para reiniciar o RustDesk automaticamente em caso de falha. Assim ele permanece no background/bandeja após boot, sem depender do usuário abrir a UI.
- **Serviço em background reforçado**: `ensure_service_running` sempre instala o serviço, força `start= auto`, aplica `sc failure ... actions= restart/5000/...` e revalida se o serviço ficou em `RUNNING`. Se não subir, reaplica `--install-service` + `sc start` antes de seguir. Assim ele permanece no background/bandeja após boot, sem depender do usuário abrir a UI.
- **Replicação completa de perfis**: após aplicar `--password`, limpamos quaisquer arquivos antigos (`RustDesk*.toml`, `password`, `passwd*`) em `%APPDATA%`, `ProgramData`, `LocalService` e `LocalSystem` e, em seguida, reescrevemos tudo. Agora os `RustDesk2.toml` herdados recebem `verification-method = "use-permanent-password"` e `approve-mode = "password"` no bloco `[options]` antes mesmo do serviço subir, evitando que o RustDesk volte para "Use both".
- **Validação por arquivo**: o Raven agora registra no `rustdesk.log` se o `password` gravado em cada `RustDesk_local.toml` coincide com o PIN configurado. Para inspecionar manualmente, rode no PowerShell (e valide que todas as linhas exibem o PIN esperado):