سؤال

باستخدام في 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
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top