Powershell-Skript, eine Anwendung zu überprüfen, die eine Datei ist Sperre?
-
12-09-2019 - |
Frage
Unter Verwendung in Powershell, wie kann ich überprüfen, ob eine Anwendung eine Datei blockiert?
Ich mag, welcher Prozess überprüfen / Anwendung die Datei verwendet, so dass ich es schließen kann.
Lösung
Sie können dies tun, mit dem SysInternals Werkzeug handle.exe . Probieren Sie etwas wie folgt aus:
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
...
Andere Tipps
Es sollte möglich sein, die openfiles Befehl von entweder der regulären Befehlszeile oder Powershell.
Das openfiles integrierte Tool für Dateifreigaben oder für lokale Dateien verwendet werden. Für lokale Dateien müssen Sie auf dem Werkzeug drehen und die Maschine neu gestartet werden (auch hier nur für die erste Verwendung). Ich glaube, den Befehl diese Funktion zu aktivieren ist:
openfiles /local on
Zum Beispiel (funktioniert unter Windows Vista x64):
openfiles /query | find "chrome.exe"
Das erfolgreich zurückgegeben Dateihandles mit Chrome verbunden. Sie können auch in einem Dateinamen übergeben der Prozess zur Zeit den Zugriff auf diese Datei zu sehen.
Dies könnte helfen Ihnen: Verwenden Sie Powershell, um herauszufinden, welcher Prozess eine Datei sperrt. Es analysiert die System.Diagnostics.ProcessModuleCollection Module Eigenschaft jeden Prozess und es sieht für den Dateipfad der gesperrten Datei:
$lockedFile="C:\Windows\System32\wshtcpip.dll"
Get-Process | foreach{$processVar = $_;$_.Modules | foreach{if($_.FileName -eq $lockedFile){$processVar.Name + " PID:" + $processVar.id}}}
Sie können eine Lösung finden, mit Sysinternal 's Griff Dienstprogramm.
Ich hatte den Code (etwas) ändern mit Powershell arbeiten 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 = "(?<Name>\w+\.\w+)\s+pid:\s+(?<PID>\b(\d+)\b)\s+type:\s+(?<Type>\w+)\s+\w+:\s+(?<Path>.*)"
# //[regex]$matchPattern = "(?<Name>\w+\.\w+)\s+pid:\s+(?<PID>\d+)\s+type:\s+(?<Type>\w+)\s+\w+:\s+(?<Path>.*)"
# (?m) for multiline matching.
# It must be . (not \.) for user group.
[regex]$matchPattern = "(?m)^(?<Name>\w+\.\w+)\s+pid:\s+(?<PID>\d+)\s+type:\s+(?<Type>\w+)\s+(?<User>.+)\s+\w+:\s+(?<Path>.*)$"
# skip processing banner
$data = &$handle -u $path -nobanner
# join output for multi-line matching
$data = $data -join "`n"
$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
Beispiel:
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>
Ich habe eine schöne Lösung gesehen in Gesperrt Dateierkennung , die nur Powershell und .NET Framework-Klassen verwendet:
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
}
Ich mag, was die Eingabeaufforderung (CMD) hat, und es kann auch in Powershell verwendet werden:
tasklist /m <dllName>
Es genügt bemerken, dass Sie nicht den vollständigen Pfad der DLL-Datei eingeben. Nur der Name ist gut genug.
Wenn Sie die obige Funktion leicht ändern, wie unten, damit er zurückkehren wird Wahr oder Falsch (Sie müssen mit voller Admin-Rechten auszuführen) z.B. Verbrauch:
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
}