如何避免WriteVerbose / WriteObject坏线程

时间:2016-12-15 05:56:02

标签: powershell pscmdlet

我已经创建了一个包含五个或六个PSCmdlet的.NET程序集。它们都是管道线cmdlet - 即它们已在BeginProcessing中设置,并在ProcessRecord中完成工作。他们打电话到图书馆。我在整个库中使用“Trace.WriteLine”来跟踪发生的事情。

我认为创建一个Trace侦听器并将其写入WriteVerbose会非常酷。

这会导致崩溃:

PS C:\Users\Gordon\Documents\Code\calratio2015\JetCutStudies> .\Find-CalRatioSamples.ps1 mc15c | .\submit-all-samples.ps1
Get-GridJobInfo : The WriteObject and WriteError methods cannot be called from outside the overrides of the BeginProcessing, ProcessRecord, and EndProcessing methods, and they can only be called from within the same thread.
Validate that the cmdlet makes these calls correctly, or contact Microsoft Customer Support Services.
At C:\Users\Gordon\Documents\Code\calratio2015\JetCutStudies\submit-all-samples.ps1:23 char:14
+                 Status = Get-GridJobInfo -JobStatus $_.ID
+                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-GRIDJobInfo], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,PSAtlasDatasetCommands.GetGRIDJobInfo

我花了一段时间才弄清楚发生了什么。我想我理解,但不知道如何解决它(至少,不容易)。

  1. Get-GridJobInfo获取一些信息并调用WriteObject
  2. 由于这是流水线操作,因此调用Invoke-GridJob中的ProcessRecord。
  3. Invoke-GridJob具有-Verbose,因此它会安装Trace侦听器。
  4. Invoke-GridJob调用WriteObject。
  5. Powershell运行时“恢复”Get-GridJobInfo让它生成下一个管道对象。
  6. Get-GridJobInfo中的某处“Trace.WriteLine”
  7. 这会触发调用WriteVerbose的跟踪侦听器。
  8. 发生错误,因为我们当前在Get-GridJobInfo中,我们尝试在Invoke-GridJob PSCmdLet对象上调用WriteVerbose。
  9. 这个问题是TraceListener是一个全局的东西,因此在Invoke-GridJob的ProcessRecord内外调用。所以问题就变成了:如何最好地检测进出?

    我的第一个问题是检查CurrentThreadId - 但事实证明它不起作用 - PS尽可能地保持同一个线程。

    接下来,我想如果有一个全局我可以在PowerShell中访问,它会告诉我当前正在执行什么命令 - 然后我可以将它与我应该编写详细消息的命令进行比较。但是,我无法找到这样的东西(你可以在调试器中找到它:PSCmdLet.Context.CurrentCommandProcessor)。

    如果没有实现某种跟踪方案并将对象深深地传递到回调函数的callstack上的库中,我不确定我能做什么。

    非常感谢提前!

0 个答案:

没有答案