Script di PowerShell per controllare un’applicazione che blocca un file?

Usando in PowerShell, come posso verificare se un’applicazione blocca un file?

Mi piace verificare quale processo / applicazione sta utilizzando il file, in modo che possa chiuderlo.

Puoi farlo con lo strumento SysInternals handle.exe . Prova qualcosa del genere:

PS> $handleOut = handle PS> foreach ($line in $handleOut) { if ($line -match '\S+\spid:') { $exe = $line } elseif ($line -match 'C:\\Windows\\Fonts\\segoeui\.ttf') { "$exe - $line" } } MSASCui.exe pid: 5608 ACME\hillr - 568: File (---) C:\Windows\Fonts\segoeui.ttf ... 

Dovresti essere in grado di utilizzare il comando openfiles dalla riga di comando normale o da PowerShell.

Lo strumento integrato openfiles può essere utilizzato per le condivisioni di file o per i file locali. Per i file locali, è necessario accendere lo strumento e riavviare la macchina (di nuovo, solo per il primo utilizzo). Credo che il comando per triggersre questa funzione sia:

 openfiles /local on 

Ad esempio (funziona su Windows Vista x64):

 openfiles /query | find "chrome.exe" 

Questo restituisce correttamente gli handle di file associati a Chrome. Puoi anche passare un nome di file per vedere il processo che sta attualmente accedendo a quel file.

Questo potrebbe aiutarti: usa PowerShell per scoprire quale processo blocca un file . Analizza la proprietà System.Diagnostics.ProcessModuleCollection Module di ogni processo e cerca il percorso del file bloccato:

 $lockedFile="C:\Windows\System32\wshtcpip.dll" Get-Process | foreach{$processVar = $_;$_.Modules | foreach{if($_.FileName -eq $lockedFile){$processVar.Name + " PID:" + $processVar.id}}} 

È ansible trovare una soluzione utilizzando l’utilità Handle di Sysinternal .

Ho dovuto modificare il codice (leggermente) per lavorare con PowerShell 2.0:

 #/* http://jdhitsolutions.com/blog/powershell/3744/friday-fun-find-file-locking-process-with-powershell/ */ Function Get-LockingProcess { [cmdletbinding()] Param( [Parameter(Position=0, Mandatory=$True, HelpMessage="What is the path or filename? You can enter a partial name without wildcards")] [Alias("name")] [ValidateNotNullorEmpty()] [string]$Path ) # Define the path to Handle.exe # //$Handle = "G:\Sysinternals\handle.exe" $Handle = "C:\tmp\handle.exe" # //[regex]$matchPattern = "(?\w+\.\w+)\s+pid:\s+(?\b(\d+)\b)\s+type:\s+(?\w+)\s+\w+:\s+(?.*)" # //[regex]$matchPattern = "(?\w+\.\w+)\s+pid:\s+(?\d+)\s+type:\s+(?\w+)\s+\w+:\s+(?.*)" [regex]$matchPattern = "(?\w+\.\w+)\s+pid:\s+(?\d+)\s+type:\s+(?\w+)\s+(?\.+)\s+\w+:\s+(?.*)" $data = &$handle -u $path $MyMatches = $matchPattern.Matches( $data ) # //if ($MyMatches.value) { if ($MyMatches.count) { $MyMatches | foreach { [pscustomobject]@{ FullName = $_.groups["Name"].value Name = $_.groups["Name"].value.split(".")[0] ID = $_.groups["PID"].value Type = $_.groups["Type"].value User = $_.groups["User"].value.trim() Path = $_.groups["Path"].value toString = "pid: $($_.groups["PID"].value), user: $($_.groups["User"].value), image: $($_.groups["Name"].value)" } #hashtable } #foreach } #if data else { Write-Warning "No matching handles found" } } #end function 

Esempio:

 PS C:\tmp> . .\Get-LockingProcess.ps1 PS C:\tmp> Get-LockingProcess C:\tmp\foo.txt Name Value ---- ----- ID 2140 FullName WINWORD.EXE toString pid: 2140, user: J17\Administrator, image: WINWORD.EXE Path C:\tmp\foo.txt Type File User J17\Administrator Name WINWORD PS C:\tmp> 

Ho visto una buona soluzione in Rilevamento file bloccato che utilizza solo classi framework PowerShell e .NET:

 function TestFileLock { ## Attempts to open a file and trap the resulting error if the file is already open/locked param ([string]$filePath ) $filelocked = $false $fileInfo = New-Object System.IO.FileInfo $filePath trap { Set-Variable -name filelocked -value $true -scope 1 continue } $fileStream = $fileInfo.Open( [System.IO.FileMode]::OpenOrCreate,[System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None ) if ($fileStream) { $fileStream.Close() } $obj = New-Object Object $obj | Add-Member Noteproperty FilePath -value $filePath $obj | Add-Member Noteproperty IsLocked -value $filelocked $obj } 

Mi piace il prompt dei comandi (CMD) e può essere utilizzato anche in PowerShell:

 tasklist /m  

Basta notare che non è ansible inserire il percorso completo del file DLL. Solo il nome è abbastanza buono.

Se si modifica leggermente la funzione sopra riportata come di seguito, verrà restituito True o False (sarà necessario eseguire con i diritti di amministratore completi), ad es.

PS> TestFileLock “c: \ pagefile.sys”

 function TestFileLock { ## Attempts to open a file and trap the resulting error if the file is already open/locked param ([string]$filePath ) $filelocked = $false $fileInfo = New-Object System.IO.FileInfo $filePath trap { Set-Variable -name Filelocked -value $true -scope 1 continue } $fileStream = $fileInfo.Open( [System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None ) if ($fileStream) { $fileStream.Close() } $filelocked }