【问题标题】:Capturing output from powershell script从 powershell 脚本捕获输出
【发布时间】:2018-06-09 06:16:51
【问题描述】:

我一直在为客户在 VS2017 中将 GUI 脚本从另一种语言转换为 C#。在这里的人们的帮助下,我已经完成了 95% 的路,但遇到了一些障碍;只是不确定我是否以最好的方式做事。我只包括以下代码的相关部分,如果我提供的不够多,请告诉我:

大部分代码以 wpf 形式为中心,该形式为低级技术人员收集数据以将多个虚拟机批量部署到 VMware 环境中。这个数字可以很容易地一次扩展到几十甚至一百个虚拟机。每个 VM 的信息在表单中指定,然后收集在列表视图中。一旦列表视图完全填充,它就会导出到 csv。到目前为止,一切正常。

接下来我一直致力于实际启动 powershell/powerCLI 脚本(也可以运行)并捕获输出。使用客户使用的特定阅读器应用程序打开日志文件,该应用程序实时更新,并将捕获的输出馈送到日志中。对于技术人员来说,逐行查看代码输出非常重要,这样他们可以在出现问题时做出反应。

我从这样的测试开始:

string sPSScript = "C:\\Users\\Admin\\Desktop\\TestC#.ps1";
string logFile = "C:\\Users\\Admin\\Desktop\\My.log";
string logReader = "C:\\Users\\Admin\\Documents\\CMTrace.exe";
string standard_output;

System.Diagnostics.Process PSScript = new System.Diagnostics.Process();
PSScript.StartInfo.FileName = 
Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) + 
"\\WindowsPowerShell\\v1.0\\powershell.exe";
PSScript.StartInfo.Arguments = "-command . '" + sPSScript + "' " + 
vCenter.Text;
PSScript.StartInfo.RedirectStandardOutput = true;
PSScript.StartInfo.UseShellExecute = false;
PSScript.Start();
System.Diagnostics.Process LogFile = new System.Diagnostics.Process();
LogFile.StartInfo.FileName = logReader;
LogFile.StartInfo.Arguments = logFile;
LogFile.Start();        while ((standard_output = 
PSScript.StandardOutput.ReadLine()) != null)
    {
       if (standard_output != "")
       {
          using (StreamWriter file = new StreamWriter(logFile, append: true))
             {
                file.WriteLine(standard_output);
             }
       }
   }

虽然这会按预期实时写入日志文件,但它会创建 100 个 logReader 应用程序实例。我理解为什么,因为我在每次传递时都声明了一个新的 StreamWriter 对象,但我不确定如何更好地解决这个问题。

我尝试在循环外创建文件,如下所示:

StreamWriter file = new StreamWriter(logFile, append: true) { };
System.Diagnostics.Process LogFile = new System.Diagnostics.Process();
LogFile.StartInfo.FileName = logReader;
LogFile.StartInfo.Arguments = logFile;

System.Diagnostics.Process PSScript = new System.Diagnostics.Process();
  PSScript.StartInfo.FileName = Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) + "\\WindowsPowerShell\\v1.0\\powershell.exe";
  PSScript.StartInfo.Arguments = "-command . '" + sPSScript + "' " + vCenter.Text;
  PSScript.StartInfo.RedirectStandardOutput = true;
  PSScript.StartInfo.UseShellExecute = false;

  LogFile.Start();
  PSScript.Start();
  System.Threading.Thread.Sleep(1500);

  while ((standard_output = PSScript.StandardOutput.ReadLine()) != null)
  {
     if (standard_output != "")
     {
        file.WriteLine(standard_output);
     }
  }

它不会创建多个实例,但也不会像之前的代码那样实时更新日志文件。它仅在脚本运行后更新,然后仅部分更新。该脚本产生约 1000 行输出,而我始终看到只有大约 840 行写入日志文件。

我想过做这样的事情:

FileStream logFS;
logFS = new FileStream(logFile, FileMode.Append);

但似乎我可以写入文件的唯一选项是需要一个字节数组。

我确信我在这方面遗漏了一些愚蠢的简单方法,但如果有任何关于创建日志文件、在阅读器中打开它、然后使用 powershell 脚本的标准输出更新它的最简单方法的建议,我将不胜感激。

【问题讨论】:

    标签: c# wpf powershell


    【解决方案1】:

    为什么前面的代码是实时写的?

    因为你用using 包装它。在using 块结束时,它会调用 dispose 调用.Flush 写入磁盘

    您的第二个代码块调用WriteLine,但从未调用Flush,因此只要缓冲区已满,它就会写入磁盘。只需在WriteLine 之后添加一个.Flush 调用,您将获得实时日志记录

    【讨论】:

    • 感谢您,这对您有所帮助。部分问题似乎是它的写入速度比日志应用程序重绘屏幕的速度要快。每次写入后我都必须进入睡眠状态才能看到输出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    • 2018-04-27
    • 2017-05-07
    • 2020-02-03
    • 1970-01-01
    • 2012-05-10
    • 2018-05-01
    相关资源
    最近更新 更多