'How to check if file is being used by another process - Powershell

I am trying to find a solution which will check whether a file is being used by another process. I don't want to read the contents of the file, as on a 7GB document, this could take a while. Currently I am using the function mentioned below, which is not ideal as the script takes about 5 - 10 minutes to retrieve a value.

function checkFileStatus($filePath)
{
    write-host (getDateTime) "[ACTION][FILECHECK] Checking if" $filePath "is locked"

    if(Get-Content $filePath  | select -First 1)
    {
        write-host (getDateTime) "[ACTION][FILEAVAILABLE]" $filePath
        return $true
    }
    else
    {
        write-host (getDateTime) "[ACTION][FILELOCKED] $filePath is locked"
        return $false
    }
}

Any help would be greatly appreciated



Solution 1:[1]

Created a function which solves the above problem:

 function checkFileStatus($filePath)
    {
        write-host (getDateTime) "[ACTION][FILECHECK] Checking if" $filePath "is locked"
        $fileInfo = New-Object System.IO.FileInfo $filePath

        try 
        {
            $fileStream = $fileInfo.Open( [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read )
            write-host (getDateTime) "[ACTION][FILEAVAILABLE]" $filePath
            return $true
        }
        catch
        {
            write-host (getDateTime) "[ACTION][FILELOCKED] $filePath is locked"
            return $false
        }
    }

Solution 2:[2]

The function i use to check whether a file is locked or not :

function IsFileLocked([string]$filePath){
    Rename-Item $filePath $filePath -ErrorVariable errs -ErrorAction SilentlyContinue
    return ($errs.Count -ne 0)
}

Solution 3:[3]

function IsFileAccessible( [String] $FullFileName )
{
  [Boolean] $IsAccessible = $false

  try
  {
    Rename-Item $FullFileName $FullFileName -ErrorVariable LockError -ErrorAction Stop
    $IsAccessible = $true
  }
  catch
  {
    $IsAccessible = $false
  }
  return $IsAccessible
}

Solution 4:[4]

Check this script on poschcode.org:

filter Test-FileLock {
    if ($args[0]) {$filepath = gi $(Resolve-Path $args[0]) -Force} else {$filepath = gi $_.fullname -Force}
    if ($filepath.psiscontainer) {return}
    $locked = $false
    trap {
        Set-Variable -name locked -value $true -scope 1
        continue
    }
    $inputStream = New-Object system.IO.StreamReader $filepath
    if ($inputStream) {$inputStream.Close()}
    @{$filepath = $locked}
}

Solution 5:[5]

SInce you don't want to read the file, I would recommend using a utility like Sysinternals Handle.exe, which will spit out all open handles for a process. You can download Handle.exe from here:

http://technet.microsoft.com/en-us/sysinternals/bb896655

You can run Handle.exe without any arguments, and it will return all open file handles. You can parse the output if necessary, or just match the output against your full file path.

Solution 6:[6]

I want to correct above answer:

 function checkFileStatus($filePath)
    {
        write-host (getDateTime) "[ACTION][FILECHECK] Checking if" $filePath "is locked"
        $fileInfo = New-Object System.IO.FileInfo $filePath

        try 
        {
            $fileStream = $fileInfo.Open( [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::None )
            write-host (getDateTime) "[ACTION][FILEAVAILABLE]" $filePath
            $fileStream.Dispose()
            return $true
        }
        catch
        {
            write-host (getDateTime) "[ACTION][FILELOCKED] $filePath is locked"
            return $false
        }
    }

If you try to open file with [FileShare]::Read, it could be opened if other process also specified this (or less restricitve) FileShare mode. So, you must use [FileShare]::None, as most restrictive and incompatible with any other mode - so if file opened by another process in any way, it will be failed to open by script.

Also filestream should be disposed, otherwise file may remain opened for indefinite amount of time.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user983965
Solution 2 Florent Breheret
Solution 3 Piper
Solution 4
Solution 5
Solution 6 Somescout