Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
300 views
in Technique[技术] by (71.8m points)

c# - Can I suppress the CR/CRLF sequence in a CMD.EXE error message?

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.

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

It seems independent of the size of the command window or the length of the erroneous command, at least in an interactive 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.

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

Additionally, if you use a fully-qualified name for the program that you want to execute (ex: C:Windowssystem32ipconfig.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:Windowssystem32ipconfig.exe))
{
    System.Diagnostics.Debug.WriteLine("Error: Filename doesn't exist.");

    //ToDo: add desired code here

}

Create a class (name: Helper)

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 - raised when error messages are received
  • OnOutputReceived - raised when standard output messages are received

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);
    }
}

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

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 (complete code)

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);
            }
        }
    }
}

Usage:

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);
};

Example 1:

helper.RunCmd("test");

Example 2:

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

Example 3:

helper.RunCmd(@"C:Windowssystem32ipconfig.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...