6

I am wanting to create a PowerShell script that will find any files that are locked within a supplied directory and return the application/process that has locked the file.

I have found a script which goes through a directory and when it finds a locked file will stop and report the file is locked.

Function Test-Lock{
    param(
    [parameter(ValueFromPipeline=$true)]
    $Path
    )
    Process {
        if($Path.Attributes -ne 'Directory'){
            $oFile = New-Object System.IO.FileInfo $Path.FullName
            $locked=$false
            try{
                $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
                $oStream.Close()
                }
            catch{
                write-host $Error[0]
                $locked=$true
                New-Object PSObject -Property @{'Path'=$Path.FullName;'Locked?'=$locked} | Select Path,Locked?
                } 

        }
    }
}
$lockedfiles=(gci C:\temp | Test-Lock)
$lockedfiles | Format-Table -auto

This returns:

Path                  Locked?
----                  ------- 
C:\temp\ReportReq.doc    True

I cannot work out how to find the application or proecess that has this file locked.

Lima
  • 1,203
  • 3
  • 22
  • 51

4 Answers4

7

Well, You need to use handle.exe from sysinternals to achieve this. Adam Driscoll, a PowerShell MVP, wrote a PowerShell version of sysinternals handle.exe. You can check that at: https://github.com/adamdriscoll/PoshInternals/blob/master/Handle.ps1

Also, there is a similar question answered here by Keith Hill: PowerShell script to check an application that's locking a file?

KERR
  • 1,312
  • 18
  • 13
ravikanth
  • 24,922
  • 4
  • 60
  • 60
  • A little frustrating that you have to use a 3rd party tool to just see what files are used by an application, but I'll try working with it. Have tried using the Get-Handle.ps1 file, using similar command to the one provided in your link describing the PS version of handle, I am unable to get it to work without errors: Where-Object : Cannot bind parameter 'FilterScript'. Cannot convert the "type" value of type "System.String" to type "S ystem.Management.Automation.ScriptBlock". – Lima Jun 20 '13 at 06:46
  • 1
    The link here is dead. – Der Kommissar Feb 07 '17 at 17:44
  • 1
    Is there a copy of the script referenced still available? – r4d1um Jun 01 '17 at 08:20
  • 1
    Adam's site moved to another domain. Anyway, here is the link to the script from his github repo. https://github.com/adamdriscoll/PoshInternals/blob/master/Handle.ps1 – ravikanth Jun 11 '17 at 14:26
1

If you only want to check if file is locked or not use this:

try {
   [IO.File]::OpenWrite($file).close();
}catch {
   $locked = 1;
};
Krzysztof Gapski
  • 528
  • 6
  • 10
0

Posted a PowerShell module in PsGallery to discover & kill processes that have open handles to a file or folder. It exposes functions to: 1) find the locking process, and 2) kill the locking process. The module automatically downloads handle.exe on first usage.

Find-LockingProcess()
Retrieves process information that has a file handle open to the specified path.
Example: Find-LockingProcess -Path $Env:LOCALAPPDATA
Example: Find-LockingProcess -Path $Env:LOCALAPPDATA | Get-Process

Stop-LockingProcess()
Kills all processes that have a file handle open to the specified path.
Example: Stop-LockingProcess -Path $Home\Documents

PsGallery Link: https://www.powershellgallery.com/packages/LockingProcessKiller To install run:
Install-Module -Name LockingProcessKiller

David R.
  • 21
  • 2
-1

Just to add to the Sysinternals 3rd Party Tools slant, you could use the Find function inside Sysinternals Process Explorer.

EndUzr
  • 363
  • 3
  • 8