Як програмно закрити всі ручки файлів у певній папці?


18

Мені було цікаво, чи є інструмент командного рядка, який дозволяє мені закривати всі ручки файлів, відкриті під певною папкою.

Я спробував ProcessExplorer , Unlocker та подібні інструменти, але вони пропонують інтерфейс GUI і не корисні в середовищі програмування

Ідеальне рішення на Python, cmd або PowerShell.


Пам'ятайте, що примусове закриття ручки файлу може призвести до збою програми, що використовує цю ручку.
Гаррі Джонстон

1
@HarryJohnston Гірше, що ти можеш спричинити різного роду пошкодження файлів до тих пір, поки програма відкрита: technet.microsoft.com/en-us/magazine/…
Боб

Відповіді:


7

Unlocker стверджує, що це дає вам таку можливість:

  1. Просто клацніть правою кнопкою миші папку чи файл та виберіть Unlocker

    Крок 1

  2. Якщо папка або файл заблокований, з'явиться вікно з переліком шаф

    Крок2

  3. Просто натисніть, Unlock Allі ви закінчите!

Я не впевнений, чи підтримує він використання командного рядка.

FileASSASSIN MalwareByte в виконує аналогічні дії, і робить підтримку використання командного рядка, так що ви повинні бути в змозі сценарію це досить легко.

Перемикачі FileAssassin


Дякую techie007, я думаю, я пропустив це. Я помітив, що іноді Unlocker пропускає мої файли (ProcessExplorer не робить). Друга проблема - якщо я хочу розблокувати або випустити файли програмно (наприклад, інструмент командного рядка допоможе в цьому напрямку).
Амеліо Васкес-Рейна

@intrpc Там ви додали ще одну пропозицію (зручна для командного рядка). :)
Ƭᴇcʜιᴇ007

1
Обережно, Unlocker поставляється разом із шкідливим програмним забезпеченням.
Джошуа Ханлі

10

Дякую за це У нас виникли деякі проблеми з відкритими ручками файлів, які спричинили збій роботи каси в наших робочих місцях на базі ОС Дженкінс, і це допомогло усунути проблему. Я викину основи техніки:

  1. Встановіть Handle.exe на вузлі збірки. Я завантажив його звідси http://technet.microsoft.com/en-us/sysinternals/bb896655 , розпакував його та видалив Handle.exe під C: \ Windows \ System32, щоб переконатися, що він буде доступний за замовчуванням% PATH%

  2. Встановіть плагін Jenkins pre-scm-buildstep: https://wiki.jenkins-ci.org/display/JENKINS/pre-scm-buildstep . Це дозволяє нам визначити операції до того, як плагін git почав досягати потенційно заблокованих файлів.

  3. Реалізовано таку командну пакетну команду як етап попереднього збирання:

    @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
    

Це, здається, працює добре і, безумовно, скорочує помилкові збої. Я також відзначу кілька пар, через які я працював:

  • Handler.exe має правові ліцензії, які повинні бути прийняті під час першого запуску. Якщо ви використовуєте свого агента Jenkins як службу в контексті локальної системи, це проблематично, оскільки ви не можете увійти як цей користувач і прийняти його вручну. Коли ми спробували запустити його з роботи Дженкінса, процес просто завис, очікуючи на введення користувачем, і знадобилося кілька хвилин, щоб з'ясувати, чому. Я вирішив це, запустивши його із завдання Дженкінса, використовуючи прапор / acceptteula, і рекомендую всім, хто реалізує це як автоматизований процес, зробити те саме. Це може бути налаштування реєстру в HKEY_CURRENT_USER \ Software \ Sysinternals \ Handle, і ви також можете встановити та зняти його через regedit.exe, якщо вам потрібно маніпулювати ним для конкретного користувача, але варіант командного рядка видався найпростішим.

  • Плагін кроку Jenkins Batch виконує пакетний код так, ніби він був у сценарії, а не як директива командного рядка. Помічайте втечі (наприклад, %% i, ^ |).

Спасибі!


Намагаючись отримати синтаксис цього, хтось може надати більш детальну інформацію про те, що є %% i, j тощо?
c4sh

Це може допомогти зрозуміти синтаксис команди пакетного: robvanderwoude.com/ntfortokens.php
c4sh

Як ви, хлопці, вирішили той факт, що handle.exe потрібно запускати як адміністратор, тоді як ми запускаємо його від користувача Jenkins, який не є адміністратором?
c4sh

8

Ми використовуємо наступний фрагмент, щоб закрити обробку файлів від користувачів на нашому сервері. Ви можете змінити його для використання.

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

Дякую @Brendan. Я думаю, що ваш код не відформатований належним чином. Ваша відповідь виглядає цікаво, тому, якщо ви не проти редагувати її, я б запропонував вам вибрати рядки коду, а потім натиснути кнопку з двома фігурними браслетами. Це перетворить ваш фрагмент у читабельний код.
Амеліо Васкес-Рейна

5

Я створюю цей маленький пакетний файл, щоб автоматично випустити всі замки у файл XML моїм затемненням

@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

Вам потрібно завантажити утиліту ручки з сайту Microsoft, а утиліту grep - з GnuWin32

Якщо вам не потрібен фільтр за типом файлу, ви можете пропустити подібну частину:

@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

Або якщо вам не потрібно фільтрувати замки за певною програмою, просто видаліть фільтр процесу затемнення:

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

Не забудьте замінити e:\git\шлях до папки.


5

Якщо ви говорите про обробку файлів, відкритих за допомогою спільного доступу SMB на файловому сервері Windows (Server 2012 або новіші), ось відповідь PowerShell:

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

На старшому файловому сервері Windows це openfiles.exe /disconnect.

Для обробки локальних системних файлів найкращим способом я знайшов використання Sysinternals handle.exe


4

Якщо ви використовуєте PSTools , це змусить рекурсивно закривати всі відкриті файли:

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

Зверніть увагу, що c:\path\toDatabase\це диск C: \\serverNameне ваш локальний апарат. Спочатку це було мені незрозуміло, тому я подумав, що я зазначу це.

Це грубий підхід, який майже гарантовано втрачає дані, тому використовуйте їх з обережністю.

У нас є погано оброблена база даних Access, яка буквально підводить нашу компанію на коліна регулярно (мені довелося це виправити тричі лише вчора).

Хлопець, який зазвичай справляється з цим, перебуває у відпустці на кілька тижнів, і його вказівки використовують підхід на основі інтерфейсу користувача (Пуск> Комп'ютер> Керування> Управління комп'ютером (Місцевий)> Підключення до іншого комп'ютера> Системні інструменти> Спільні папки> Відкриті файли> Закрити Відкрити файли). БУДЬ занадто багато клацань, коли я можу просто запустити вищевказану команду і вигнати всю компанію з усіх файлів баз даних і запустити процес Compact & Repair (над яким я також працюю на грубому сценарії).

Хитрість полягає в тому, щоб випередити людей, які негайно починають підключатися до бази даних, як тільки вона знижується. Вони настільки звикли до цього, що їм не спадає на думку подавати помилку проти цього, вони просто продовжують забивати базу даних, поки вони не повернуться. Я просто продовжую завантажувати їх, поки я не ущільнив і не відремонтував три десятки. файли, що складають базу даних.


3

Я віддаю перевагу http://lockhunter.com, оскільки він підтримує і графічний інтерфейс, і інтерфейс командного рядка, і в багатьох випадках вдалося видалити файли, які не вдалося видалити Unlocker.


2

Unlocker також може працювати в беззвучному режимі.

Наприклад, щоб розблокувати всі файли всередині робочої області Jenkins:

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

Тоді ви можете безпечно видалити файли робочої області:

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

0

Ви можете використовувати Powershell для цього:

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

Для отримання детальної інформації зверніться до Томаса Ардала тут: https://thomasardal.com/deleting-contents-of-a-folder-contain-files-with-open-file-handles-using-powershell/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.