Domanda

Come posso deallocare le risorse quando il processo viene ucciso, ad esempio dal Task Manager? C'è un modo per chiamare una funzione prima che il processo venga chiuso?

È stato utile?

Soluzione

Non c'è davvero nulla che tu possa fare se il tuo processo viene interrotto. Per definizione, uccidere un processo è proprio questo: ucciderlo. Il processo non ha l'opportunità di eseguire alcun codice. Questo è molto & Quot; in base alla progettazione & Quot ;.

Immagina di poter registrare una routine chiamata quando il tuo processo è stato interrotto dall'utente (o da un altro processo). Cosa farebbe? Tutti gli altri thread nel tuo processo sarebbero in uno stato indeterminato, come ti sincronizzeresti con loro? Ricorda, l'idea è che il processo debba essere ucciso.

L'altro scenario è ancora più difficile: il tuo codice è benigno e cerca di fare la cosa giusta, ad es. ripulire ed essere un buon cittadino di sistema. Alcuni codici non lo sono. Immagina che vantaggio sarebbe un autore di malware se il sistema operativo consentisse l'esecuzione del codice per un processo che è stato ucciso. Sarebbe abbastanza grave per i processi dannosi in esecuzione con privilegi di utente standard e completamente terribile per qualsiasi esecuzione con privilegi di amministratore.

Le finalizzazioni critiche e la gestione strutturata delle eccezioni non risolveranno questo problema fondamentale.

Sul lato positivo, il sistema operativo libererà tutte le risorse che conosce quando il processo viene interrotto, vale a dire oggetti di memoria e kernel. Quelli non coleranno. Ma Explorer non è a conoscenza del tuo processo, quindi non può ripulirlo.

Un modo per risolverlo sarebbe quello di avere un processo di monitoraggio che tenga traccia dello stato degli altri tuoi processi e lo ripulisca. Puoi farlo con un semplice processo o con un servizio. Potresti anche prendere in considerazione una sorta di estensione shell che ha il suo thread che ha fatto la stessa cosa.

Altri suggerimenti

Non è possibile eseguire codice arbitrario al termine di un processo che sta per essere ucciso da una chiamata a TerminateProcess, ad esempio da Task Manager o da un'altra utilità di processo come TSKILL o TASKKILL.

Né finalizzatori critici, né finalizzatori ordinari, né blocchi try / finally, e certamente non semplici oggetti che implementano IDisposable possono causare l'esecuzione di codice in questo scenario. Anche gli eventi di scollegamento DLL non verranno richiamati da una terminazione del processo tramite <=>.

Il meglio che puoi fare è utilizzare un processo di watchdog che monitora il processo originale ed esegue il codice pertinente al termine del processo originale.

Teoricamente l'O / S dovrebbe deallocare le risorse dopo che il processo è stato terminato. A che tipo di risorsa stai pensando in particolare?


Modifica

  

Ok, è piuttosto difficile da spiegare. Sto usando una libreria che racchiude alcune funzioni del sistema operativo per gestire alcune estensioni della shell. Quando l'applicazione si chiude senza chiamare esplicitamente i metodi appropriati, tutto Explorer si blocca e devo riavviarlo.

Si suppone che qualsiasi DLL non gestita (secondo la documentazione) venga invocata con un evento DLL_PROCESS_DETACH; tuttavia, questo TerminateProcess evento non viene chiamato quando il processo viene terminato tramite l'API <=>.

Cercando su Google questi termini sono stati visualizzati The Old New Thing: Perché non riesci a intercettare TerminateProcess? che dice " Una volta ucciso con TerminateProcess, non verrà eseguito più codice in modalità utente in quel processo. È sparito. & Quot;

Poiché tutto ciò con cui stai cercando di lavorare (ad es. .NET, Explorer, Shell, COM) sta avvenendo in modalità utente, penso che la risposta sia che non c'è modo di fare quello che vuoi.

Invece, forse c'è un altro modo: ad esempio, aggiungendo codice alle estensioni Shell in modo che si rendano conto se il processo è stato interrotto.

Potresti provare a racchiudere l'intero processo in un'istruzione try / finally (hai messo le cose di deallocazione nella clausola finally), ma in alcuni casi anche questo non sarà sufficiente.

In realtà, penso che potresti lanciare un thread in background dal tuo processo per fare tutto e Thread.Join () con il tuo thread principale in modo che se qualcosa va storto nel thread figlio, il thread principale sarà ancora in grado di fai le cose bene. Naturalmente, questo non funzionerà se l'intero processo viene interrotto per qualche motivo.

Potresti anche avviare un processo figlio e chiamare Process.WaitForExit () ma non sono sicuro che la tua cosa relativa alla shell possa funzionare con un approccio multi-processo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top