Jak programowo zamknąć wszystkie uchwyty plików w danym folderze?

18

Zastanawiałem się, czy istnieje narzędzie wiersza polecenia, które pozwala mi zamykać wszystkie uchwyty plików, które są otwarte w określonym folderze.

Próbowałem ProcessExplorer , Unlocker i podobnych narzędzi, ale oferują one interfejs GUI i nie są przydatne w środowisku programowania

Idealne byłoby rozwiązanie dla Pythona, cmd lub PowerShell.

Amelio Vazquez-Reina
źródło
Pamiętaj, że wymuszone zamknięcie uchwytu pliku może spowodować awarię programu używającego tego uchwytu.
Harry Johnston,
1
@HarryJohnston Gorzej, możesz skończyć powodując wszelkiego rodzaju uszkodzenia plików, o ile program jest otwarty: technet.microsoft.com/en-us/magazine/…
Bob

Odpowiedzi:

7

Unlocker twierdzi, że daje ci tę zdolność:

  1. Wystarczy kliknąć folder lub plik prawym przyciskiem myszy i wybrać Unlocker

    Krok 1

  2. Jeśli folder lub plik jest zablokowany, pojawi się okno szafek

    Krok 2

  3. Po prostu kliknij Unlock Alli gotowe!

Nie jestem pewien, czy obsługuje użycie wiersza polecenia.

MalwareByte za FileASSASSIN wykonuje podobne działania, a nie pomocy użycia wiersza polecenia, więc powinno być możliwe do skryptu to dość łatwo.

FileAssassin's Switches

Ƭᴇcʜιᴇ007
źródło
Dzięki techie007, chyba to przegapiłem. Zauważyłem, że Unlocker czasami pomija moje pliki (ProcessExplorer nie). Drugim problemem jest to, czy chcę programowo odblokować lub zwolnić pliki (np. Narzędzie wiersza poleceń pomogłoby w tym kierunku).
Amelio Vazquez-Reina,
@intrpc Proszę bardzo, dodałem kolejną (przyjazną dla wiersza poleceń) sugestię. :)
Ƭᴇcʜιᴇ007
1
Ostrożnie, Unlocker jest obecnie dostarczany wraz ze złośliwym oprogramowaniem.
Joshua Hanley
10

Dzięki za to. Występują problemy z otwartymi uchwytami plików, które powodują awarie git w naszych zadaniach Jenkins opartych na systemie Windows, co pomogło ręcznie rozwiązać problem. Wyrzucę podstawy techniki:

  1. Zainstaluj Handle.exe w węźle kompilacji. Pobrałem go stąd http://technet.microsoft.com/en-us/sysinternals/bb896655 , rozpakowałem go i upuściłem Handle.exe pod C: \ Windows \ System32, aby upewnić się, że będzie dostępny na domyślnym% PATH%

  2. Zainstaluj wtyczkę Jenkins pre-scm-buildstep: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep . To pozwala nam zdefiniować operacje, zanim wtyczka git zacznie sięgać po potencjalnie zablokowane pliki.

  3. Zaimplementowano następujące polecenie wsadowe jako krok kompilacji przed 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
    

Wygląda na to, że działa dobrze i zdecydowanie ogranicza fałszywe awarie. Zwrócę też uwagę na kilka błędów, przez które pracowałem:

  • Program Handler.exe ma umowę EULA, którą należy zaakceptować przy pierwszym uruchomieniu. Jeśli używasz agenta Jenkins jako usługi w kontekście systemu lokalnego, jest to problematyczne, ponieważ nie możesz zalogować się jako ten użytkownik i zaakceptować go ręcznie. Kiedy próbowaliśmy uruchomić go z zadania Jenkins, proces po prostu zawiesił się, czekając na dane wejściowe użytkownika i zajęło kilka minut, aby dowiedzieć się, dlaczego. Rozwiązałem ten problem, uruchamiając go z zadania Jenkins przy użyciu flagi / accepteula i polecam wszystkim, którzy wdrażają to jako zautomatyzowany proces, robią to samo. Jest to ustawienie rejestru pod HKEY_CURRENT_USER \ Software \ Sysinternals \ Handle i możesz go również ustawić i rozbroić za pomocą regedit.exe, jeśli chcesz manipulować nim dla konkretnego użytkownika, ale opcja wiersza poleceń wydawała się najłatwiejsza.

  • Wtyczka krokowa Jenkins Batch wykonuje kod wsadowy tak, jakby był w skrypcie, a nie jako dyrektywa wiersza poleceń. Zwróć uwagę na ucieczki (np. %% i, ^ |).

Dzięki!

Thomas Boyles
źródło
Walcząc o uzyskanie składni tego, czy ktoś może podać więcej szczegółów na temat %% i, j itd?
c4sh
Może to pomóc w zrozumieniu składni komendy wsadowej: robvanderwoude.com/ntfortokens.php
c4sh
Jak rozwiązaliście fakt, że uchwyt.exe musi działać jako administrator, podczas gdy my uruchamiamy go od użytkownika Jenkins, który nie jest administratorem?
c4sh,
8

Używamy następującego fragmentu kodu, aby zamknąć uchwyt pliku od użytkowników do naszego serwera. Możesz go zmodyfikować do własnego użytku.

rem close all network files that are locked
for /f "skip=4 tokens=1" %%a in ('net files') do net files %%a /close
Brendan
źródło
Dzięki @Brendan. Myślę, że twój kod nie został poprawnie sformatowany. Twoja odpowiedź wygląda interesująco, więc jeśli nie masz nic przeciwko edycji, sugeruję wybranie linii kodu, a następnie kliknięcie przycisku z dwiema kręconymi bransoletkami. To zmieni Twój fragment kodu w czytelny kod.
Amelio Vazquez-Reina,
5

Tworzę ten mały plik wsadowy, aby automatycznie zwolnić wszystkie blokady do pliku xml przez moje zaćmienie

@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

Musisz pobrać narzędzie uchwyt z witryny Microsoft i narzędzie grep z GnuWin32

Jeśli nie potrzebujesz filtrować według typu pliku, możesz pominąć część grep w następujący sposób:

@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

Lub jeśli nie musisz filtrować blokad według określonego programu, po prostu usuń filtr procesu zaćmienia:

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

Pamiętaj, aby zastąpić e:\git\ścieżką folderu.

Coolersport
źródło
5

Jeśli mówisz o uchwytach plików otwartych przez udział SMB na serwerze plików Windows (Server 2012 lub nowszy), oto odpowiedź PowerShell:

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

Na starszym serwerze plików Windows tak jest openfiles.exe /disconnect.

W przypadku lokalnego uchwytu pliku systemowego najlepszym sposobem, jaki znalazłem, jest użycie narzędzia Sysinternals handle.exe

Joshua Hanley
źródło
4

Jeśli używasz PSTools , wymusi to zamknięcie wszystkich otwartych plików rekurencyjnie:

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

Pamiętaj, że c:\path\toDatabase\jest włączony dysk C:, a \\serverNamenie komputer lokalny. Na początku było to dla mnie niejasne, więc pomyślałem, że zwrócę na to uwagę.

To brutalna metoda, która prawie gwarantuje utratę danych, więc używaj jej ostrożnie.

Mamy źle skompletowaną bazę danych Access, która dosłownie rzuca naszą firmę na kolana (musiałem to naprawić trzy razy wczoraj).

Facet, który normalnie sobie z tym radzi, jest na urlopie przez kilka tygodni, a jego instrukcje wykorzystują podejście oparte na interfejsie użytkownika (Start> Komputer> Zarządzaj> Zarządzanie komputerem (lokalne)> Połącz z innym komputerem> Narzędzia systemowe> Foldery udostępnione> Otwórz pliki> Zamknij Otwórz pliki). ODPOWIEDŹ zbyt wiele kliknięć, gdy mogę po prostu uruchomić powyższe polecenie i wykopać całą firmę ze wszystkich plików bazy danych i rozpocząć proces Kompaktowania i naprawy (nad którym pracuję również przy użyciu skryptu brute force).

Sztuką jest wyprzedzanie ludzi, którzy natychmiast zaczynają ponownie łączyć się z bazą danych, gdy tylko się zepsuje. Są do tego tak przyzwyczajeni, że nie przychodzi im do głowy zgłaszać błąd, po prostu wbijają bazę danych, dopóki nie wrócą. Po prostu je uruchamiam, dopóki nie spakuję i nie naprawię trzech tuzinów pliki tworzące bazę danych.

delliottg
źródło
3

Wolę http://lockhunter.com, ponieważ obsługuje zarówno GUI, jak i interfejs wiersza poleceń, aw wielu przypadkach był w stanie usunąć pliki, które nie mogły zostać usunięte przez Unlocker.

Vladimir Reshetnikov
źródło
2

Unlocker może również działać w trybie cichym.

Na przykład, aby odblokować wszystkie pliki w obszarze roboczym Jenkins:

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

Następnie możesz bezpiecznie usunąć pliki obszaru roboczego:

del "%WORKSPACE%\*.*" /s /q
Noam Manos
źródło
0

Możesz użyć programu Powershell, aby wykonać te czynności:

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

Aby uzyskać więcej informacji, zapoznaj się z Thomasem Ardalem tutaj: https://thomasardal.com/deleting-contents-of-a-folder-containing-files-with-open-file-handles-using-powershell/

Abhi
źródło