'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 |