Sembra un compito impossibile. Assolutamente nulla ho trovato opere. La domanda è come chiudere in modo pulito un'applicazione console avviata con Process.Start che è stata avviata senza alcuna finestra della console e senza utilizzare shell execute: (ProcessStartInfo.CreateNoWindow = true; ProcessStartInfo.UseShellExecute = false;
).Come chiudere correttamente un'app per console avviata con Process.Start?
È dato che l'applicazione che si avvia si spegne "in modo pulito" se riceve un segnale ctrl-c o ctrl-break, ma sembra che non ci sia modo di inviarne uno che funzioni (in particolare GenerateConsoleCtrlEvent).
- Process.Kill non funziona. Lascia i file corrotti dietro a causa di un improvviso annullamento del processo da parte di .
- Process.CloseMainWindow non funziona. In questo caso non c'è una finestra principale, quindi la funzione restituisce false e non fa nulla.
- Chiamando EnumThreadWindows su tutti i thread per il processo e inviando un WM_CLOSE a ogni finestra non fa nulla, e non ci sono comunque finestre di thread.
- GenerateConsoleCtrlEvent non funziona. È utile solo per i processi nello stesso gruppo (su cui .NET non ti dà alcun controllo), con un indesiderato effetto collaterale di chiudere comunque il processo di chiamata. La funzione non consente di specificare un id di processo.
Chiunque può fornire codice che accetta un oggetto "Processo" avviato con i parametri sopra che si traduce in un nuovo arresto del processo avviato senza influenzare il processo chiamante sarà contrassegnato come risposta. Usa 7z.exe (7-zip archiver) come app di console di esempio, che inizia a comprimere un file di grandi dimensioni e lascerà un file corrotto non finito dietro se non terminato in modo pulito.
Fino a quando qualcuno fornisce un esempio funzionale o un codice che porta a un esempio funzionale, questa domanda non ha risposta. Ho visto dozzine di persone a fare questa domanda e decine di risposte online, e nessuna di queste funzioni. .NET sembra non fornire supporto per chiudere in modo pulito un'applicazione console dato il suo id di processo, il che è strano considerando che è stato avviato con un oggetto .NET Process. Parte del problema è l'impossibilità di creare un processo in un nuovo gruppo di processi, il che rende inutile l'uso di GenerateConsoleCtrlEvent. Ci deve essere una soluzione a questo.
Mi sembra la soluzione corretta è 'GenerateConsoleCtrlEvent'. Quindi devi solo capire come creare un processo in un nuovo gruppo. Se ciò non è possibile utilizzando il wrapper di processo .NET, passare alla funzione nativa di Win32. Nessun danno nell'usare P/Invoke, lo stai già facendo per 'GenerateConsoleCtrlEvent' comunque. –
Non sto già usando GenerateConsoleCtrlEvent (non funziona), e preferirei non usare P/Invoke. La struttura SECURITY_ATTRIBUTES usata da CreateProcess ha un puntatore che mi richiede di compilare con 'unsafe', cosa che non sto facendo. Un altro problema con CreateProcess è che non riesco a utilizzare Process.EnableRaisingEvents e l'evento Exited in modo affidabile, poiché il processo potrebbe terminare prima che io abbia la possibilità di chiamare Process.GetProcessById per creare un'istanza di .NET Process per assegnare il gestore, che normalmente sarebbe fatto prima di chiamare Process.Start. Sono costretto a riscrivere la maggior parte della logica in Win32. – Triynko
E non funziona comunque, come ho detto. Nonostante la creazione del processo con CREATE_NEW_PROCESS_GROUP, GenerateConsoleCtrlEvent non ha alcun effetto sul gruppo, come identificato dall'ID di processo. Ho provato a passare la costante per CTRL + C, quindi CTRL + INTERR e non funziona. Inoltre, insieme a CREATE_NEW_PROCESS_GROUP, ho provato entrambi i flag per CREATE_NO_WINDOW o DETACHED_PROCESS (separatamente, poiché si escludono a vicenda), e mentre entrambi raggiungono un processo senza console che non interferisce con la finestra della console dell'applicazione principale, GenerateConsoleCrtlEvent il metodo non funziona. – Triynko