【问题标题】:Getting the error of a Powershell Script within c# and outputting it with conditional statement?在 c# 中获取 Powershell 脚本的错误并使用条件语句输出它?
【发布时间】:2021-10-09 03:42:30
【问题描述】:

我有一个控制台应用程序和一个在控制台应用程序中执行 PowerShell 脚本的方法。所以我试图获取它在应用程序中输出的错误文本并对其进行处理。

示例/我正在尝试做的事情:

    If Error.contains("Object") 
{
    // do something here
}

这是我目前的方法

  public void ExecutePowershellScript()
{
  var file = @"C:\Path\filename.ps1";
           
            var start = new ProcessStartInfo()
            {
                FileName = "powershell.exe",
                Arguments = $"-NoProfile -ExecutionPolicy unrestricted -file \"{file}\"",
                UseShellExecute = false
            };
            Process.Start(start);
}

【问题讨论】:

    标签: c# .net powershell object console-application


    【解决方案1】:

    Process.start: how to get the output?

    当您创建 Process 对象时,适当地设置 StartInfo:

    var proc = new Process 
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = "program.exe",
            Arguments = "command line arguments to your executable",
            UseShellExecute = false,
            RedirectStandardOutput = true,
            CreateNoWindow = true
        }
    };
    

    然后启动进程并从中读取:

    proc.Start();
    while (!proc.StandardOutput.EndOfStream)
    {
        string line = proc.StandardOutput.ReadLine();
        // do something with line
    }
    

    您可以使用 int.Parse() 或 int.TryParse() 将字符串转换为数值。如果您读取的字符串中有无效的数字字符,您可能需要先进行一些字符串操作。

    【讨论】:

    • 是的,你可以设置异步错误处理程序process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler); //* 启动进程和处理程序
    【解决方案2】:

    您可以设置RedirectStandardError = true并从process.StandardError访问任何错误

        public static void ExecutePowershellScript()
        {
            var file = @"C:\Path\filename.ps1";
    
            var start = new ProcessStartInfo()
            {
                FileName = "powershell.exe",
                Arguments = $"-NoProfile -ExecutionPolicy unrestricted -file \"{file}\"",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };
            using Process process = Process.Start(start);
            string output = process.StandardOutput.ReadToEnd();
            string errors = process.StandardError.ReadToEnd();
        }
    



    好的,放弃上面的建议。 被mklement0修正后,

    这是一个完全合理的尝试,但不幸的是,它可能导致挂起(在等待一个流结束时,另一个超过缓冲区大小时,可能会导致进程执行阻塞)。如果您需要捕获两个流,则必须通过事件从其中一个流中收集输出。 – mklement0

    我将解决方案更改为使用 ErrorDataReceived 事件

            public static async Task ExecutePowershellScript()
            {
                var file = @"C:\Path\filename.ps1";
    
                var start = new ProcessStartInfo
                {
                    FileName = "powershell.exe",
                    Arguments = $"-NoProfile -ExecutionPolicy unrestricted -file \"{file}\"",
                    UseShellExecute = false,
                    // redirect standard error stream to process.StandardError
                    RedirectStandardError = true
                };
    
                using var process = new Process
                {
                    StartInfo = start
                };
    
                // Subscribe to ErrorDataReceived event
                process.ErrorDataReceived += (sender, e) =>
                {
                    //  code to process the error lines in e.Data
                };
    
                process.Start();
    
                // Necessary to start redirecting errors to StandardError
                process.BeginErrorReadLine();
    
                // Wait for process to exit
                await process.WaitForExitAsync();
    
            }
    

    【讨论】:

    • 这是一个完全合理的尝试,但不幸的是,它可能会导致挂起(在等待一个流结束时,另一个超过缓冲区大小时,可能会导致进程执行阻塞)。如果您需要捕获两个流,则必须通过事件收集其中一个流的输出。
    • 很公平。谢谢(你的)信息! @mklement0
    • @mklement0,有没有想过制作一本书(或文章/博客)来弥合 C# 和 PowerShell 之间的差距? ? 我真的很坚持这些书的想法 lol
    • 感谢更新,@Daniel。重申一下:原始方法在仅捕获 一个 流时有效。当 both 需要被捕获时,基于事件的方法是唯一完全健壮的方法,不过,务实地说,在 loopline 中读取两个流按行,也可以使用 - 你只会遇到过长的个别行(接近 64KiB 及以上)的麻烦。
    • @AbrahamZinala :) 我开始担心家庭作业的数量......
    【解决方案3】:
    start.Start();
    while (!start.StandardOutput.EndOfStream)
    {
        string line = start.StandardOutput.ReadLine();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-13
      • 2017-01-23
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 2023-01-13
      • 2020-10-09
      • 2018-04-08
      相关资源
      最近更新 更多