PowerShellでRename-ItemやCopy/Move/Removeなど、各種操作でそのファイルがロックされているかどうかの確認が必要です。
システム管理の一環として、ファイルの処理は欠かせないので使う場面は多いですが、PowerShellにロック状態を取得するコマンドレットはありません。
今回ちらっと作ってみました。
コード
GitHubに挙げてあります。
guitarrapc/PowerShellUtil - Test-FileLock | GitHub
Test-FileLockとGet-FileLockコマンドレットとしてモジュールを用意しています。
ファイルロックの検知部分はこのようにしてみました。
try { # initialise variables $script:filelocked = $false # attempt to open file and detect file lock $script:fileInfo = New-Object System.IO.FileInfo $Path $script:fileStream = $fileInfo.Open([System.IO.FileMode]::OpenOrCreate, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None) # close stream if not lock if ($fileStream) { $fileStream.Close() } } catch { # catch fileStream had falied $filelocked = $true } finally { # return result [PSCustomObject]@{ path = $Path filelocked = $filelocked } }
利用例
ファイルを対象にした時だけ結果が返ってきます。
-Verboseを付けることで、対象がDirectoryだった場合にはメッセージが出ます。
対象がフォルダ、Registryや環境変数では動きません。
Test-FileLock
Test-FileLockパスを受けてbooleanを返します。
# true for locked file Test-FileLock -Path 'C:\Program Files\Windows NT\Accessories\wordpad.exe' # false for not locked file Test-FileLock -Path 'D:\Software\SumoLogics\SumoCollector_linux_amd64_19_40-8.sh' # blank for Directory (as it always returns true) # Add -Verbose if you want to check if it were not file Test-FileLock -path D:\Hyper-V -Verbose # error for not exist # Add -Verbose if you want to check if it were not file Test-FileLock -Path D:\ge # access error Test-FileLock -path "C:\Windows\System32\LogFiles\HTTPERR\httperr1.log" # Path recurse Get-ChildItem -path $env:USERPROFILE -Recurse | %{Test-FileLock -path $_.FullName -Verbose} # Registry is ignore Get-FileLock -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion # Environment Variables is ignored Get-FileLock -Path $env:AMDAPPSDKROOT
Get-FileLock
Get-FileLockでパスを受けてファイルパスとbooleanを返します。
# locked file Get-FileLock -Path 'C:\Program Files\Windows NT\Accessories\wordpad.exe' # not locked file Get-FileLock -Path 'D:\Software\SumoLogics\SumoCollector_linux_amd64_19_40-8.sh' # blank for Directory (as it always returns true) # Add -Verbose if you want to check if it were not file Get-FileLock -path D:\Hyper-V -Verbose # not exist Get-FileLock -Path D:\ge # access error Get-FileLock -path "C:\Windows\System32\LogFiles\HTTPERR\httperr1.log" # Path recurse Get-ChildItem -path $env:USERPROFILE -Recurse | %{Get-FileLock -path $_.FullName -Verbose} # Registry is ignore Get-FileLock -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion # Environment Variables is ignored Get-FileLock -Path $env:AMDAPPSDKROOT
まとめ
もうちょっと楽にファイルロックを取得できるといいのですが、まぁ実用できるのでいいです。 もっといい方法ないかな。