为什么这个try / catch块会神奇吞噬异常?

时间:2016-02-07 02:20:21

标签: windows powershell error-handling scripting

我正在编写一个PowerShell脚本,该脚本使用反射API来获取程序集中的所有名称空间。无论如何,那是不相关的。以下是代码的相关部分:

function Get-Namespaces($assembly)
{
    $assemblyClass = [Reflection.Assembly]
    $assemblyObject = $assemblyClass::ReflectionOnlyLoadFrom($assembly)
    $types = $assemblyObject.GetTypes() # This is the part that's having issues
    return $types | ? IsPublic | select Namespace -Unique
}

cd $PSScriptRoot

$assemblies = @()
$assemblies += Get-WpfAssemblies
$assemblies += Get-UwpAssembly

$namespaces = $assemblies | % {
    % { Get-Namespaces $_ }
}

出于某种原因,初始化$types的部分似乎有问题;具体来说,它告诉我捕获异常并检查捕获的异常的LoaderExceptions属性以获取更多信息。所以,当我尝试这样做时:

try { $assemblyObject.GetTypes() } catch { echo $_.LoaderExceptions }

并运行它,脚本不打印任何内容。

为什么会发生这种情况,我该如何解决?

对于想要完整地试用该脚本的人,我已经公开发布了GitHub gist.(请注意,只有安装了Windows 10开发工具才能使用它,但我和#39;我确信有经验的PowerShell用户可以修改脚本以在他们的机器上运行。)

3 个答案:

答案 0 :(得分:0)

不幸的是,我不是在Windows PC上尝试这个,但是通过谷歌搜索,看起来应该是正确的语法:

try {
    ....
} catch [System.Reflection.ReflectionTypeLoadException] {
    echo $_.LoaderExceptions
}

结帐http://www.vexasoft.com/blogs/powershell/7255220-powershell-tutorial-try-catch-finally-and-error-handling-in-powershell。似乎在PowerShell中有关于异常处理的一些很好的信息。

答案 1 :(得分:0)

您捕获的(最顶层)异常可能是https://crossclj.info/fun/clj-webdriver.taxi/cookies.html,它没有属性LoaderExceptions。 PowerShell将缺少的属性扩展为$null值,这些值将转换为空字符串以进行输出。您可以通过使用catch cmdlet检查Get-Member块中的当前对象来检查异常类型及其属性和方法:

try { $assemblyObject.GetTypes() } catch { Get-Member -InputObject $_ }

由于PowerShell倾向于在嵌套异常中隐藏相关信息,因此您可能希望执行类似这样的操作来展开它们:

try {
  ...
} catch {
  $_.InvocationInfo.Line.Trim() + "`n"
  $_.InvocationInfo.PositionMessage + "`n"

  $e = $_.Exception
  do {
    $e.Message
    if ($e.LoaderExceptions) { $e.LoaderExceptions }
    $e = $e.InnerException
  } while ($e)
}

答案 2 :(得分:0)

问题在于PowerShell正在将回显的内容解释为返回值:

function Generate-ErrorMessage
{
    try
    {
        blah
    }
    catch
    {
        echo $_
    }
}

$message = Generate-ErrorMessage # Will contain some PowerShell message about not being able to find 'blah'

解决方案是直接使用Console.WriteLine

function Generate-ErrorMessage
{
    try
    {
        blah
    }
    catch
    {
        [Console]::WriteLine($_)
    }
}

Generate-ErrorMessage # prints the message to the console

不是很漂亮,但它按预期工作。

编辑: Write-Host也有效:

try { blah }
catch { Write-Host $_ }

对于其他命令,您可以查看here.

编辑2:事实上,Out-Host甚至更适合记录:

try { blah }
catch { $_ | gm | Out-Host } # displays more detailed info than Write-Host