2010-04-13 54 views
4

我在C#中执行PowerShell脚本代码的地方有一些PowerShell主机。下面的代码来自于AddOIn for Visual Studio中的主机。问题是,如果在PowerShell脚本代码中发生错误,我不知道发生错误的PowerShell脚本文件的文件和行号。从运行空间中的c#调用PowerShell脚本,并获取错误发生的行号

我的托管代码如下所示:

 public Exception Execute(string scriptcode, Hashtable variables) 
    { 
     Runspace runspace = null; 
     Pipeline pipeline = null; 
     PipelineStateInfo info = null; 

     try 
     { 
      // Make our output window active 
      Logger.ShowOutputWindow(); 

      // Create the runspace and stuff. 
      runspace = RunspaceFactory.CreateRunspace(host); 
      pipeline = runspace.CreatePipeline(); 

      runspace.Open(); 

      // Add our scriptcode to the pipeline 
      pipeline.Commands.Add(new Command(scriptcode, true)); 

      // We don't want to get PSObjects out of the pipeline, output result as string in default way 
      pipeline.Commands.Add(new Command("Out-Default", true)); 

      // Set up global variables 
      FillVariables(runspace, variables); 

      SetUpOutputStreams(pipeline); 


      // Run the scriptcode 
      Collection<PSObject> psOutput = pipeline.Invoke(); 

      // Did it complete ok? 
      info = pipeline.PipelineStateInfo; 
      if (info.State != PipelineState.Completed) 
      { 
       return info.Reason; 
      } 
      else 
      { 
       return null; // succesful! 
      } 
     } 
     catch (Exception ex) 
     { 
      return ex; 
     } 
    } 

首先,我有我的剧本在脚本代码变量,我现在先写代码到一个临时文件名为.psl这样我就可以在该文件linenumbers报告。但我找不到如何在文件中执行代码,以便在发生错误时可以检索文件名和行号。

任何想法?

+0

关于它的任何解决方案和完整的源代码? – Kiquenet 2012-05-25 08:19:17

回答

6

这应该让你在正确的地方:

//invoke pipeline 
collection = pipeline.Invoke(); 

// check for errors (non-terminating) 
if (pipeline.Error.Count > 0) 
{ 
    //iterate over Error PipeLine until end 
    while (!pipeline.Error.EndOfPipeline) 
    { 
    //read one PSObject off the pipeline 
    var value = pipeline.Error.Read() as PSObject; 
    if (value != null) 
    { 
     //get the ErrorRecord 
     var r = value.BaseObject as ErrorRecord; 
     if (r != null) 
     { 
     //build whatever kind of message your want 
     builder.AppendLine(r.InvocationInfo.MyCommand.Name + " : " + r.Exception.Message); 
     builder.AppendLine(r.InvocationInfo.PositionMessage); 
     builder.AppendLine(string.Format("+ CategoryInfo: {0}", r.CategoryInfo)); 
     builder.AppendLine(
     string.Format("+ FullyQualifiedErrorId: {0}", r.FullyQualifiedErrorId)); 
     } 
    } 
    } 
    return builder.ToString(); 
} 

UPDATE:

除了我在评论中写道的信息,也请看看这本书:Professional PowerShell Programming

我当我第一次开始编写PowerShell运行时的主机时,发现这本书是无价的。它是由一些PowerShell开发人员编写的。

+1

奇怪的是,如果发生错误,例如使用throw或1/0,pipeline.Invoke()将引发异常,并且错误集合为空。所以我没有得到调用信息。它也不会跟踪工作(set-psdebug -trace 1)。 – 2010-04-21 07:22:57

+0

是的。此代码将捕获PowerShell表面的任何错误,PowerShell不会抛出异常。那些必须在调用调用周围的正常try catch块中捕获。我通常会遇到NullReferenceException和特定情况下捕获的一些特定的PowerShell异常。 追踪是另一条管线。目前我没有SDK在我面前,但我相信它以相同的方式访问。 – 2010-04-21 14:52:07