tech.guitarrapc.cóm

Technical updates

PowerShell で ファイルの File Lock Status を取得したい

PowerShell で Rename-Item や Copy, Move, Remove など、各種操作を行う際に必須となるのが、 そのファイルが File Lock されているかどうかの確認です。 システム管理の一環として、ファイルの処理は欠かせないので 使う場面は多いはずです。 さて、PowerShell で FileLock 状態を取得するCmdlet はありません。 今回 ちらっと作ってみたので参考になれば幸いです。 

コード

GitHub に挙げてあります。

https://github.com/guitarrapc/PowerShellUtil/tree/master/Test-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
    }
}

今回は Test-FileLock と Get-FileLock Cmdlet としてモジュールを用意しています。

利用例

基本的には、 File でのみ結果が返ってきます。 -Verbose を付けることで、対象がDirectoryだった場合にはメッセージが出ます。 対象がフォルダ、Registry や環境変数では動きません。

Test-FileLock

Test-FileLock は Path を受けて $true / $false を返します。

#region Test-FileLock will return file lock status for the file

# 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

#endregion

Get-FileLock

Get-FileLock は Path を受けて ファイルパスと $true / $false を返します。

#region Get-FileLock will return file name and file lock status for the file

# 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

#endregion

まとめ

もうちょっと楽に ファイルロックを取得できるといいのですが、まぁ実用できるのでいいです。 もっといい方法ないかなーです。