c# - utente - fileassassin




Come faccio a eliminare un file bloccato da un altro processo in C#? (6)

Sto cercando un modo per eliminare un file bloccato da un altro processo usando C #. Ho il sospetto che il metodo debba essere in grado di trovare quale processo sta bloccando il file (forse monitorando gli handle, anche se non sono sicuro di come farlo in C #) quindi chiudere quel processo prima di poter completare l'eliminazione del file usando File.Delete() .


Il metodo tipico è il seguente. Hai detto che vuoi farlo in C # quindi ecco qui ...

  1. Se non si conosce quale processo ha il file bloccato, è necessario esaminare l'elenco di handle di ciascun processo ed eseguire una query su ciascun handle per determinare se identifica il file bloccato. Per fare ciò in C # probabilmente sarà necessario P / Invoke o un C ++ / CLI intermedio per chiamare le API native di cui hai bisogno.
  2. Una volta capito quali processi hanno il file bloccato, dovrai iniettare in modo sicuro una piccola DLL nativa nel processo (puoi anche iniettare una DLL gestita, ma questo è più disordinato, poiché devi quindi iniziare o collegarsi al runtime .NET).
  3. Quella DLL bootstrap quindi chiude l'handle usando CloseHandle, ecc.

In sostanza: il modo per sbloccare un file "bloccato" è quello di iniettare un file DLL nello spazio degli indirizzi del processo offensivo e chiuderlo da soli. Puoi farlo usando il codice nativo o gestito. Non importa cosa, avrai bisogno di una piccola quantità di codice nativo o almeno P / Invoke nello stesso.

Collegamenti utili:

In bocca al lupo!


Oh, un grande trucco che ho impiegato anni fa è che Windows non ti consente di eliminare i file, ma ti consente di spostarli .

Pseudo-sort-of-code:

mv %WINDIR%\System32\mfc42.dll %WINDIR\System32\mfc42.dll.old
Install new mfc42.dll
Tell user to save work and restart applications

Quando le applicazioni sono state riavviate (nota che non è necessario riavviare il computer), hanno caricato il nuovo mfc42.dll e tutto è andato bene. Questo, insieme a PendingFileOperations per eliminare quello vecchio alla successiva riavvio dell'intero sistema, ha funzionato abbastanza bene.


Puoi usare questo programma, Handle , per trovare quale processo ha il blocco sul tuo file. È uno strumento da riga di comando, quindi immagino che tu usi l'output di quello ... Non sono sicuro di trovarlo a livello di codice.

Se la cancellazione del file può attendere, è possibile specificarlo per l'eliminazione al successivo avvio del computer:

  1. Avviare REGEDT32 (W2K) o REGEDIT (WXP) e accedere a:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
  2. W2K e WXP

    • W2K:
      modificare
      Aggiungere valore...
      Tipo di dati: REG_MULTI_SZ
      Nome valore: PendingFileRenameOperations
      ok

    • WXP:
      modificare
      Nuovo
      Valore multistringa
      accedere
      PendingFileRenameOperations

  3. Nell'area Dati, immettere "\??\" + filename da eliminare. Gli LFN possono essere inseriti senza essere inseriti tra virgolette. Per eliminare C:\Long Directory Name\Long File Name.exe , immettere i seguenti dati:

    \??\C:\Long Directory Name\Long File Name.exe

    Quindi premere OK .

  4. Il "nome del file di destinazione" è una stringa nulla (zero). È inserito come segue:

    • W2K:
      modificare
      Binario
      selezionare il formato dati: esadecimale
      fare clic alla fine della stringa esadecimale
      inserisci 0000 (quattro zeri)
      ok

    • WXP:
      Fare clic con il tasto destro del mouse sul valore
      scegli "Modifica dati binari"
      fare clic alla fine della stringa esadecimale
      inserisci 0000 (quattro zeri)
      ok

  5. Chiudi REGEDT32/REGEDIT e riavvia per eliminare il file.

(Rubati spudoratamente da qualche forum casuale , per l'amor dei posteri.)


Se vuoi farlo programmaticamente. Non ne sono sicuro ... e lo sconsiglioi davvero. Se stai solo risolvendo problemi sul tuo computer, SysInternals Process Explorer può aiutarti

Eseguilo, usa il comando Trova handle (penso sia nel menu trova o gestisci) e cerca il nome del tuo file. Una volta trovati gli handle, è possibile chiuderli con la forza.

È quindi possibile eliminare il file e così via.

Attenzione , ciò potrebbe causare un comportamento strano del programma proprietario delle maniglie, dato che hai appena estratto il tappeto proverbiale da sotto di esso, ma funziona bene quando esegui il debug del tuo codice errante o quando visual studio / windows explorer sta facendo schifo e non rilasciando handle di file anche se hai detto loro di chiudere il file anni fa ... sigh :-)


Uccidere altri processi non è una cosa salutare da fare. Se lo scenario prevede qualcosa di simile alla disinstallazione, è possibile utilizzare la funzione API MoveFileEx per contrassegnare il file per l'eliminazione al successivo riavvio.

Se sembra che tu abbia davvero bisogno di eliminare un file in uso da un altro processo, ti consiglio di riconsiderare il problema reale prima di considerare qualsiasi soluzione.


Usando il consiglio di Orion Edwards ho scaricato Sysinternals Process Explorer che a sua volta mi ha permesso di scoprire che il file che stavo avendo difficoltà a cancellare non era in realtà trattenuto dall'oggetto Excel.Applications che pensavo, ma piuttosto dal fatto che il mio codice C # inviasse posta codice aveva creato un oggetto Allegato che ha lasciato aperto un handle per questo file.

Una volta che l'ho visto, ho semplicemente chiamato il metodo dispose dell'oggetto Attachment e l'handle è stato rilasciato.

L'esploratore Sysinternals mi ha permesso di scoprire questo usato insieme al debugger di Visual Studio 2005.

Consiglio vivamente questo strumento!





file-locking