none
Running DOS command from windows for application

    Question

  • Hello All,

    I working on a simple windows form application to be used instead of keep writing commands to run a program with long file paths from DOS, my application is working perfect now, and produce the output file i need. The program that i am running displays a couple of lines report at the end of its run (in case i run it directly from DOS). But when i do it from my new windows application form the DOS window disappears right after it finish executing and i can read anything from the report!!! Below is my code, any help is appreciated, i tried to write the output in textbox4 , it is NOT working!!!

     

     

    Thursday, October 06, 2011 5:07 AM

Answers

  • As an afterthought, I think this case can make it a good use of extension methods:

    First creating this class in whatever namespace you use to store helper functions:

        public static class UIHelper
        {
            public static void AppendTextAsync(this TextBoxBase textbox, string text)
            {
                if (textbox.InvokeRequired)
                {
                    textbox.BeginInvoke(new Action(() => AppendTextAsync(textbox, text)));
     
                }
                else
                {
                    textbox.AppendText(text + "\r\n");
                }
            }
        }

    Now you have to compile it once, or your compiler will always prompt it can't find such method. :P

    After the compilation, and including your namespace in the From with using statement, you can update your Textbox4 with something like this:

            void mp_ErrorDataReceived(object sender, DataReceivedEventArgs e)
            {
                this.textBox4.AppendTextAsync(e.Data);
            }
    
            void mp_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                this.textBox4.AppendTextAsync(e.Data);
            }
    

    Much neater, right?






    Monday, October 10, 2011 3:39 AM

All replies

  • as last sentence

    Console.ReadLine();
    
    or 
    
    Console.ReadKey();
    


     


    Success
    Cor
    Thursday, October 06, 2011 5:30 AM
  • Thanks Cor,

    Not sure what do u mean?!

    • textbox4.text = Console.Readline() --> It didn't work the textbox remained blank.
    • textBox4.Text = Console.ReadKey() --> Cannot implicitly convert type 'System.ConsoleKeyInfo' to 'string'

     

    Thursday, October 06, 2011 6:30 AM
  • It's usually worthwhile to check MSDN library for example that can be modified for your work.

    For the problems in your code:
    1) You have to call Read functions before your WaitForExit() call or everything will be destroyed before control is returned to your application.
    2) You should not use ReadToEnd() if you would plan for redirecting stderr later in the case, as it can lead to race condition as explained in the MSDN documentation.

    Thursday, October 06, 2011 8:16 AM
  • Thanks for the link, i modified the code a bit based on what i understood, here is the new code, which is still not showing anything in the textbox, BTW, if there is a way i can prevent the command prompt from disappearing automatically that would work i guess:

     

    Thursday, October 06, 2011 3:14 PM
  • The following snippet works for me:

                string progrmname = "C:\\windows\\system32\\more.com";
                string arg = "C:\\test.txt";
    
                Process mp = new Process();
                mp.StartInfo.FileName = progrmname;
                mp.StartInfo.Arguments = arg;
                mp.StartInfo.UseShellExecute = false;
                mp.StartInfo.CreateNoWindow = false;
                mp.StartInfo.RedirectStandardInput = true;
                mp.StartInfo.RedirectStandardOutput = true;
    
                mp.Start();
                StreamReader mystreamreader = mp.StandardOutput;
    
                StringBuilder Result = new StringBuilder();
                while (!mystreamreader.EndOfStream)
                {
                    Result.AppendLine(mystreamreader.ReadLine());
                }
                textBox4.Text = Result.ToString();
                mp.WaitForExit();
                mp.Close();
    

     

    Friday, October 07, 2011 1:32 AM
  • I've rewritten the example for task running a little longer.

        public partial class Form2 : Form
        {
            delegate void SetTextCallback(string output);
    
            public Form2()
            {
                InitializeComponent();
                //Control.CheckForIllegalCrossThreadCalls = false;
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                string progrmname = "C:\\windows\\system32\\findstr.exe";
                string arg = "/s setup D:\\workspace\\*.js";
                this.textBox4.Clear();
    
                Process mp = new Process();
                mp.StartInfo.FileName = progrmname;
                mp.StartInfo.Arguments = arg;
                mp.StartInfo.UseShellExecute = false;
                mp.StartInfo.CreateNoWindow = true;
                //mp.StartInfo.RedirectStandardInput = true;
                mp.StartInfo.RedirectStandardOutput = true;
                mp.StartInfo.RedirectStandardError = true;
                mp.OutputDataReceived += new DataReceivedEventHandler(mp_OutputDataReceived);
                mp.ErrorDataReceived += new DataReceivedEventHandler(mp_ErrorDataReceived);
    
                mp.Start();
                mp.BeginOutputReadLine();
                mp.BeginErrorReadLine();
                if (!mp.HasExited) // if no output, program will end immediately and cause following WaitForExit() call blocking forever
                    mp.WaitForExit();
                mp.Close();
            }
    
            void mp_ErrorDataReceived(object sender, DataReceivedEventArgs e)
            {
                WriteOutput(e.Data);
            }
    
            void mp_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                WriteOutput(e.Data);
            }
    
            void WriteOutput(string output)
            {
                if (textBox4.InvokeRequired)
                {
                    this.textBox4.BeginInvoke(new Action(() =>  WriteOutput(output)));
                }
                else
                {
                    this.textBox4.AppendText(output + "\r\n");
                }
            }
        }

     

    • Edited by cheong00 Friday, October 07, 2011 3:24 AM
    Friday, October 07, 2011 2:33 AM
  • The following snippet works for me:

                string progrmname = "C:\\windows\\system32\\more.com";
                string arg = "C:\\test.txt";
    
                Process mp = new Process();
                mp.StartInfo.FileName = progrmname;
                mp.StartInfo.Arguments = arg;
                mp.StartInfo.UseShellExecute = false;
                mp.StartInfo.CreateNoWindow = false;
                mp.StartInfo.RedirectStandardInput = true;
                mp.StartInfo.RedirectStandardOutput = true;
    
                mp.Start();
                StreamReader mystreamreader = mp.StandardOutput;
    
                StringBuilder Result = new StringBuilder();
                while (!mystreamreader.EndOfStream)
                {
                    Result.AppendLine(mystreamreader.ReadLine());
                }
                textBox4.Text = Result.ToString();
                mp.WaitForExit();
                mp.Close();
    

     

    I tried this code as it is, works fine and returns the output of (more.com
    )in the textbox , but when i tried it with my program it did not work!!! weirdo!
    Saturday, October 08, 2011 4:20 AM
  • I've rewritten the example for task running a little longer.

        public partial class Form2 : Form
        {
            delegate void SetTextCallback(string output);
    
            public Form2()
            {
                InitializeComponent();
                //Control.CheckForIllegalCrossThreadCalls = false;
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                string progrmname = "C:\\windows\\system32\\findstr.exe";
                string arg = "/s setup D:\\workspace\\*.js";
                this.textBox4.Clear();
    
                Process mp = new Process();
                mp.StartInfo.FileName = progrmname;
                mp.StartInfo.Arguments = arg;
                mp.StartInfo.UseShellExecute = false;
                mp.StartInfo.CreateNoWindow = true;
                //mp.StartInfo.RedirectStandardInput = true;
                mp.StartInfo.RedirectStandardOutput = true;
                mp.StartInfo.RedirectStandardError = true;
                mp.OutputDataReceived += new DataReceivedEventHandler(mp_OutputDataReceived);
                mp.ErrorDataReceived += new DataReceivedEventHandler(mp_ErrorDataReceived);
    
                mp.Start();
                mp.BeginOutputReadLine();
                mp.BeginErrorReadLine();
                if (!mp.HasExited) // if no output, program will end immediately and cause following WaitForExit() call blocking forever
                    mp.WaitForExit();
                mp.Close();
            }
    
            void mp_ErrorDataReceived(object sender, DataReceivedEventArgs e)
            {
                WriteOutput(e.Data);
            }
    
            void mp_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                WriteOutput(e.Data);
            }
    
            void WriteOutput(string output)
            {
                if (textBox4.InvokeRequired)
                {
                    this.textBox4.BeginInvoke(new Action(() =>  WriteOutput(output)));
                }
                else
                {
                    this.textBox4.AppendText(output + "\r\n");
                }
            }
        }
    

     

    I am trying to to run this code as it is, it not working there is a syntax error in the line this.textBox4.BeginInvoke(new Action(() => WriteOutput(output))); i can not figure it out ,,,

    Thanks for the help :)

    Saturday, October 08, 2011 4:23 AM
  • dear Amative2:

       maybe you need to set a breakpoint and figure out what is the real value of "arg"

     


    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度
    Saturday, October 08, 2011 5:46 AM
  • Thanks Alex, 

    The point is that the program i am calling starts and finish executing correctly and the output file is correct. But this program when i run it from the CMD directly it displays 4 lines kind of report summaries the run progress. So the "arg"  is fine. I just need either to capture these lines in a textbox or to prevent the CMD from disappearing (i prefer the first option)

    Saturday, October 08, 2011 2:50 PM
  • hi Amative2

           you can use cmd.exe /k to keep command window remained.

    which meas:

    using (Process p = new Process())

    {

                    p.StartInfo.FileName = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\cmd.exe";
                    p.StartInfo.Arguments = "/k " + YourExecutionFile + " " + ParametersOfYourExecutionFile;
                    p.StartInfo.UseShellExecute = true;
                    p.Start();
    }

    remember if there is a blank in the path of your execution file, use quote properly.


    先查MSDN文件庫
    再用GOOGLE搜尋
    才到論壇來發問

    這是論壇不是技術支援中心
    沒有人得無償解答你的問題

    在標題或文章註明很急
    不會增加網友回覆速度
    Saturday, October 08, 2011 6:22 PM
  • Amative,

    Did I write the code you gave?

    Those commands simply stay empty, the process you started is not related to your texbox, it runs in its own (DOS) window.

    Be aware to get the returned value back in the textbox is easy, but in my idea in not anyway related to your question.

     


    Success
    Cor
    Saturday, October 08, 2011 6:27 PM
  • Yape... put a breakpoint at arg and step through to see what is the value.

    chanmm


    chanmm
    Sunday, October 09, 2011 4:09 AM
  • Try this:

    Public Class Form1
      
    Dim MyConsole As New CmdPnl(Me)
      
    Private Sub Form1_Shown(sender As Object, e As System.EventArgsHandles Me.Shown
        MyConsole.Parent = 
    Me
        MyConsole.Dock = 
    DockStyle.Fill
        MyConsole.TB.Text = 
    "Dir"
        MyConsole.WriteLine()
      
    End Sub
    End Class

    Public Class CmdPnl
      
    Inherits Panel
      
    Dim WithEvents P As New Process
      
    Friend WithEvents TB As New TextBox
      
    Friend WithEvents RTB As New RichTextBox
      
    Delegate Sub UpdateRTB(SelectionColor As Color, Text As String)
      
    Dim UpdateRTBDelegate As UpdateRTB = AddressOf UpdateRTBMethod
      
    Public Sub New(Parent As Form)
        SetProcess()
        TB.Parent = 
    Me
        TB.Location = 
    New Point(0, 0)
        TB.Dock = 
    DockStyle.Top
        RTB.ContextMenuStrip = 
    New ContextMenuStrip
        RTB.ContextMenuStrip.ShowImageMargin = 
    False
        
    Dim MenuItems() As String = {"Cut""Copy""Paste"}
        
    For I As Integer = 0 To MenuItems.Length - 1
          RTB.ContextMenuStrip.Items.Add(MenuItems(I))
          
    AddHandler RTB.ContextMenuStrip.Items(I).Click, AddressOf MI_Click
        
    Next
        RTB.Parent = 
    Me
        RTB.BringToFront()
        RTB.Dock = 
    DockStyle.Fill
        
    Me.Parent = Parent
      
    End Sub
      
    Sub MI_Click(ByVal sender As ObjectByVal e As EventArgs)
        
    Select Case DirectCast(sender, ToolStripMenuItem).Text
          
    Case "Cut"
            RTB.Cut()
          
    Case "Copy"
            RTB.Copy()
          
    Case "Paste"
            RTB.Paste()
        
    End Select
      
    End Sub
      
    Private Sub SetProcess()
        P.StartInfo.FileName = 
    "cmd.exe"
        P.StartInfo.Arguments = 
    "/k"
        P.StartInfo.RedirectStandardError = 
    True
        P.StartInfo.RedirectStandardInput = 
    True
        P.StartInfo.RedirectStandardOutput = 
    True
        P.StartInfo.CreateNoWindow = 
    True
        P.StartInfo.UseShellExecute = 
    False
        P.Start()
        P.BeginErrorReadLine()
        P.BeginOutputReadLine()
      
    End Sub
      
    Private Sub TB_KeyPress(ByVal sender As Object, _
                           
    ByVal e As KeyPressEventArgsHandles TB.KeyPress
        
    If e.KeyChar = Chr(13) Then
          WriteLine()
          e.Handled = 
    True
        
    End If
      
    End Sub
      
    Sub WriteLine()
        P.StandardInput.WriteLine(TB.Text)
      
    End Sub
      
    Private Sub P_ErrorDataReceived(sender As Object, _
                                      e 
    As DataReceivedEventArgsHandles P.ErrorDataReceived
        
    Me.Invoke(UpdateRTBDelegate, New Object() {Color.Red, e.Data})
      
    End Sub
      
    Private Sub P_OutputDataReceived(sender As Object, _
                                       e 
    As DataReceivedEventArgsHandles P.OutputDataReceived
        
    Me.Invoke(UpdateRTBDelegate, New Object() {Color.Green, e.Data})
      
    End Sub
      
    Sub UpdateRTBMethod(SelectionColor As Color, Text As String)
        RTB.SelectionColor = SelectionColor
        RTB.SelectedText = Text + 
    Environment.NewLine
        RTB.ScrollToCaret()
      
    End Sub
    End Class


    Sunday, October 09, 2011 5:07 AM
  • What .NET framework version you're targeting? System.Action exist as of .NET v3.5 or later.

    If you use eariler verion, you can change it to the following:

    this.textBox4.BeginInvoke(new SetTextCallback(WriteOutput), new object[] {output});

    If you see compile error, it helps if you can post the error message for us to check.


    • Edited by cheong00 Monday, October 10, 2011 1:37 AM
    Monday, October 10, 2011 1:27 AM
  • As an afterthought, I think this case can make it a good use of extension methods:

    First creating this class in whatever namespace you use to store helper functions:

        public static class UIHelper
        {
            public static void AppendTextAsync(this TextBoxBase textbox, string text)
            {
                if (textbox.InvokeRequired)
                {
                    textbox.BeginInvoke(new Action(() => AppendTextAsync(textbox, text)));
     
                }
                else
                {
                    textbox.AppendText(text + "\r\n");
                }
            }
        }

    Now you have to compile it once, or your compiler will always prompt it can't find such method. :P

    After the compilation, and including your namespace in the From with using statement, you can update your Textbox4 with something like this:

            void mp_ErrorDataReceived(object sender, DataReceivedEventArgs e)
            {
                this.textBox4.AppendTextAsync(e.Data);
            }
    
            void mp_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                this.textBox4.AppendTextAsync(e.Data);
            }
    

    Much neater, right?






    Monday, October 10, 2011 3:39 AM
  • Thank you all for your active participation in the MSDN forum!

     

    Hi Amative2,

    Welcome to the MSDN forum!

     

    How is it going with the problem?

     

    Have a nice day!


    Yoyo Jiang[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Thursday, October 13, 2011 7:31 AM