PowerShellで自動的にリソース開放する

toc目次

リソースの開放について

StreamReaderなどでファイルをOpenした場合、Close()を忘れたり、Close()前にエラーで処理が終了してしまうとファイルがオープンされたままになります。

1
2
3
4
5
6
7
8
9
# Close()を実行していない例
$filePath = "C:\test.txt"
$sr = New-Object System.IO.StreamReader($filePath)

while(($line = $sr.ReadLine()) -ne $null) {
    Write-Host $line
}

# $sr.Close()

上記スクリプト実行後、テキストエディターで該当ファイルを開こうとするとエラーメッセージが表示されます。

C:\test.txt は現在他のプロセスによって書き込みが禁止されてます。

PowerShellの自動リソース開放

C#ではUsing、Javaではtry-with-resourcesといった自動でリソース開放する構文が存在します。

PowerShellには自動でリソースを開放する構文は存在しませんが、以下サイトに公開されているUsing-Objectを使用すると自動リソース開放が可能となります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function Using-Object {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [AllowEmptyString()]
        [AllowEmptyCollection()]
        [AllowNull()]
        [Object]
        $InputObject,

        [Parameter(Mandatory = $true)]
        [scriptblock]
        $ScriptBlock
    )

    try {
        . $ScriptBlock
    }
    finally {
        if ($null -ne $InputObject -and $InputObject -is [System.IDisposable]) {
            $InputObject.Dispose()
        }
    }
}

Using-Objectを使用するとIDisposableを実装するオブジェクトはClose()Dispose()を実行しなくても自動でリソースが開放されます。

1
2
3
4
5
6
7
8
$filePath = "D:\test.txt"

# 自動でリソースが開放される
Using-Object($sr = New-Object System.IO.StreamReader($filePath)) {
    while(($line = $sr.ReadLine()) -ne $null) {
        Write-Host $line
    }
}