PowerShell: Find Process ID (PID) Locking a Certain File

Here’s a function to kill common processes (Antivirus executable excluded) locking a particular file. This must be ran in the context of an Administrator.

$filePath='c:\temp\test.docx'
function removeFileLocks($filePath){
    function isFileLocked ($filePath){
        $fileName=Split-Path $filePath -leaf
        $file = New-Object System.IO.FileInfo $filePath
        
        function includeHandle{
            try{
                if (!(Get-Command handle.exe -ErrorAction SilentlyContinue)) {
                    if (!(Get-Command choco.exe -ErrorAction SilentlyContinue)) {
                    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
                    Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))    
                    }
                try{
                    choco install handle
                }catch{
                    choco install systernals -y
                }
                if (Get-Command handle.exe -ErrorAction SilentlyContinue) {                   
                    return $true
                }else{
                    return $false
                }
                }
            }catch{
                return $false
            }
        }

        if ((Test-Path -Path $filePath) -eq $false) {
            return $false
        }
        
        try {
            $exclusiveLock = $file.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)
            if ($exclusiveLock) {
                $exclusiveLock.Close()
            }
            return $false
        }catch{
            if(includeHandle){
                $handles=handle $fileName
                $pidRegex='pid: (\d+)'
                $pids=$handles|%{try{[regex]::Match($_,$pidRegex).captures.groups[1].value}catch{}}|Select-Object -Unique
                write-warning "$filePath is currently locked by process ID(s): $pids"
                return $pids
            }else{
                write-warning "$filePath is currently locked by a process."
                return $true
            }
        }
    }
    try{
        $lockingPids=isFileLocked $filePath
        if($lockingPids -eq $true){
            write-host ""
            return $true
        }elseif($lockingPids){
            $lockingpids|ForEach-Object{stop-process -id $_ -force}
            write-host "Program has removed $filePath locking PIDs: $lockingPids" -ForegroundColor Green
            return $true
        }else{
            write-host "$filePath has no locks." -ForegroundColor Green
            return $false
        }
    }catch{
        write-warning $_
        return $false
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *