如何在范围结束时自动调用Pop-Location

时间:2016-03-10 17:45:40

标签: powershell

假设我有一个简单的范围,通过Push-Location和Pop-Location以书结尾:

Function MyFunction($Location)
{
  Push-Location $Location
  # do other stuff here
  Pop-Location
}

有没有办法在范围的开头设置它,这样我就不必记得将Pop-Location放在最后?像这样:

Function MyFunction($Location)
{
  Setup-BothPushAndPopHere $Location
  # do other stuff here
  # at the end of the scope, Pop-Location is automatically called
}

3 个答案:

答案 0 :(得分:6)

简短回答:不。

我对Push-LocationPop-Location的看法是,您通常应该避免使用它们,并调整脚本以使用命令中的路径名;换句话说,而不是:

Push-Location $Location
Get-ChildItem
Pop-Location

只是做:

Get-ChildItem $Location

(简化示例)

如果您必须使用该模式,请考虑try / finally

Push-Location $Location
try {
    # ...
} finally {
    Pop-Location
}

因为这有助于意外异常或用户中断程序执行。

当代码超出我的控制范围时,我通常使用try / finally模式;最常见的是在加载SQLPS模块时,因为它将当前位置更改为SQL服务器提供程序,根据我的经验,这会导致使用当前位置的所有内容变慢。

正如Eris指出的那样,它在处理本机应用程序时也很有用。如果使用空格绕过带有空格的路径名称的引号很痛苦,或者应用程序无论如何都无法正确处理它,那么尤其如此。

答案 1 :(得分:1)

根据您在#do other stuff here代码中尝试执行的操作,您可以尝试将这些命令作为子进程中的脚本块执行。骨架代码示例:

$ScriptBlock = {
  Push-Location $Location
  #commands
}

$Job = Start-Job -ScriptBlock $ScriptBlock   # Add other arguments if needed

# Check the status of the task:
Get-Job $Job

# Wait for the job state to be 'Completed' (do-while, maybe?)

# If your ScriptBlock writes any output, collect in a variable:
$Output = Receive-Job $Job

# Clean up:
Remove-Job $Job

这种方法的关键在于你产生了一份工作来完成工作(在后台)你不必担心Pop-Location因为你只是让那个孩子的范围退出而你继续做任何事情你需要在主脚本中完成。

StackExchange上还有其他帖子详细介绍了

答案 2 :(得分:0)

这是使用脚本块实现的一种很酷的方法

function withPath($action,$path) {
    Push-Location $path
    try 
    {
        & $action
    }
    finally
    {
        Pop-Location
    }
}
withPath { 
    Get-Location | Write-Host 
    withPath {
        Get-Location | Write-Host 
        throw "oh no, an inner exception!"
    } 'Program Files' #relative path
} 'C:\'