Come chiudere programmaticamente tutti gli handle di file in una determinata cartella?


18

Mi chiedevo se esiste uno strumento da riga di comando che mi consente di chiudere tutti gli handle di file aperti in una cartella specifica.

Ho provato ProcessExplorer , Unlocker e strumenti simili, ma offrono un'interfaccia GUI e non sono utili in un ambiente di programmazione

Una soluzione su Python, cmd o PowerShell sarebbe l'ideale.


Ricordare che la chiusura forzata di un handle di file potrebbe causare l'arresto anomalo del programma che utilizza tale handle.
Harry Johnston,

1
@HarryJohnston Peggio ancora, potresti finire per causare ogni sorta di corruzione dei file finché il programma è aperto: technet.microsoft.com/en-us/magazine/…
Bob

Risposte:


7

Unlocker afferma di darti questa abilità:

  1. Basta fare clic destro sulla cartella o sul file e selezionare Unlocker

    Passo 1

  2. Se la cartella o il file è bloccato, verrà visualizzato un elenco di armadietti

    Passo 2

  3. Basta fare clic Unlock Alle il gioco è fatto!

Non sono sicuro che supporti l'utilizzo della riga di comando.

FileASSASSIN di Malwarebyte esegue azioni simili, e fa uso della riga di comando di supporto, così si dovrebbe essere in grado di sceneggiatura abbastanza facilmente.

Switch di FileAssassin


Grazie techie007, immagino di essermi perso. Ho notato che a volte Unlocker manca i miei file (ProcessExplorer no). Un secondo problema è se desidero sbloccare o rilasciare i file a livello di codice (ad esempio, uno strumento da riga di comando sarebbe utile in questa direzione).
Amelio Vazquez-Reina,

@intrpc Ecco fatto, ho aggiunto un altro suggerimento (adatto alla riga di comando). :)
Ƭᴇcʜιᴇ007,

1
Attento, Unlocker viene fornito in bundle con malware in questi giorni.
Joshua Hanley,

10

Grazie per questo. Abbiamo riscontrato alcuni problemi con gli handle di file aperti che causavano il fallimento dei checkout di Git nei nostri lavori Jenkins basati su Windows e questo ci ha aiutato a correggere facilmente il problema. Butto fuori le basi della tecnica:

  1. Installare Handle.exe sul nodo build. L'ho scaricato da qui http://technet.microsoft.com/en-us/sysinternals/bb896655 , decompresso e rilasciato Handle.exe in C: \ Windows \ System32 per assicurarsi che fosse disponibile sul% PATH% predefinito

  2. Installa il plug-in Jenkins pre-scm-buildstep: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep . Questo ci consente di definire le operazioni prima che il plugin git iniziasse a raggiungere file potenzialmente bloccati.

  3. Implementato il seguente comando batch come fase di compilazione pre-scm:

    @echo off
    echo Cleaning up open file handles from %NODE_NAME%:%WORKSPACE%...
    for /f "tokens=3,6,8 delims=: " %%i in ('Handle /accepteula %WORKSPACE% ^| grep workspace') do echo Releasing file lock on E:%%k & handle -c %%j -y -p %%i
    

Sembra funzionare bene e sicuramente riduce i fallimenti spuri. Noterò anche un paio di gotcha con cui ho lavorato:

  • Handler.exe ha un EULA che deve essere accettato la prima volta che viene eseguito. Se stai eseguendo il tuo agente Jenkins come servizio nel contesto del sistema locale, questo è problematico perché non puoi accedere come quell'utente e accettarlo a mano. Quando abbiamo provato a eseguirlo dal lavoro Jenkins, il processo è rimasto in attesa dell'input dell'utente e ci sono voluti alcuni minuti per capire perché. Ho risolto il problema eseguendolo dal lavoro Jenkins usando il flag / accepteula e consiglio a chiunque lo stia implementando come un processo automatizzato di fare lo stesso. Questa è un'impostazione del Registro di sistema in HKEY_CURRENT_USER \ Software \ Sysinternals \ Handle e puoi anche impostarla e disinserirla tramite regedit.exe se è necessario manipolarla per un utente specifico, ma l'opzione della riga di comando sembrava più semplice.

  • Il plug-in passo Jenkins Batch esegue il codice batch come se fosse in uno script anziché come una direttiva da riga di comando. Notare gli escape (ad es. %% i, ^ |).

Grazie!


Lottando per ottenere la sintassi di questo, qualcuno può fornire maggiori dettagli su cosa è %% i, j ecc?
c4sh,

Ciò potrebbe aiutare a comprendere la sintassi del comando batch: robvanderwoude.com/ntfortokens.php
c4sh,

Come avete risolto il fatto che handle.exe deve essere eseguito come amministratore, mentre lo eseguiamo da un utente Jenkins che non è admin?
c4sh

8

Usiamo il seguente frammento per chiudere l'handle del file dagli utenti al nostro server. Potresti essere in grado di modificarlo per il tuo uso.

rem close all network files that are locked
for /f "skip=4 tokens=1" %%a in ('net files') do net files %%a /close

Grazie @Brendan. Penso che il tuo codice non sia stato formattato correttamente. La tua risposta sembra interessante, quindi se non ti dispiace modificarla, ti suggerirei di selezionare le tue righe di codice, quindi fare clic sul pulsante con i due braccialetti ricci. Ciò trasformerà il tuo frammento in codice leggibile.
Amelio Vazquez-Reina,

5

Creo questo piccolo file batch per rilasciare automaticamente tutti i blocchi in file XML con la mia eclissi

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle -p eclipse e:\git\ ^| grep .xml') do echo Releasing %%k & handle -c %%j -y -p %%i

È necessario scaricare l' utilità handle dal sito Microsoft e l' utilità grep da GnuWin32

Se non hai bisogno di filtrare per tipo di file, puoi saltare la parte grep in questo modo:

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle -p eclipse e:\git\') do echo Releasing %%k & handle -c %%j -y -p %%i

Oppure, se non è necessario filtrare i blocchi in base a un determinato programma, è sufficiente rimuovere il filtro del processo eclipse:

@echo off
for /f "tokens=3,6,8 delims=: " %%i in ('handle e:\git\') do echo Releasing %%k & handle -c %%j -y -p %%i

Ricorda di sostituire e:\git\con il percorso della cartella.


4

Se stai usando PSTools , questo forzerà la chiusura ricorsiva di tutti i file aperti:

psfile \\serverName c:\path\toDatabase\ -c

Si noti che c:\path\toDatabase\è l'unità C: attiva \\serverName, non il computer locale. All'inizio non mi era chiaro, quindi ho pensato di segnalarlo.

Questo è un approccio a forza bruta che garantisce quasi la perdita di dati, quindi usalo con cautela.

Abbiamo messo insieme un database di Access che mette letteralmente in ginocchio la nostra azienda su base regolare (ho dovuto ripararlo tre volte proprio ieri).

Il ragazzo che normalmente gestisce questo è in vacanza per un paio di settimane e le sue istruzioni utilizzano un approccio basato sull'interfaccia utente (Start> Computer> Gestisci> Gestione computer (locale)> Connetti a un altro computer> Strumenti di sistema> Cartelle condivise> Apri file> Chiudi Apri file). MODO troppi clic quando posso semplicemente eseguire il comando sopra e buttare via l'intera azienda da tutti i file del database e avviare il processo Compatta e ripristina (a cui sto lavorando anche su un approccio basato su script di forza bruta).

Il trucco sta davanti alle persone che iniziano immediatamente a riconnettersi al database non appena si interrompe. Sono così abituati a questo che non gli viene in mente di presentare un bug contro di esso, continuano a martellare il database fino a quando non rientrano. Continuo ad avviarli fino a quando non ho compattato e riparato le tre dozzine file che compongono il database.


4

Se stai parlando di handle di file aperti tramite una condivisione SMB su un file server Windows (Server 2012 o più recente), ecco la risposta di PowerShell:

Get-SmbOpenFile | Where-Object { $_.Path -like "D:\Folder\*" } | Close-SmbOpenFile -Force

Su un vecchio file server Windows, lo è openfiles.exe /disconnect.

Per un handle di file di sistema locale, il modo migliore che ho trovato è utilizzare handle.exe di Sysinternals


3

Preferisco http://lockhunter.com perché supporta sia l'interfaccia grafica che l'interfaccia della riga di comando e in molti casi è stato in grado di eliminare file che non potevano essere eliminati da Unlocker.


2

Unlocker può funzionare anche in modalità silenziosa.

Ad esempio, per sbloccare tutti i file all'interno dell'area di lavoro di Jenkins:

"C:\Program Files\Unlocker\unlocker.exe" "%WORKSPACE%" /S

Quindi è possibile eliminare in modo sicuro i file dell'area di lavoro:

del "%WORKSPACE%\*.*" /s /q

0

Puoi usare Powershell per fare queste cose:

function KillProcessesWithHandles
{
    param([string]$path)

    $allProcesses = Get-Process

    # Start by closing all notepad processes. Someone may have left a logor config file open
    $allProcesses | Where-Object {$_.Name -eq "notepad"} | Stop-Process -Force -ErrorAction SilentlyContinue

    # Then close all processes running inside the folder we are trying to delete
    $allProcesses | Where-Object {$_.Path -like ($path + "*")} | Stop-Process -Force -ErrorAction SilentlyContinue

    # Finally close all processes with modules loaded from folder we are trying to delete
    foreach($lockedFile in Get-ChildItem -Path $path -Include * -Recurse) {
        foreach ($process in $allProcesses) {
            $process.Modules | Where-Object {$_.FileName -eq $lockedFile} | Stop-Process -Force -ErrorAction SilentlyContinue
        }
    }
}

Per maggiori dettagli, consultare Thomas Ardal qui: https://thomasardal.com/deleting-contents-of-a-folder-contain-files-with-open-file-handles-using-powershell/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.