2016-08-28 8 views
2

Я пытаюсь написать сценарий PowerShell, который проверяет, не заблокирован ли какой-либо из файлов в определенной папке каким-либо процессом; if true, только затем удалите папку.Как проверить, нет ли в папке каких-либо файлов, заблокированных каким-либо процессом?

Один из способов - проверить блокировки на каждом файле, открыв их в режиме RW итеративно - посмотреть, не произошло ли исключение. Но это слишком громоздко.

Есть ли способ проверить одно и то же для папки? Я пытался использовать Remove-Item с флагом -WhatIf, но это бесполезно, потому что команда не возвращает никакого значения - и не обнаружила заблокированные файлы. Если я попытаюсь запустить Remove-Item без флага, чтобы искать исключение, тогда он удаляет только свободные файлы, тогда как я хочу иметь условие «Все» или «Нет».

+0

Вы всегда можете получить Restart Manager, чтобы проверить блокировки для вас, но это все еще несколько громоздко. – Neil

ответ

2

Пока вы не собираетесь распространять решение, вы можете использовать handle.exe. Он показывает все используемые файлы и папки и кто их использует.

$path = "C:\Users\frode\Desktop\Test folder" 

(.\handle64.exe /accepteula $path /nobanner) -match 'File' 
explorer.exe  pid: 1888 type: File   F3C: C:\Users\frode\Desktop\Test folder 
explorer.exe  pid: 1888 type: File   2E54: C:\Users\frode\Desktop\Test folder 
notepad.exe  pid: 2788 type: File   38: C:\Users\frode\Desktop\Test folder 
WINWORD.EXE  pid: 2780 type: File   40: C:\Users\frode\Desktop\Test folder 
WINWORD.EXE  pid: 2780 type: File   6FC: C:\Users\frode\Desktop\Test folder\New Microsoft Word-dokument.docx 

Если вы хотите только да/нет ответа вы можете использовать, если тест и -match, чтобы увидеть, если возврат каких-либо результатов.

if((.\handle64.exe /accepteula $path /nobanner) -match 'File') { "IN USE, ABORT MISSION!" } 

Обычно вы можете удалить папку, даже если explorer.exe просматривает внутри него, так что вы можете, как правило, исключает этот процесс из результатов:

if((.\handle64.exe /accepteula $path /nobanner) -match 'File' -notmatch 'explorer.exe') { "IN USE, ABORT MISSION!" } 
2

Если вы не хотите установить ручку , вы можете посмотреть, какой процесс выполняется в данном каталоге или подкаталоге.

$lockedFolder="C:\Windows\System32" 
Get-Process | % { 
    $processVar = $_ 
    $_.Modules | %{ 
    if($_.FileName -like "$lockedFolder*"){ 
     $processVar.Name + " PID:" + $processVar.id + " FullName: " + $_.FileName 
    } 
    } 
} 
0

Это не полное решение, но отправная точка, на которой вы можете построить.

У меня есть txt-файл под названием «demo.txt» в разделе «E: \ Work \ Powershell \ scripts \ demo». И я использую Notepad.exe, чтобы открыть его. В этом случае я не смогу удалить папку «demo», пока не закрою блокнот.

Вам необходимо запросить класс «Win32_process», чтобы понять, использует ли блокнот этот файл.

Get-WmiObject win32_process | where {$_.name -eq 'notepad.exe'} 

В выходе выше командлета, то «CommandLine» свойство , покажет вам, какие файлы в настоящее время используются этим процессом.

enter image description here

Вы, возможно, придется перебрать это, чтобы иметь полное решение для вашей проблемы.

Некоторые процессы, такие как «chrome.exe», будут иметь огромный список под свойством «CommandLine». Поскольку chrome или iExplorer не будут препятствовать удалению папки при открытии файла, вы можете игнорировать эти процессы ,

Примечание: «FileName» в разделе «(Get-Process) .Modules» предоставляет вам только PATH, где вы можете найти «notepad.exe» (то есть E: \ Work \ Powershell \ scripts \ demo)

+0

Это должно в значительной степени работать: $ location = 'E: \ Work \ Powershell \ scripts \ demo' Get-WmiObject Win32_process | где {$ _. commandline -like "* $ location *"} | выбрать имя –