2009-06-05 15 views
32

पावरशेल में उपयोग करना, मैं कैसे जांच सकता हूं कि कोई एप्लिकेशन फ़ाइल लॉक कर रहा है या नहीं?PowerShell स्क्रिप्ट किसी फ़ाइल को लॉक करने वाले एप्लिकेशन को जांचने के लिए?

मुझे यह जांचना है कि कौन सी प्रक्रिया/एप्लिकेशन फ़ाइल का उपयोग कर रहा है, ताकि मैं इसे बंद कर सकूं।

उत्तर

28

आप इसे SysInternals tool 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 
... 
+7

धन्यवाद, मैं इसे आसान बनाने के लिए, हैंडल [फ़ाइल नाम] का उपयोग कर सकता हूं। –

+0

उसमें मजाक कहां है? :-) लेकिन हाँ, यह बहुत आसान होगा। –

+0

:(अभी भी समस्याएं हैं ... यह दिखाने के लिए शक्तिशाली नहीं है कि किसी निश्चित प्रक्रिया द्वारा फाइलें (यानी टेक्स्ट फाइलें) खोली गईं। –

9

आप नियमित कमांड लाइन या PowerShell से openfiles command का उपयोग करने में सक्षम होना चाहिए।

ओपनफाइल निर्मित टूल का उपयोग फ़ाइल शेयरों या स्थानीय फ़ाइलों के लिए किया जा सकता है। स्थानीय फाइलों के लिए, आपको टूल चालू करना होगा और मशीन को पुनरारंभ करना होगा (फिर, केवल पहली बार उपयोग के लिए)। मेरा मानना ​​है कि आदेश इस सुविधा को चालू करने के लिए है पर:

openfiles /local on 

उदाहरण के लिए (विंडोज   Vista x64 पर काम करता है):

openfiles /query | find "chrome.exe" 

कि सफलतापूर्वक फ़ाइल रिटर्न क्रोम के साथ जुड़े हैंडल। वर्तमान में उस फ़ाइल तक पहुंचने वाली प्रक्रिया को देखने के लिए आप फ़ाइल नाम में भी पास कर सकते हैं।

+0

मैं क्या देखते हैं कि आदेश बस उस से एक उपयोगकर्ता द्वारा खोला फ़ाइलों विश्लेषण करता है से एसएमबी शेयरों के माध्यम से रिमोट। यह आपको इस प्रक्रिया के बारे में कुछ भी नहीं बताएगा। – Joey

+0

आप इसे लिंक से नहीं बता सकते हैं, लेकिन ऐसा लगता है कि जोहान्स सही है। यह मेरे लिए Vista x64 पर काम नहीं करता है - कहता है "INFO: कोई साझा खुली फ़ाइलें नहीं मिलीं।" –

+0

जो/जोहान्स: सबसे पहले, क्या आपके पास वैश्विक "बनाए रखने वाली ऑब्जेक्ट सूची" चालू है (मुझे लगता है कि सिंटैक्स "आईआईआरसी पर" ओपनफाइल/स्थानीय "है? अगला, क्या आप "/ query" तर्क में गुजर रहे हैं, जैसा उपरोक्त उदाहरण में है (Vista के लिए req'd, ऐसा लगता है)? – Garrett

3

मैं केवल PowerShell और .NET फ्रेमवर्क वर्गों का उपयोग करता है Locked file detection पर एक अच्छा समाधान देखा है: कुछ इस तरह का प्रयास करें

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 
} 
+0

क्षमा करें, मैंने एक अलग परिदृश्य का जवाब दिया :( – Jordij

+0

यह केवल दिखाता है कि फ़ाइल लॉक है या नहीं, यह नहीं दिखाती कि कौन सी प्रक्रिया इसका उपयोग कर रही है। – KERR

0

आप थोड़ा नीचे की तरह ऊपर समारोह को संशोधित करते हैं सही या गलत लौटाएगा (आपको पूर्ण व्यवस्थापक अधिकारों के साथ निष्पादित करने की आवश्यकता होगी) उदा। उपयोग:

पुनश्च> 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 
} 
+3

इंगित करता है कि फ़ाइल लॉक है या नहीं, लेकिन फ़ाइल को लॉक करने वाला एप्लिकेशन नहीं देता है। – CJBS

+2

इसके अतिरिक्त: यह वास्तव में * एक नई फ़ाइल बनायेगा यदि यह पहले से मौजूद नहीं है – monojohnny

8

यह आपको मदद कर सकता है: Use PowerShell to find out which process locks a file। यह प्रत्येक प्रक्रिया की System.Diagnostics.ProcessModuleCollection मॉड्यूल संपत्ति पार्स करके उसे बंद कर दिया फ़ाइल के फ़ाइल पथ के लिए लग रहा है: मुझे पसंद है क्या कमांड प्रॉम्प्ट (सीएमडी) है

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

मेरे लिए सही उत्तर होगा, लेकिन ऐसा लगता है कि यह केवल डीएलएस के लिए काम करेगा, न कि किसी भी फाइल के लिए, जैसे कि लॉक की गई टेक्स्ट फाइलें। –

0

, और यह PowerShell में इस्तेमाल किया जा सकता साथ ही:

tasklist /m <dllName> 

बस ध्यान दें कि आप DLL फ़ाइल का पूरा पथ दर्ज नहीं कर सकते हैं। बस नाम काफी अच्छा है।

+0

दुर्भाग्यवश यह केवल डीएलएल फाइलों को दिखाता है ... – KERR

4

आप Sysinternal के Handle उपयोगिता का उपयोग कर समाधान ढूंढ सकते हैं।

मैं 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>.*)" 
    [regex]$matchPattern = "(?<Name>\w+\.\w+)\s+pid:\s+(?<PID>\d+)\s+type:\s+(?<Type>\w+)\s+(?<User>\.+)\s+\w+:\s+(?<Path>.*)" 

    $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 

उदाहरण:

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> 
+0

अच्छा, इस सरल कार्य को लिखने के लिए धन्यवाद! – Denis