Functions/Validations/Test-ReadWriteAccessFile.ps1
<#
.Synopsis Test files from supplied folder on locks. .DESCRIPTION Tests all files from the supplied folder recursively if they are available to write. Returns a list of files that are not writeable, locked by other processes. .EXAMPLE $PathsToCheck = @('C:\Temp\FolderA', 'C:\Temp\FolderB') Test-GetReadWriteAccessFile -Path $PathsToCheck .EXAMPLE Test-GetReadWriteAccessFile -Path "C:\Temp\FolderA" .PARAMETER Path One or more parent folder paths. Items in these folders will be validated if they are writeable. #> function Test-ReadWriteAccessFile { [CmdletBinding()] [OutputType([array])] Param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)] $Path ) Begin { [array] $LockedFiles = @() $TotalFiles = 0 $ProcessedFiles = 0 # Calculate total number of files before processing foreach ($p in $Path) { $TotalFiles += (Get-ChildItem -Path $p -Recurse -File).Count } } Process { foreach ($p in $Path) { $files = Get-ChildItem -Path $p -Recurse -File | Select-Object -Property FullName foreach ($file in $files) { # Update progress $ProcessedFiles++ $percentComplete = ($ProcessedFiles/$TotalFiles)*100 $status = "Validating if files in the target directory are unlocked." Write-Progress -PercentComplete $percentComplete -Status $status ` -Activity "$ProcessedFiles of $TotalFiles checked." if (-not (Test-FileLock -Path $file.FullName)) { # File is not locked Write-Verbose "Not Locked: $($file.FullName)" continue } # File is locked Write-Verbose "Is Locked: $($file.FullName)" $LockedFiles += $file.FullName } } } End { # Hide the progress bar Write-Progress -Activity "Completed" -Completed if ($LockedFiles.Count -ge 1) { return $LockedFiles } return $false } } Export-ModuleMember -Function Test-ReadWriteAccessFile # https://social.technet.microsoft.com/Forums/windowsserver/en-US/74ea3752-9403-4296-ab98-d03fcc12b608/how-to-check-to-see-if-a-file-is-openlocked-before-trying-to-copy-it?forum=winserverpowershell function Test-FileLock { param ( [parameter(Mandatory=$true)] [string]$Path ) $oFile = New-Object System.IO.FileInfo $Path $scriptBlock = [scriptblock] { param($oFile) try { $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None) if ($oStream) { $oStream.Close() } $false } catch { # file is locked by a process. $true } } # Create the job with a timeout $job = Start-Job -ScriptBlock $scriptBlock -ArgumentList $oFile # Wait for the job for the defined amount of time $wait = Wait-Job -Job $job -Timeout 5 # If the job is still running after the timeout, consider the file as locked if ($wait -eq $null -or $wait.State -ne 'Completed') { $return = $true } else { $return = $false } Remove-Job -Job $job return $return } |