Execute multiple command lines with the same process using C#

17,484

Solution 1

Your question is a little confusing but I think i see your problem. First you should check out this blog post to see common issues with System.Diagnostics.Process. Your code happens to violate one that isn't listed there. The reuse of the Process object itself.

You need to refactor the code like:

    class MyProcessStarter
    {
        private ProcessStartInfo _startInfo = new ProcessStartInfo();
        public MyProcessStarter(string exe, string workingDir)
        {
            _startInfo.WorkingDirectory = workingDir;
            _startInfo.FileName = exe;
            _startInfo.UseShellExecute = false;
            _startInfo.RedirectStandardOutput = true;
        }

        public string Run(string arguments)
        {
            _startInfo.Arguments = arguments;
            Process p = Process.Start(_startInfo);
            p.Start();
            string strOutput = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
            return strOutput;
        }
    }

I've written a more complete and accurate implementation called ProcessRunner. The following demonstrates it's usage to perform the same operation:

using CSharpTest.Net.Processes;
partial class Program
{
    static int Main(string[] args)
    {

        ProcessRunner run = new ProcessRunner("svn.exe");
        run.OutputReceived += new ProcessOutputEventHandler(run_OutputReceived);
        return run.Run("update", "C:\\MyProject");
    }

    static void run_OutputReceived(object sender, ProcessOutputEventArgs args)
    {
        Console.WriteLine("{0}: {1}", args.Error ? "Error" : "Output", args.Data);
    }
}

Solution 2

You need to READ ALL data from input, before send another command!

And you can't ask to READ if no data is avaliable... little bit suck isn't?

My solutions... when ask to read... ask to read a big buffer... like 1 MEGA...

And you will need wait a min 100 milliseconds... sample code...

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim oProcess As New Process()
        Dim oStartInfo As New ProcessStartInfo("cmd.exe", "")
        oStartInfo.UseShellExecute = False
        oStartInfo.RedirectStandardOutput = True
        oStartInfo.RedirectStandardInput = True
        oStartInfo.CreateNoWindow = True
        oProcess.StartInfo = oStartInfo
        oProcess.Start()

        oProcess.StandardInput.WriteLine("dir")


        Threading.Thread.Sleep(100)

        Dim Response As String = String.Empty

        Dim BuffSize As Integer = 1024 * 1024
        Dim bytesRead As Integer = 0

        Do

            Dim x As Char() = New Char(BuffSize - 1) {}
            bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)

            Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))            

        Loop While oProcess.StandardOutput.Peek >= 0



        MsgBox(Response)
        Response = String.Empty



        oProcess.StandardInput.WriteLine("dir c:\")




        Threading.Thread.Sleep(100)


        bytesRead = 0

        Do

            Dim x As Char() = New Char(BuffSize - 1) {}
            bytesRead = oProcess.StandardOutput.Read(x, 0, BuffSize)

            Response = String.Concat(Response, String.Join("", x).Substring(0, bytesRead))
            'Response = String.Concat(Response, String.Join("", x))

        Loop While oProcess.StandardOutput.Peek >= 0

        MsgBox(Response)


    End Sub
End Class
Share:
17,484
Amir
Author by

Amir

I am a hardworking and motivated software engineer who has acquired extensive knowledge in the field through the study of software engineering at the PhD level. I have working experience in the information technology and financial industry in the insurance sector. I am looking for a new challenge on my career path to fulfil my experience in a different career path with new opportunities. Moreover, I am keen to learn new technologies and I am a victim of developaralysis...

Updated on June 04, 2022

Comments

  • Amir
    Amir almost 2 years

    Hi according to my last question here I try to write a sql editor or some thing like this,in this way I try to connect to CMD from C# and execute my command. Now my problem is I connect to SQLPLUS after that I cant get SQLPLUS command,and the other resource I review don't satisfy me. Please help me how after I connected to sqlplus , I can a live my process to run my sql command? right now I use this code:

    //Create process
    System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
    
    //strCommand is path and file name of command to run
    pProcess.StartInfo.FileName = strCommand;
    
    //strCommandParameters are parameters to pass to program
    pProcess.StartInfo.Arguments = strCommandParameters;
    
    pProcess.StartInfo.UseShellExecute = false;
    
    //Set output of program to be written to process output stream
    pProcess.StartInfo.RedirectStandardOutput = true;
    
    //Optional
    pProcess.StartInfo.WorkingDirectory = strWorkingDirectory;
    
    //Start the process
    pProcess.Start();
    
    //Get program output
    string strOutput = pProcess.StandardOutput.ReadToEnd();
    
    //Wait for process to finish
    pProcess.WaitForExit();
    

    I customized it. I separate the initialize, I created the process object one time I still have problem, to run the second command I use these codes for the second call:

    pProcess.StartInfo.FileName = strCommand;
    
    //strCommandParameters are parameters to pass to program
    pProcess.StartInfo.Arguments = strCommandParameters;
    //Start the process
    pProcess.Start();
    
    //Get program output
    string strOutput = pProcess.StandardOutput.ReadToEnd();
    
    //Wait for process to finish
    pProcess.WaitForExit();
    

    Thanks in advance

    • and_the_rand
      and_the_rand about 14 years
      FWIW, those comments are just noise...
    • Jacques Bosch
      Jacques Bosch about 14 years
      Do you mean you want to start the process once, but send multiple commands to it? If so, why not just send multiple commands starting the whole process from scratch each time (pun not intended, but fun anyway)
    • Amir
      Amir about 14 years
      Exactly... I just run one time sqlplus after that i give user/pass and if it login send Sql.PL command. I m a little bit confusing :( actully it take time each time i try to connect DB & run my commands...but i dont have any idea,maybe other software use like this? ha?any Idea?
  • Amir
    Amir about 14 years
    Thanks dude,the first code was useful but still i have error!!! do u know ,my process run like this: I translate it to exec command: sqlplus user/pass@db sqlplus prompt "amir"; <== this line provide error! I just sqlplus running one time,and after it i just send argument and execute it... and second utility I got error!I recieve null exception pointer and also I try to use it's own testRunFile ,but on that one also same.I cant find "Assert" class anywhere??! :(( help me plzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.