Check lock and unlock Windows files using Powershell script

Here is the PowerShell script to force close programs that lock some Windows file. This can be usefull in many situations, for me it was necessary before updating IBM Cognos PowerPlay cubes. As some programs (for example IBM PowerPlay) can lock it, and do not allow any modifications: delete, copy and so on.

Script needs Administators rights and uses Handle.exe program from Microsoft, you can download it from Microsoft site.

# PROCESS NEEDS ADMIN RULES

# PowerShell script to force close of programs that lock $fileName file 
# Example of usage: 
#   [Path]/unlockFile.ps1 'filename.mdc'

# --------------- 
param([string]$fileName)

function Close-AllHandles {
    param(
        [Parameter(Mandatory=$true)]
        [object[]]$HandleInfo)

    foreach ($line in $handles) {
        $line=$Line.trim()
        if($line -like "*pid:*") {
            $result = $line | Select-String –pattern '^([^ ]*)\s*pid: ([0-9]*)\s*type: ([^ ]*)\s*([^ ]*)\s*(.*?): (.*)'
 
            $processName =  $result.Matches[0].Groups[1].Value
            $processId = [int]::Parse( $result.Matches[0].Groups[2].Value)
            $type = $result.Matches[0].Groups[3].Value
            $user = $result.Matches[0].Groups[4].Value
            $handleId =  $result.Matches[0].Groups[5].Value
            $name = $result.Matches[0].Groups[6].Value
            
            Write-Host "$($processName) - $($processId) - $($handleId)"

            # Close handles
            if($processId -and $handleId) {
                # Next will try to kill handle, but does not work for me
                # ./handle/handle64.exe -c $handleId -p $processId -y
                Stop-Process -Id $processId -Force
                Write-Host "$($processName) - $($processId) - $($handleId)"
            }
        }
    }
}

if(!$filename){
    echo "Specify filename as second argument, example: [Path]\unlockFile.ps1 name_of_file"
} else {
    Write-Host $fileName
    $handles = & ./handle/handle64.exe -a -u -accepteula $filename
    if($handles){
        Close-AllHandles -HandleInfo $handles    
    }
}

If you just need to check whenever file is locked you can use this script, it does not require Admin rights. Just call this process with full path to file as argument.

param([string]$fileName)

function Test-FileLock {
  param (
    [parameter(Mandatory=$true)][string]$Path
  )

  $oFile = New-Object System.IO.FileInfo $Path

  if ((Test-Path -Path $Path) -eq $false) {
    return $false
  }

  try {
    $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)

    if ($oStream) {
      $oStream.Close()
    }
    Write-Host 'Not Locked'
  } catch {
    # file is locked by a process.
	  Write-Host 'Locked'
  }
}

Test-FileLock -Path $fileName

Framework for script was taken from MarkRobertJohnson post.

Need more information about PowerScript read this: