如何将ScriptStackTrace保留在远程计算机上的Invoke-Command内部引发的异常中?

FacticiusVir

我正在编写一个Powershell脚本,该脚本执行构建/部署过程中的步骤之一,并且需要在远程计算机上运行一些操作。该脚本是相对复杂的,因此,如果在该远程活动期间发生错误,我想详细了解该错误在脚本中何处发生的堆栈跟踪(已经生成的日志之上)。

出现的问题是,当从远程计算机中继终止异常时,Invoke-Command会丢失堆栈跟踪信息。如果在本地计算机上调用了脚本块:

Invoke-Command -ScriptBlock {
    throw "Test Error";
}

返回所需的异常详细信息:

Test Error
At C:\ScriptTest\Test2.ps1:4 char:2
+     throw "Test Error";
+     ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Test Error:String) [], RuntimeException
    + FullyQualifiedErrorId : Test Error

但是,如果远程运行:

Invoke-Command -ComputerName $remoteComputerName -ScriptBlock {
    throw "Test Error";
}

异常堆栈跟踪指向整个Invoke-Command块:

Test Error
At C:\ScriptTest\Test2.ps1:3 char:1
+ Invoke-Command -ComputerName $remoteComputerName -ScriptBlock {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Test Error:String) [], RuntimeException
    + FullyQualifiedErrorId : Test Error

我可以手动将异常传输回本地计算机:

$exception = Invoke-Command -ComputerName $remoteComputerName -ScriptBlock {
    try
    {
        throw "Test Error";
    }
    catch
    {
        return $_;
    }
}

throw $exception;

但是重新抛出它会丢失堆栈跟踪:

Test Error
At C:\ScriptTest\Test2.ps1:14 char:1
+ throw $exception;
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Test Error:PSObject) [], RuntimeException
    + FullyQualifiedErrorId : Test Error

如果我将异常写入输出:

$exception = Invoke-Command -ComputerName $remoteComputerName -ScriptBlock {
    try
    {
        throw "Test Error";
    }
    catch
    {
        return $_;
    }
}

Write-Output $exception;

我得到正确的堆栈跟踪信息:

Test Error
At line:4 char:3
+         throw "Test Error";
+         ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Test Error:String) [], RuntimeException
    + FullyQualifiedErrorId : Test Error

但是由于它不在错误流中,因此我的构建工具没有正确地将其拾取。如果尝试Write-Error,我将遇到与重新引发异常类似的问题,并且堆栈跟踪指向脚本的错误部分。

所以我的问题是-如何使Powershell从远程计算机报告异常,就好像它是在本地引发的一样,具有相同的堆栈跟踪信息并且在Error流上?

Frode F.

当您运行某些代码而失败时,您会收到一个ErrorRecord,它反映了(本地计算机)执行的代码因此,在使用时,throw "error"您可以访问该代码的invocationinfo和异常。

使用时Invoke-Command,您将不再执行throw "error"远程计算机。您(本地计算机)正在执行Invoke-Command ....,这就是为什么ErrorRecord您得到反映的原因(而不是您想要的真正异常)。这是必须的方式,因为异常可能来自远程计算机执行的脚本块,但是它也可能是Invoke-Command自身的异常,因为它无法连接到远程计算机或类似的东西。

最初在远程计算机上引发异常时,Invoke-Command/ PowerShell在本地计算机上引发RemoteException

#Generate errors
try { Invoke-Command -ComputerName localhost -ScriptBlock { throw "error" } }
catch { $remoteexception = $_ }

try { throw "error" }
catch { $localexception = $_ }

#Get exeception-types
$localexception.Exception.GetType().Name
RuntimeException

$remoteexception.Exception.GetType().Name
RemoteException

此异常类型具有一些额外的属性,包括SerializedRemoteException并且SerializedRemoteInvocationInfo包含来自远程会话中引发的异常的信息。使用这些,您可以收到“内部”异常。

样本:

#Show command that threw error 
$localexception.InvocationInfo.PositionMessage

At line:4 char:7
+ try { throw "error" }
+       ~~~~~~~~~~~~~

$remoteexception.Exception.SerializedRemoteInvocationInfo.PositionMessage    

At line:1 char:2
+  throw "error"
+  ~~~~~~~~~~~~~

然后,您可以编写一个简单的函数来动态提取信息,例如:

function getExceptionInvocationInfo ($ex) {
    if($ex.Exception -is [System.Management.Automation.RemoteException]) {
        $ex.Exception.SerializedRemoteInvocationInfo.PositionMessage
    } else {
        $ex.InvocationInfo.PositionMessage
    }
}

function getException ($ex) {
    if($ex.Exception -is [System.Management.Automation.RemoteException]) {
        $ex.Exception.SerializedRemoteException
    } else {
        $ex.Exception
    }
}

getExceptionInvocationInfo $localexception

At line:4 char:7
+ try { throw "error" }
+       ~~~~~~~~~~~~~

getExceptionInvocationInfo $remoteexception
At line:1 char:2
+  throw "error"
+  ~~~~~~~~~~~~~

请注意,SerializedRemoteExpcetion显示的PSObject原因由于网络传输期间发生了序列化/反序列化,因此,如果要检查异常类型,则需要从中提取它psobject.TypeNames

$localexception.Exception.GetType().FullName
System.Management.Automation.ItemNotFoundException

$remoteexception.Exception.SerializedRemoteException.GetType().FullName
System.Management.Automation.PSObject

#Get TypeName from psobject
$remoteexception.Exception.SerializedRemoteException.psobject.TypeNames[0]
Deserialized.System.Management.Automation.ItemNotFoundException

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在Python中,如何将字符串写入远程计算机上的文件?

来自分类Dev

使用Invoke-Command将XML保存在远程计算机上

来自分类Dev

如何将文字保留在父项中?

来自分类Dev

如何将所选数据保留在表中?

来自分类Dev

如何将特定节点保留在networkx中

来自分类Dev

如何将ID保留在dummyVars()中

来自分类Dev

如何将动画div保留在容器中

来自分类Dev

如何将本地计算机上的代码推送到主分支中的GitHub

来自分类Dev

即使重新安装病毒,病毒仍可以保留在计算机中吗?

来自分类Dev

如何告诉git忽略本地更改,但将文件保留在远程仓库中?

来自分类Dev

将多播消息保留在我的计算机上

来自分类Dev

如何在Powershell中替换远程计算机上文件中的字符串?

来自分类Dev

如何使用vuex刷新后如何将商品保留在购物车中

来自分类Dev

如何在golang CLI中的远程计算机上执行命令?

来自分类Dev

如何在IPython(Jupyter)Notebook中的远程计算机上添加内核?

来自分类Dev

如何删除远程计算机上authorized_keys文件中的重复行

来自分类Dev

使用存储在远程计算机上的会话中的数组

来自分类Dev

如何将本地计算机中的文件复制到远程虚拟机?

来自分类Dev

如何将值保留在Play框架中的inputPassword帮助器的字段中?

来自分类Dev

如何将span标签和类保留在TinyMce中的预代码块中

来自分类Dev

如何检查内部服务是否引发异常?

来自分类Dev

如何将逻辑推入模型而不是将其保留在控制器中?

来自分类Dev

如何将GIT存储库保留在Dropbox中?

来自分类Dev

更新气泡图中的数据时如何将圆圈保留在svg中

来自分类Dev

提交后如何将字段值保留在表单中?

来自分类Dev

如何将图标保留在统一启动器中并从桌面删除?

来自分类Dev

如何将ImageOutputStream的流保留在内存中?

来自分类Dev

如何将网格线保留在空的TableView Javafx中

来自分类Dev

如何将第一个值保留在多列中?

Related 相关文章

  1. 1

    在Python中,如何将字符串写入远程计算机上的文件?

  2. 2

    使用Invoke-Command将XML保存在远程计算机上

  3. 3

    如何将文字保留在父项中?

  4. 4

    如何将所选数据保留在表中?

  5. 5

    如何将特定节点保留在networkx中

  6. 6

    如何将ID保留在dummyVars()中

  7. 7

    如何将动画div保留在容器中

  8. 8

    如何将本地计算机上的代码推送到主分支中的GitHub

  9. 9

    即使重新安装病毒,病毒仍可以保留在计算机中吗?

  10. 10

    如何告诉git忽略本地更改,但将文件保留在远程仓库中?

  11. 11

    将多播消息保留在我的计算机上

  12. 12

    如何在Powershell中替换远程计算机上文件中的字符串?

  13. 13

    如何使用vuex刷新后如何将商品保留在购物车中

  14. 14

    如何在golang CLI中的远程计算机上执行命令?

  15. 15

    如何在IPython(Jupyter)Notebook中的远程计算机上添加内核?

  16. 16

    如何删除远程计算机上authorized_keys文件中的重复行

  17. 17

    使用存储在远程计算机上的会话中的数组

  18. 18

    如何将本地计算机中的文件复制到远程虚拟机?

  19. 19

    如何将值保留在Play框架中的inputPassword帮助器的字段中?

  20. 20

    如何将span标签和类保留在TinyMce中的预代码块中

  21. 21

    如何检查内部服务是否引发异常?

  22. 22

    如何将逻辑推入模型而不是将其保留在控制器中?

  23. 23

    如何将GIT存储库保留在Dropbox中?

  24. 24

    更新气泡图中的数据时如何将圆圈保留在svg中

  25. 25

    提交后如何将字段值保留在表单中?

  26. 26

    如何将图标保留在统一启动器中并从桌面删除?

  27. 27

    如何将ImageOutputStream的流保留在内存中?

  28. 28

    如何将网格线保留在空的TableView Javafx中

  29. 29

    如何将第一个值保留在多列中?

热门标签

归档