Wie kann ich programmgesteuert alle Dateihandles in einem bestimmten Ordner schließen?


18

Ich habe mich gefragt, ob es ein Befehlszeilentool gibt, mit dem ich alle Dateihandles schließen kann, die in einem bestimmten Ordner geöffnet sind.

Ich habe ProcessExplorer , Unlocker und ähnliche Tools ausprobiert , aber sie bieten eine GUI-Oberfläche und sind in einer Programmierumgebung nicht nützlich

Eine Lösung auf Python, Cmd oder PowerShell wäre ideal.


Denken Sie daran, dass das gewaltsame Schließen eines Datei-Handles dazu führen kann, dass das Programm, das dieses Handle verwendet, abstürzt.
Harry Johnston

1
@HarryJohnston Schlimmer noch, Sie könnten am Ende alle Arten von Dateibeschädigungen verursachen, solange das Programm geöffnet ist: technet.microsoft.com/en-us/magazine/…
Bob

Antworten:


7

Unlocker behauptet, dass es Ihnen diese Fähigkeit gibt:

  1. Klicken Sie einfach mit der rechten Maustaste auf den Ordner oder die Datei und wählen Sie Unlocker

    Schritt 1

  2. Wenn der Ordner oder die Datei gesperrt ist, wird ein Fenster mit Schließfächern angezeigt

    Schritt 2

  3. Einfach anklicken Unlock Allund fertig!

Ich bin nicht sicher, ob es die Verwendung über die Befehlszeile unterstützt.

Der FileAssassin von MalwareByte führt ähnliche Aktionen aus und unterstützt die Verwendung über die Befehlszeile. Daher sollten Sie in der Lage sein, das Skript ganz einfach zu erstellen.

FileAssassin's Schalter


Danke techie007, das habe ich wohl verpasst. Mir ist aufgefallen, dass Unlocker manchmal meine Dateien übersieht (ProcessExplorer nicht). Ein zweites Problem ist, wenn ich Dateien programmgesteuert entsperren oder freigeben möchte (z. B. würde ein Befehlszeilentool in diese Richtung helfen).
Amelio Vazquez-Reina

@intrpc Nun, ich habe einen weiteren (befehlszeilenfreundlichen) Vorschlag hinzugefügt. :)
ƬᴇcƬᴇιʜ007

1
Vorsicht, Unlocker wird heutzutage mit Malware ausgeliefert.
Joshua Hanley

10

Danke dafür. Es gab einige Probleme mit Handles für geöffnete Dateien, die dazu führten, dass das Auschecken von Git in unseren Windows-basierten Jenkins-Jobs fehlschlug. Auf diese Weise konnte das Problem problemlos behoben werden. Ich werde die Grundlagen der Technik rausschmeißen:

  1. Installieren Sie Handle.exe auf dem Erstellungsknoten. Ich heruntergeladen es von hier http://technet.microsoft.com/en-us/sysinternals/bb896655 , es dekomprimiert und fiel Handle.exe unter C: \ Windows \ System32 , um sicherzustellen , dass es auf dem Standard - % PATH% verfügbar wäre

  2. Installieren Sie das Jenkins pre-scm-buildstep-Plugin: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep . Auf diese Weise können wir Operationen definieren, bevor das Git-Plugin nach potenziell gesperrten Dateien sucht.

  3. Implementierte den folgenden Batch-Befehl als Pre-Scm-Build-Schritt:

    @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
    

Es scheint gut zu funktionieren und reduziert auf jeden Fall Fehlschläge. Ich stelle auch ein paar Fallstricke fest, die ich durchgearbeitet habe:

  • Handler.exe verfügt über eine EULA, die beim ersten Ausführen akzeptiert werden muss. Wenn Sie Ihren Jenkins-Agenten als Dienst im Kontext "Lokales System" ausführen, ist dies problematisch, da Sie sich nicht als dieser Benutzer anmelden und ihn manuell akzeptieren können. Als wir versuchten, es über den Jenkins-Job auszuführen, wartete der Prozess nur auf Benutzereingaben, und es dauerte einige Minuten, um herauszufinden, warum. Ich habe dieses Problem gelöst, indem ich es über den Jenkins-Job mit dem Flag / accepteula ausgeführt habe, und ich empfehle jedem, der dies als automatisierten Prozess implementiert, dasselbe zu tun. Dies ist eine Registrierungseinstellung unter HKEY_CURRENT_USER \ Software \ Sysinternals \ Handle. Sie können sie auch über regedit.exe festlegen und deaktivieren, wenn Sie sie für einen bestimmten Benutzer bearbeiten müssen. Die Befehlszeilenoption schien jedoch am einfachsten zu sein.

  • Das Jenkins-Batch-Step-Plugin führt Batch-Code wie in einem Skript und nicht als Befehlszeilenanweisung aus. Beachten Sie die Escapezeichen (z. B. %% i, ^ |).

Vielen Dank!


Kann jemand genauer erklären, was %% i, j usw. ist?
c4sh

Dies könnte helfen, die Syntax des Batch-Befehls zu verstehen: robvanderwoude.com/ntfortokens.php
c4sh

Wie haben Sie die Tatsache gelöst, dass handle.exe als Administrator ausgeführt werden muss, während wir es von einem Jenkins-Benutzer ausführen, der kein Administrator ist?
c4sh

8

Wir verwenden das folgende Snippet, um die Dateizugriffsnummer von Benutzern auf unseren Server zu schließen. Möglicherweise können Sie es für Ihre Verwendung ändern.

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

Danke @Brendan. Ich denke, Ihr Code wurde nicht richtig formatiert. Ihre Antwort sieht interessant aus. Wenn Sie also nichts dagegen haben, sie zu bearbeiten, empfehle ich Ihnen, Ihre Codezeilen auszuwählen und dann auf die Schaltfläche mit den beiden geschweiften Armbändern zu klicken. Dadurch wird Ihr Snippet in lesbaren Code umgewandelt.
Amelio Vazquez-Reina

5

Ich erstelle diese kleine Batch-Datei, um automatisch alle Sperren für die XML-Datei durch meine Eclipse freizugeben

@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

Sie müssen das Handle- Dienstprogramm von der Microsoft-Site und das grep- Dienstprogramm von GnuWin32 herunterladen

Wenn Sie keinen Filter nach Dateityp benötigen, können Sie den grep-Teil wie folgt überspringen:

@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

Wenn Sie Sperren nicht nach einem bestimmten Programm filtern müssen, entfernen Sie einfach den Eclipse-Prozessfilter:

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

Denken Sie daran, e:\git\durch Ihren Ordnerpfad zu ersetzen .


4

Wenn Sie PSTools verwenden , werden alle geöffneten Dateien rekursiv geschlossen:

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

Beachten Sie, dass c:\path\toDatabase\das Laufwerk C: eingeschaltet ist \\serverName, nicht Ihr lokaler Computer. Das war mir zunächst unklar, also dachte ich, ich würde darauf hinweisen.

Dies ist ein Brute-Force-Ansatz, bei dem fast garantiert Daten verloren gehen. Gehen Sie daher vorsichtig vor.

Wir haben eine schlecht gepflasterte Access-Datenbank, die unser Unternehmen regelmässig in die Knie zwingt (ich musste sie erst gestern dreimal reparieren).

Der Typ, der dies normalerweise erledigt, ist ein paar Wochen im Urlaub, und seine Anweisungen basieren auf einer Benutzeroberfläche (Start> Computer> Verwalten> Computerverwaltung (lokal)> Mit einem anderen Computer verbinden> Systemprogramme> Freigegebene Ordner> Dateien öffnen> Schließen) Dateien öffnen). WEG zu viele Klicks, wenn ich einfach den obigen Befehl ausführen und das gesamte Unternehmen aus allen Datenbankdateien herauswerfen und den Compact & Repair-Prozess starten kann (an dem ich auch mit Brute-Force-Skripten arbeite).

Der Trick besteht darin, den Leuten einen Schritt voraus zu sein, die sich sofort wieder mit der Datenbank verbinden, sobald sie ausfällt. Sie sind so daran gewöhnt, dass sie keinen Bug dagegen einreichen, sondern einfach die Datenbank weiter hämmern, bis sie wieder reinkommen. Ich boote sie einfach weiter aus, bis ich die drei Dutzend komprimiert und repariert habe Dateien, aus denen die Datenbank besteht.


4

Wenn Sie über Dateien sprechen, die über eine SMB-Freigabe auf einem Windows-Dateiserver (Server 2012 oder neuer) geöffnet werden, finden Sie hier die PowerShell-Antwort:

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

Auf einem älteren Windows-Dateiserver ist es openfiles.exe /disconnect.

Für ein lokales Systemdatei-Handle verwende ich am besten Sysinternals handle.exe



2

Unlocker kann auch im stillen Modus ausgeführt werden.

So entsperren Sie beispielsweise alle Dateien im Jenkins-Arbeitsbereich:

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

Dann können Sie sicher Arbeitsbereichsdateien löschen:

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

0

Sie können Powershell verwenden , um diese Dinge zu tun:

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
        }
    }
}

Weitere Informationen erhalten Sie von Thomas Ardal hier: https://thomasardal.com/de/deleting-contents-of-a-folder-containing-fileses-with-open-file-handles-using-powershell/

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.