我可以取消 CMD.EXE 错误消息中的 CR/CRLF 序列吗? [英] Can I suppress the CR/CRLF sequence in a CMD.EXE error message?

查看:19
本文介绍了我可以取消 CMD.EXE 错误消息中的 CR/CRLF 序列吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在标准 Windows 命令 shell 中,尝试运行找不到的命令会导致以下错误(逐字):

In the standard windows command shell, attempting to run a commmand that cannot be found results in the following error (verbatim):

'iamanonexistentcommand' is not recognized as an internal or external command,
operable program or batch file.

...外部命令,之后,有没有办法抑制CR/CRLF?

Is there any way to suppress the CR/CRLF after ... external command, ?

它似乎与命令窗口的大小或错误命令的长度无关,至少在交互式 shell 中是这样.

It seems independent of the size of the command window or the length of the erroneous command, at least in an interactive shell.

当我在 .net 框架中使用 Process.Start 运行命令 shell 时尝试捕获和重新格式化错误消息时,这给我带来了问题.

This is causing me problems when I attempt to capture and reformat error messages when running a command shell with Process.Start in the .net framework.

我最终收到了多条相同的消息,我只想捕获从一条消息到下一条消息的更改.问题是当数据可用于通过 ErrorDataReceived 事件处理时,CR/CRLF 被解释为 EOM,所以效果是我收到多条消息为每个实际故障,一个为 'iamanonexistentcommand' 不被识别为内部或外部命令, 和另一个用于 可运行的程序或批处理文件.

I end up with multiple identical messages piped in and I'd like to capture only changes from one message to the next. The problem is that CR/CRLF is interpreted as EOM when the data is available for processing through the ErrorDataReceived event, so the effect is that I receive multiple messages for each actual failute, one for 'iamanonexistentcommand' is not recognized as an internal or external command, and another for operable program or batch file.

这感觉就像是为了激怒我而设计的.

This feels like it was designed just to irritate me.

推荐答案

尝试以下操作,看看它是否满足您的需求——它展示了如何使用 System.Diagnostics.Process 进行异常处理和似乎避免了你提到的问题.它已经过测试,但它是否适用于您的情况可能取决于您正在调用的其他程序以及其他程序如何生成输出.

Try the following to see if it meets your needs--it shows how to use System.Diagnostics.Process with exception handling and seems to avoid the issue that you mentioned. It's been tested, but whether or not it works for your case may depend on what other program you are calling and how the other program generates output.

此外,如果您对要执行的程序使用完全限定名称(例如:C:\Windows\system32\ipconfig.exe),您可以使用 System 检查文件是否存在.IO.File.Exists,在尝试使用Process"调用它之前.

Additionally, if you use a fully-qualified name for the program that you want to execute (ex: C:\Windows\system32\ipconfig.exe), you can check to see if the file exists using System.IO.File.Exists, prior to attempting to call it using "Process".

if (!System.IO.File.Exists(@"C:\Windows\system32\ipconfig.exe))
{
    System.Diagnostics.Debug.WriteLine("Error: Filename doesn't exist.");

    //ToDo: add desired code here

}

创建一个类(名称:Helper)

Create a class (name: Helper)

添加以下 using 语句:

Add the following using statements:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

创建两个事件以允许将数据发送给订阅者.

Create two events to allow data to be sent to subscribers.

//delegates
public delegate void EventHandlerProcessErrorReceived(object sender, string data);
public delegate void EventHandlerProcessOutputReceived(object sender, string data);

//event that subscribers can subscribe to
public event EventHandlerProcessErrorReceived ProcessErrorReceived;
public event EventHandlerProcessOutputReceived ProcessOutputReceived;

创建两个我们可以调用以将数据传递给订阅者的方法:

Create two methods that we can call to pass data to subscribers:

  • OnErrorReceived - 收到错误消息时引发
  • OnOutputReceived - 在收到标准输出消息时引发

每个方法检查是否有任何订阅者,以及是否存在任何数据.如果是,则引发该事件.

Each method checks if there are any subscribers, and if any data exists. If so, the event is raised.

private void OnErrorReceived(string data)
{
    //only raise event if there are subscribers and actual data exists
    if (ProcessErrorReceived != null && !String.IsNullOrEmpty(data))
    {
        //raise event
        ProcessErrorReceived(this, data);
    }
}

private void OnOutputReceived(string data)
{
    //only raise event if there are subscribers and actual data exists
    if (ProcessOutputReceived != null && !String.IsNullOrEmpty(data))
    {
        //raise event
        ProcessOutputReceived(this, data);
    }
}

创建调用 System.Diagnostics.Process 的方法(名称:RunCmd)

Create method that calls System.Diagnostics.Process (name: RunCmd)

运行命令

public void RunCmd(string exePath, string arguments = null, Dictionary<string, string> environmentVarDict = null)
{
    string errMsg = string.Empty;

    try
    {
        if (String.IsNullOrEmpty(exePath))
        {
            errMsg = "Error: fullyQualifiedExePath not specified";

            Debug.WriteLine("Error: " + errMsg);
            OnErrorReceived(errMsg); //raise event

            return;
        }

        //create new instance
        ProcessStartInfo startInfo = new ProcessStartInfo(exePath, arguments);

        //add environment variables, if specified
        if (environmentVarDict != null)
        {
            foreach (KeyValuePair<string, string> kvp in environmentVarDict)
            {
                //add environment variable
                startInfo.EnvironmentVariables[kvp.Key] = kvp.Value;
            }
        }

        startInfo.Arguments = arguments; //arguments
        startInfo.CreateNoWindow = true; //don't create a window
        startInfo.RedirectStandardError = true; //redirect standard error
        startInfo.RedirectStandardOutput = true; //redirect standard output
        startInfo.RedirectStandardInput = false;
        startInfo.UseShellExecute = false; //if true, uses 'ShellExecute'; if false, uses 'CreateProcess'

        //startInfo.WindowStyle = ProcessWindowStyle.Normal;
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        startInfo.ErrorDialog = false;

        if (exePath.Contains("\\"))
        {
            startInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(exePath);
        }

        using (Process p = new Process { StartInfo = startInfo, EnableRaisingEvents = true })
        {
            //subscribe to event and add event handler code
            p.ErrorDataReceived += (sender, e) =>
            {
                if (!String.IsNullOrEmpty(e.Data))
                {
                    //ToDo: add desired code 
                    //Debug.WriteLine("Error: " + e.Data);
                    OnErrorReceived(errMsg); //raise event
                }
            };

            //subscribe to event and add event handler code
            p.OutputDataReceived += (sender, e) =>
            {
                if (!String.IsNullOrEmpty(e.Data))
                {
                    //ToDo: add desired code
                    //Debug.WriteLine("Output: " + e.Data);
                    OnOutputReceived(e.Data); //raise event
                }
            };

            p.Start(); //start

            p.BeginErrorReadLine(); //begin async reading for standard error
            p.BeginOutputReadLine(); //begin async reading for standard output

            //waits until the process is finished before continuing
            p.WaitForExit();

        }
    }
    catch(System.ComponentModel.Win32Exception ex)
    {
        errMsg = "Error (Win32Exception): " + ex.Message;
        //Debug.WriteLine(errMsg);
        OnErrorReceived(errMsg);
    }
    catch(Exception ex)
    {
        errMsg = "Error: " + ex.Message;
        //Debug.WriteLine(errMsg);
        OnErrorReceived(errMsg);
    }
    
}

Helper.cs(完整代码)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace ProcessUsage
{
    public class Helper
    {
        //delegates
        public delegate void EventHandlerProcessErrorReceived(object sender, string data);
        public delegate void EventHandlerProcessOutputReceived(object sender, string data);

        //event that subscribers can subscribe to
        public event EventHandlerProcessErrorReceived ProcessErrorReceived;
        public event EventHandlerProcessOutputReceived ProcessOutputReceived;

        private void OnErrorReceived(string data)
        {
            //only raise event if there are subscribers and actual data exists
            if (ProcessErrorReceived != null && !String.IsNullOrEmpty(data))
            {
                //raise event
                ProcessErrorReceived(this, data);
            }
        }

        private void OnOutputReceived(string data)
        {
            //only raise event if there are subscribers and actual data exists
            if (ProcessOutputReceived != null && !String.IsNullOrEmpty(data))
            {
                //raise event
                ProcessOutputReceived(this, data);
            }
        }

        public void RunCmd(string exePath, string arguments = null, Dictionary<string, string> environmentVarDict = null)
        {
            string errMsg = string.Empty;

            try
            {
                if (String.IsNullOrEmpty(exePath))
                {
                    errMsg = "Error: fullyQualifiedExePath not specified";

                    Debug.WriteLine("Error: " + errMsg);
                    OnErrorReceived(errMsg); //raise event

                    return;
                }

                //create new instance
                ProcessStartInfo startInfo = new ProcessStartInfo(exePath, arguments);

                //add environment variables, if specified
                if (environmentVarDict != null)
                {
                    foreach (KeyValuePair<string, string> kvp in environmentVarDict)
                    {
                        //add environment variable
                        startInfo.EnvironmentVariables[kvp.Key] = kvp.Value;
                    }
                }

                startInfo.Arguments = arguments; //arguments

                startInfo.CreateNoWindow = true; //don't create a window

                startInfo.RedirectStandardError = true; //redirect standard error
                startInfo.RedirectStandardOutput = true; //redirect standard output

                startInfo.RedirectStandardInput = false;

                startInfo.UseShellExecute = false; //if true, uses 'ShellExecute'; if false, uses 'CreateProcess'

                //startInfo.WindowStyle = ProcessWindowStyle.Normal;
                startInfo.WindowStyle = ProcessWindowStyle.Hidden;
                startInfo.ErrorDialog = false;

                if (exePath.Contains("\\"))
                {
                    startInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(exePath);
                }

                using (Process p = new Process { StartInfo = startInfo, EnableRaisingEvents = true })
                {
                    //subscribe to event and add event handler code
                    p.ErrorDataReceived += (sender, e) =>
                    {
                        if (!String.IsNullOrEmpty(e.Data))
                        {
                            //ToDo: add desired code 
                            //Debug.WriteLine("Error: " + e.Data);
                            OnErrorReceived(errMsg); //raise event
                        }
                    };

                    //subscribe to event and add event handler code
                    p.OutputDataReceived += (sender, e) =>
                    {
                        if (!String.IsNullOrEmpty(e.Data))
                        {
                            //ToDo: add desired code
                            //Debug.WriteLine("Output: " + e.Data);
                            OnOutputReceived(e.Data); //raise event
                        }
                    };

                    p.Start(); //start

                    p.BeginErrorReadLine(); //begin async reading for standard error
                    p.BeginOutputReadLine(); //begin async reading for standard output

                    //waits until the process is finished before continuing
                    p.WaitForExit();

                }
            }
            catch(System.ComponentModel.Win32Exception ex)
            {
                errMsg = "Error (Win32Exception): " + ex.Message;
                //Debug.WriteLine(errMsg);
                OnErrorReceived(errMsg);
            }
            catch(Exception ex)
            {
                errMsg = "Error: " + ex.Message;
                //Debug.WriteLine(errMsg);
                OnErrorReceived(errMsg);
            }
        }
    }
}

用法:

Helper helper = new Helper();

//subscribe to event and add event handler
helper.ProcessErrorReceived += (s, data ) =>
{
    Debug.WriteLine("helper.ProcessErrorReceived: " + data);
};

//subscribe to event and add event handler
helper.ProcessOutputReceived += (s, data) =>
{
    Debug.WriteLine("helper.ProcessOutputReceived: " + data);
};

示例 1:

helper.RunCmd("test");

示例 2:

helper.RunCmd("ipconfig", "/all");

示例 3:

helper.RunCmd(@"C:\Windows\system32\ipconfig.exe", "/all");

示例 4:

Dictionary<string, string> environmentVarsDict = new Dictionary<string, string>();
environmentVarsDict.Add("environmentVar1", "myValue1");
environmentVarsDict.Add("environmentVar2", "myValue2");

helper.RunCmd("test123", "/c", environmentVarsDict);

这篇关于我可以取消 CMD.EXE 错误消息中的 CR/CRLF 序列吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆