views:

328

answers:

3

I have a module that needs to run a small .Net command-line program to check for updates. Everything is working great, however I am having trouble suppressing the Command Prompt output from being shown.

The app has it's own Windows Form that it pops up if it detected an update. Updating needs to run as a seperate app due to the fact that it requires a different execution context from the DLL it is launched from.

string path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\" + AUTO_UPDATE_EXENAME;

updater.StartInfo.FileName = path;
updater.StartInfo.Arguments = AUTO_UPDATE_PARAMETERS;
updater.StartInfo.CreateNoWindow = false;
updater.StartInfo.UseShellExecute = false;
updater.StartInfo.RedirectStandardOutput = true;
updater.StartInfo.WorkingDirectory = path;

updater.Start();

I have tried most all of the different working combinations of CreateNoWindow, UseShellExecute, and RedirectStandardOutput and each of them results in that annoying black box popping up. The app does write to stdout but I only use that for debugging and the user shouldn't really see the text that it generates.

Supposedly CreateNoWindow and/or RedirectStandardOutput should prevent the box from popping up, but it does no matter how I set these variables.

+3  A: 

Set the command-line application to a Winforms Application, but don't open a form when it executes, like you usually would.

Robert Harvey
Wouldn't that prevent him from writing to stdout?
Cory Charlton
@Cory: no, why?
John Saunders
stdout isn't required anymore, I have it logging through our standard logging interface too
Tom the Junglist
This works wonderfully. Thank you!
Tom the Junglist
+2  A: 

You can hide the window on startup like this:

using System.Runtime.InteropServices;

namespace MyConsoleApp {    
    class Program    {        

        [DllImport("user32.dll")]        
        public static extern IntPtr FindWindow(string lpClassName,
                                               string lpWindowName);   

        [DllImport("user32.dll")]       
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        [STAThread()]
        static void Main(string[] args)        
        {          
            Console.Title = "MyConsoleApp";

            if (args.StartWith("-w"))            
            {                   
                // hide the console window                    
                setConsoleWindowVisibility(false, Console.Title);                   
                // open your form                    
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);                    
                Application.Run( new frmMain() );           
            }           
            // else don't do anything as the console window opens by default    
        }        

        public static void setConsoleWindowVisibility(bool visible, string title)       
        {             
            //Sometimes System.Windows.Forms.Application.ExecutablePath works  
            // for the caption depending on the system you are running under.           
            IntPtr hWnd = FindWindow(null, title); 

            if (hWnd != IntPtr.Zero)            
            {               
                if (!visible)                   
                    //Hide the window                    
                    ShowWindow(hWnd, 0); // 0 = SW_HIDE                
                else                   
                     //Show window again                    
                    ShowWindow(hWnd, 1); //1 = SW_SHOWNORMA           
             }        
        }
    }
}

http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/ea8b0fd5-a660-46f9-9dcb-d525cc22dcbd

Robert Harvey
A: 

Here's an example code that interrogates the MAC on the active connection, this is a console application, no need to make this a Windows form...

    public class TestARP
    {
        private StringBuilder sbRedirectedOutput = new StringBuilder();
        public string OutputData
        {
            get { return this.sbRedirectedOutput.ToString(); }
        }

        // Asynchronous!
        public void Run()
        {
            System.Diagnostics.ProcessStartInfo ps = new System.Diagnostics.ProcessStartInfo();
            ps.FileName = "arp";
            ps.ErrorDialog = false;
            ps.Arguments = "-a";
            ps.CreateNoWindow = true; // comment this out
            ps.UseShellExecute = false; // true
            ps.RedirectStandardOutput = true; // false
            ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; // comment this out

            using (System.Diagnostics.Process proc = new System.Diagnostics.Process())
            {
                proc.StartInfo = ps;
                proc.Exited += new EventHandler(proc_Exited);
                proc.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(proc_OutputDataReceived);
                proc.Start();
                proc.WaitForExit();
                proc.BeginOutputReadLine(); // Comment this out
            }
        }

        void proc_Exited(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("proc_Exited: Process Ended");
        }

        void proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
        {
            if (e.Data != null) this.sbRedirectedOutput.Append(e.Data + Environment.NewLine);
        }
    }

Now, look at the Run method, that is in Asynchronous mode, and runs as a single console window - in fact a normal console application with no extra window popping up, notice the comments, if you were to change those lines, it becomes a synchronous process shelling out, very quickly, you will notice that this console will create another window with the output of the command arp. Because it is in Asynchronous mode, the output gets redirected to an event handler which stuffs the data into the StringBuilder instance for further processing...

Hope this helps, Best regards, Tom.

tommieb75