嵌套脚本块的范围问题,并尝试...终于

时间:2014-12-09 18:23:02

标签: powershell powershell-v2.0 powershell-v3.0 raii

我试图在PowerShell中实现RAII式的资源管理。令我印象深刻的是在try-block中获取资源并在finally块中再次释放它(因为它保证了finally块的执行)。有时,我的资源相互依赖,所以我使用嵌套方法。大纲如下:

我的资源1是这样获得的(对于长度代码感到遗憾,找不到缩短它的方法):

function withResource1 {
    param( [Parameter(Mandatory=$true)][scriptblock]$action )

    try {
        write-host "acquire resource1"

        <# ... compute resource 1... #>
        $resource1 = "<this is the resource>"

        invoke-command -scriptBlock $action -args $resource1
    } finally {
        write-host "release resource1"
        <# ... #>
    }
}

资源2取决于1,所以我这样得到它:

function withResource2 {
    param( [Parameter(Mandatory=$true)][scriptblock]$action )

    withResource1 { param( $res1 )
        try {
            write-host "acquire resource2"

            <# ... compute resource2, using resource1 ... #>
            $resource2 = "<and this is the other resource>"

            invoke-command -scriptBlock $action -args $resource2
        } finally {
            write-host "release resource2"
            <# ...  #>
        }
    }
}

现在(至少我在思考),我可以像这样使用资源2:

withResource2 { param( $res2 )
    write-host "I'm happy to have '$res2', which depends on resource 1"
}

我预计输出为

acquire resource1
acquire resource2
I'm happy to have '<and this is the other resource>', which depends on resource 1
release resource2
release resource1

但实际发生的是某种无限循环。问题似乎是某种范围问题,因为如果我将action重命名为ac中的withResource2,那么一切都按预期工作。

我怎样才能实现我想要的目标?是否有更好的方法在PowerShell中模拟RAII?

1 个答案:

答案 0 :(得分:0)

好的,我发现了自己。

try中的withResource2块内,{0}范围内没有$action变量,即

get-variable -name action -scope 0 

找不到名为action的变量。因此它会缩放到scope 1,这是父作用域(withResource1的范围),而$action正好是我提供给withResource1的脚本块。调用它会导致无限循环。

try withResource2中的$action块实际上要调用的是withResource2中的invoke-command,其中 2 范围。因此,将withResource2中的invoke-command -scriptBlock ( get-variable -name action -scope 2 ).Value -args $resource2 - 行更改为

{{1}}

诀窍。