PowerShell Script للتحقق من تطبيق يقوم بإغلاق ملف؟
-
12-09-2019 - |
سؤال
باستخدام في PowerShell، كيف يمكنني التحقق مما إذا كان التطبيق قفل ملف؟
أحب التحقق من العملية / التطبيق باستخدام الملف، بحيث يمكنني إغلاقه.
المحلول
يمكنك القيام بذلك مع أداة sysinternals handle.exe.. وبعد جرب شيئا مثل هذا:
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
...
نصائح أخرى
يجب أن تكون قادرا على استخدام OpenFiles Command. من سطر الأوامر العادي أو من PowerShell.
يمكن استخدام أداة OpenFiles المدمجة في رسوم الملفات أو الملفات المحلية. بالنسبة للملفات المحلية، يجب عليك تشغيل الأداة وأعد تشغيل الجهاز (مرة أخرى، فقط لأول مرة). أعتقد أن الأمر لتحويل هذه الميزة إليه هو:
openfiles /local on
على سبيل المثال (يعمل على نظام التشغيل Windows Vista X64):
openfiles /query | find "chrome.exe"
أن يؤدي ذلك بنجاح مقابض الملفات المرتبطة بالكروم. يمكنك أيضا تمرير اسم ملف لمعرفة العملية التي تصل حاليا إلى هذا الملف.
هذا يمكن أن يساعدك: استخدم PowerShell لمعرفة أي عملية أقفال ملف. وبعد يوزع System.Diagnostics.ProcessModulecollection الخاصية خاصية كل عملية ويبحث عن مسار الملف من الملف المؤمن:
$lockedFile="C:\Windows\System32\wshtcpip.dll"
Get-Process | foreach{$processVar = $_;$_.Modules | foreach{if($_.FileName -eq $lockedFile){$processVar.Name + " PID:" + $processVar.id}}}
يمكنك العثور على حل باستخدام sysinternal.'س مقبض جدوى.
اضطررت لتعديل التعليمات البرمجية (قليلا) للعمل مع 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 = "(?<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
مثال:
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>
لقد رأيت حل لطيف في اكتشاف الملف المقفل يستخدم فئات PowerShell و .NET Framework فقط:
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
}
أنا أحب ما هو موجه الأوامر (CMD)، ويمكن استخدامه في PowerShell كذلك:
tasklist /m <dllName>
فقط لاحظ أنه لا يمكنك إدخال المسار الكامل لملف DLL. فقط الاسم جيد بما فيه الكفاية.
إذا قمت بتعديل الوظيفة المذكورة أعلاه بشكل طفيف مثل، فسوف ترجع True أو False (ستحتاج إلى تنفيذ حقوق المسؤول الكامل) على سبيل المثال الاستخدام:
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
}