2016-12-16 91 views
4

我试图赶上异常调用运行这样的其他功能的功能:Powershell的尝试捕捉

$ErrorActionPreference = "Stop" 
function f { 
    $a = 1 
    $b = $a/0 
} 
function Main($f) { 
    try { 
     $f 
    } catch [System.Exception] { 
     "Caught exception" 
    } 
} 
Main(f) 

的问题是,该异常没有被捕获像这样的PowerShell显示消息:

Attempted to divide by zero. 
In C:\test.ps1:4 car:5 
+  $b = $a/0 
+  ~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [], ParentContainsErrorRecordException 
    + FullyQualifiedErrorId : RuntimeException 

为什么异常没有被捕获,即使$ErrorActionPreference = "Stop"是对代码的顶部?

+0

没有高阶函数在你的榜样 –

回答

1

那么,你没有调用你的Main函数,你调用f函数,并将其输出作为Main的输入,然后调用Main函数。使用Set-PSDebug并查看。

Set-PSDebug -Trace 2 

现在测试:

Main(f) 

DEBUG:  ! CALL function '<ScriptBlock>' 
DEBUG:  ! SET $ErrorActionPreference = 'Stop'. 
DEBUG: 15+ >>>> Main(f) 
DEBUG: 2+ function f >>>> { 

DEBUG:  ! CALL function 'f' 
DEBUG: 3+ >>>> 1/0 

这枚返回1

function f { 
1/1 
} 
function Main($f) { 
    try { 
     $f 
    } catch [System.Exception] { 
     "Caught exception" 
    } 
} 

Main(f) 

这捕获预期:

function f { 
1/1 
} 
function Main($f) { 
    try { 
     $f/0 
    } catch [System.Exception] { 
     "Caught exception" 
    } 
} 

Main(f) 

编辑:为了澄清错误的第二答案,这与机智无关^ h预编译,它很容易与下面的代码可验证:

function f { 
$a = 0 
1/$a 
} 
function Main($input) { 
    try { 
     $input 
    } catch [System.Exception] { 
     "Caught exception" 
    } 
} 

Main(f) 
+0

感谢所有。我明白我的错误。 – guidros

+0

@guidros好,如果其中一个答案帮助你将它标记为答案,谢谢! – 4c74356b41

3

问题是真的在这条线Main(f)。所做的就是调用函数f并尝试将结果传递给函数Main。当然,在它可以得到结果之前,有一个异常,并且管道永远不会进入Main。你试图传递函数本身而不是结果。 PowerShell没有很好的方法直接做到这一点。这是一种脚本语言,不是一种功能语言。但是,您可以将参数声明为Main作为ScriptBlock并调用它。一个ScriptBlock就像一个函数对象。使用它将产生相同的效果。然而,获取函数的ScriptBlock有点麻烦。这应该是预期,是更标准的工作作风:

$ErrorActionPreference = "Stop" 
function f { 
    $a = 1 
    $b = $a/0 
} 

function Main {  
    param([ScriptBlock]$f) 

    try { 
     & $f 
    } catch [System.Exception] { 
     "Caught exception" 
    } 
} 

Main -f { f } 

所以不是我们传递的是只包含对f和调用该包装的调用一个新的脚本块。

请注意,我已经替换了C风格的函数调用语法。以我的经验来看,这种风格比在PowerShell中的价值更麻烦。坚持PowerShell风格,事情往往更清晰。

如果你真的想要得到的相关函数的脚本,你需要做的是这样的:

Main -f (get-command f).ScriptBlock