Not able to run interactive program using C# Process class

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • masaniparesh
    New Member
    • Apr 2008
    • 23

    Not able to run interactive program using C# Process class

    Hi Friends,

    The basic issue is "To read stdin and stdout in the same program" The following program is i have wrote using thread but i figured out that stdout is working but it is not working when application need the input.

    'myprog.pl' is the simple perlscript which ask for the your name and print the same. the execution sequence is given below:

    c:\ myprog.pl
    Enter your name: Myname
    Your name is: Myname

    When i am running this script from my C# prog given below it it is not asking for the name at all and it is giving following output;

    C:\myCSharpProg .exe
    stdin
    stdout
    Enter your name:Your name is :

    Could anyone please help me on this, it will be veryhelpful to me if any alternative method is there to achieve this.

    Thanks in Advanced,
    Megha


    Code:
    public void ProgramExecute(
    string password,
    string commandPath,
    string commandArguments)
    { 
    process = new Process(); 
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = " /c \"" +  " myprog.pl";
    process.StartInfo.RedirectStandardError = true; 
    process.StartInfo.RedirectStandardInput = true; 
    process.StartInfo.RedirectStandardOutput = true; 
    process.StartInfo.Verb = "Open"; 
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.ErrorDialog = false;
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.LoadUserProfile = true;
    // get the domain and user name parts of the current
    // windows identity
    Match identity_match = Regex.Match(
    WindowsIdentity.GetCurrent().Name,
    @"^([^\\]+)\\(.+)$");
    // domain name
    string dn = identity_match.Groups[1].Value;
    // user name
    string un = identity_match.Groups[2].Value;
    // only set the domain if it is an actual domain and
    // not the name of the local machine, i.e. a local account
    // invoking sudo
    if (!Regex.IsMatch(dn,
    Environment.MachineName, RegexOptions.IgnoreCase))
    {
    process.StartInfo.Domain = dn;
    }
    process.StartInfo.UserName = un;
    // transform the plain-text password into a
    // SecureString so that the ProcessStartInfo class
    // can use it 
    process.StartInfo.Password = new System.Security.SecureString();
    
    for (int x = 0; x < password.Length; ++x)
    process.StartInfo.Password.AppendChar(password[x]);
    process.Start(); 
    new Thread(new ThreadStart(this.readStdin)).Start(); 
    new Thread(new ThreadStart(this.readStdout)).Start(); 
    process.WaitForExit(); 
    Environment.Exit(process.ExitCode); 
    } 
    private void readStdin()
    {
    try
    {
    Console.WriteLine("stdin");
    string line;
    while ((line = Console.In.ReadLine()) != null)
    {
    process.StandardInput.WriteLine(line);
    }
    }
    catch (Exception e)
    {
    Console.Error.WriteLine(e.Message);
    }
    } 
    private void readStdout()
    {
    try
    {
    Console.WriteLine("stdout");
    int b;
    while ((b = process.StandardOutput.BaseStream.ReadByte()) != -1)
    {
    Console.Write((char)b);
    }
    }
    catch (Exception e)
    {
    Console.Error.WriteLine(e.Message);
    }
    
    }
  • Plater
    Recognized Expert Expert
    • Apr 2007
    • 7872

    #2
    You do a lot of wierd stuff.

    For instance
    Code:
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = " /c \"" +  " myprog.pl";
    Could be written as
    Code:
    process.StartInfo.FileName = "myprog.pl";
    process.StartInfo.Arguments = "";

    You are using readline and writeline, is it possible you are getting extra newline characters in there?

    Comment

    • masaniparesh
      New Member
      • Apr 2008
      • 23

      #3
      Thanks for the reply.

      But i cant change "cmd.exe" because i wants to all the commands with extensions (.msc,.pl,.cpl, .exe etc) which may not be win32 application where Process class failed to spawn process when it assigned Process.File. About "\n" i am taking care.

      Thanks,
      Paresh

      Comment

      • Plater
        Recognized Expert Expert
        • Apr 2007
        • 7872

        #4
        If CMD can be run with the arguments provided, the arguments provided will run by themselves as the processes.
        By using CMD with arguments, you are effectively just re-wrapping the application.
        It's the same as if you just ran CMD
        Then in the CMD window type your filename.

        The only things that don't work like that are commands like "dir", "cd" and other console specific commands.

        Comment

        • masaniparesh
          New Member
          • Apr 2008
          • 23

          #5
          Not able to run interactive program using C# Process class

          Hi,

          I am running inputreader.exe which is interactive program using C# program given below:

          Followin is my C# program which redirect standard output and input.

          private void mainProcess(
          string password,
          string commandPath,
          string commandArgument s)
          {
          ProcessStartInf o psi = new ProcessStartInf o(@"c:\temp\inp utreader.exe");
          psi.RedirectSta ndardOutput = true;
          psi.RedirectSta ndardInput = true;
          psi.UseShellExe cute = false;
          psi.CreateNoWin dow = true;
          Process proc = Process.Start(p si);
          StreamReader reader = proc.StandardOu tput;
          string line = "";
          while ((line = reader.ReadLine ()) != null)
          {
          Console.WriteLi ne(line);
          proc.StandardIn put.WriteLine(l ine);
          }
          }

          following is the inputreader.exe sourcecode.

          static void Main(string[] args)
          {
          try
          {
          Console.WriteLi ne("Login[]");
          Console.ReadLin e();
          Console.WriteLi ne("\r\nPasswor d[]:");
          Console.ReadLin e();
          Console.WriteLi ne("\r\nDo you wish to continue? y/n");
          string answer = Console.ReadLin e();
          if (answer.Equals( "y"))
          Console.WriteLi ne("yippie");
          else
          Console.WriteLi ne("aborting") ;
          }
          catch (Exception ex)
          {
          Console.WriteLi ne("Exception: " + ex.Message);
          }
          }

          Here C# program is not waiting while inputreader.exe needs the output and its simply proceeding and just printing the output as follow:

          C:\>MyCSharpPro g.exe
          Login[]

          Password[]:

          Do you wish to continue? y/n
          aborting

          Could anyone please help me here.

          Thanks,
          Paresh

          Comment

          • masaniparesh
            New Member
            • Apr 2008
            • 23

            #6
            You are absolutely right that Shell commands will not run.I am checking for all this commands internally in my application and showing error messages if user has specified one of these command.

            The actuall process will be argument to cmd command that also i agree with you. But to run all the extensions commands/files i has to use "cmd.exe /c" else its not possible to run all those commands.

            Here i am able to read standard output but not standard input to get the input from user. Could you tell me why it is like this? or any alternative method will be very helpful to me.

            Thanks,
            Paresh

            Comment

            • masaniparesh
              New Member
              • Apr 2008
              • 23

              #7
              (truncating for double post)
              Last edited by Plater; Apr 8 '08, 04:49 PM. Reason: truncated for double post

              Comment

              • Plater
                Recognized Expert Expert
                • Apr 2007
                • 7872

                #8
                EDIT: Please don't double post, I merged the threads.
                MODERATOR

                I just ran that program and it is running just fine?
                I should point out:
                Console.WriteLi ne(line);
                proc.StandardIn put.WriteLine(l ine);
                You are already writing something back to the input, so it's not like it's "not waiting", its that you are already writing data.


                Here is what I used for handling the redirecting:
                Code:
                private static Process proc;
                        private static void mainProcess(string password,string commandPath,string commandArguments)
                        {
                            ProcessStartInfo psi = new ProcessStartInfo(@"c:\inputreader.exe");
                            psi.RedirectStandardOutput = true;
                            psi.RedirectStandardInput = true;
                            psi.UseShellExecute = false;
                            psi.CreateNoWindow = true;
                            proc = Process.Start(psi);
                            new Thread(new ThreadStart(ShowProcStdOut)).Start();
                            new Thread(new ThreadStart(GiveProcStdIn)).Start(); 
                        }
                        private static void GiveProcStdIn()
                        {
                            string line = "";
                            try
                            {
                                StreamReader reader = new StreamReader(Console.OpenStandardInput());// proc.StandardOutput;
                                while (!reader.EndOfStream)
                                {
                                    line = reader.ReadLine();
                                    proc.StandardInput.WriteLine(line); 
                                }
                            }
                            catch (Exception e)
                            {
                                Console.Error.WriteLine("GiveProcStdIn:" + e.Message);
                            }
                        }
                        private static void ShowProcStdOut()
                        {
                            string line = "";
                            try
                            {
                                StreamReader reader = proc.StandardOutput; 
                                while (!reader.EndOfStream)
                                {
                                    line = reader.ReadLine();
                                    Console.WriteLine(line);
                                }
                            }
                            catch (Exception e)
                            {
                                Console.Error.WriteLine("ShowProcStdOut:"+e.Message);
                            }
                        }

                Comment

                • masaniparesh
                  New Member
                  • Apr 2008
                  • 23

                  #9
                  Sorry for that..I will take of that next time...

                  Simply great ....It is working fine for me. But when i run it, even the process inputreader is ended, it is not getting terminated and i have to press cntr-c to exit. I think that is because of " while (!reader.EndOfS tream)" condition is stdin thread.

                  Thanks a lot, You have taken me out from a great trouble.
                  Paresh

                  Comment

                  • masaniparesh
                    New Member
                    • Apr 2008
                    • 23

                    #10
                    Another problem with my implementation:

                    I used your suggested solution and it works great when My application directly calling the "inputreader.ex e".

                    Now consider the following scenario:

                    Assume there are following C# programs:
                    1. Client.exe
                    2. Server.exe
                    3. GetToken.exe
                    4. MainProcess.exe

                    Here Client.exe invokes the function in Server.exe and in turns this Server.exe calls GetToken.exe by generating new process using Process class. Again this GetToken.exe calls MainProcess.exe same way. And at last this MainProcess.exe is running and this is the process which is responsible to execute "inputreader.ex e" using code given by you. Here it is showing only black cmd window and not showing any output and also not asking for any inputs.

                    Much complicated...! !! Here i think problem is we lost the standard I/O handle and dont know where it is redirected.

                    Let me know if you have any questions here. Could you please help me here.

                    Thanks,
                    Paresh

                    Comment

                    • masaniparesh
                      New Member
                      • Apr 2008
                      • 23

                      #11
                      Ahhh... The solution is not working for the perl script. :( :(

                      I tried to run following simple 'interactive.pl ' perl script though your code:

                      print"Enter your name:\n";
                      $name = <STDIN>;
                      print"Your name is : $name\n";

                      C# program Working:
                      ------------------------------
                      ProcessStartInf o psi = new ProcessStartInf o("cmd.exe" , @"c:\temp\input reader\inputrea der\bin\Release \inputreader.ex e");
                      psi.RedirectSta ndardOutput = true;
                      psi.RedirectSta ndardInput = true;
                      psi.UseShellExe cute = false;
                      psi.CreateNoWin dow = true;
                      proc = Process.Start(p si);
                      new Thread(new ThreadStart(Sho wProcStdOut)).S tart();
                      new Thread(new ThreadStart(Giv eProcStdIn)).St art();


                      C# Program Not Working:
                      ------------------------------------
                      ProcessStartInf o psi = new ProcessStartInf o("cmd.exe", @"/c c:\local\intera ctive.pl");
                      psi.RedirectSta ndardOutput = true;
                      psi.RedirectSta ndardInput = true;
                      psi.UseShellExe cute = false;
                      psi.CreateNoWin dow = true;
                      proc = Process.Start(p si);
                      new Thread(new ThreadStart(Sho wProcStdOut)).S tart();
                      new Thread(new ThreadStart(Giv eProcStdIn)).St art();

                      Any thoughts??? I think I am giving you much troubles.

                      Thanks,
                      Paresh

                      Comment

                      • masaniparesh
                        New Member
                        • Apr 2008
                        • 23

                        #12
                        Sorry..I haven't appended output when I ran perl script from C# program.

                        Output:
                        ---------
                        Enter your name: //It should wait here to get the input but not waiting
                        Your name is :

                        Thanks,
                        Paresh

                        Comment

                        • masaniparesh
                          New Member
                          • Apr 2008
                          • 23

                          #13
                          Hey Plater,

                          Congratulations on your 4000 posts passes.

                          Could you please help me on this thread alone. It is very difficult and important for me.

                          Thanks,
                          Paresh

                          Comment

                          • Plater
                            Recognized Expert Expert
                            • Apr 2007
                            • 7872

                            #14
                            I am unsure why perl does not deal well with the redirection of stdio. Perhaps you could check with the Perl people?

                            Comment

                            • masaniparesh
                              New Member
                              • Apr 2008
                              • 23

                              #15
                              Ok..thats fine...Anything about #10 update ??? Any idea will be very helpful to me.

                              Thanks,
                              Paresh

                              Comment

                              Working...