locked
Using a Console with a Windows Form... RRS feed

  • Question

  • Alright, I've been searching but I can't find anything related to my question... I need to use a Console with my Windows Form (for debug purposes). How do I "add" a Console?

    Another thing... I need to find out how to make a rich text box unwritable.

    Thanks!

    Sunday, August 13, 2006 10:22 PM

Answers


  • You can dynamically create and destroy a console window using PInvoke to call the Windows API:




    [DllImport("kernel32.dll",SetLastError=true)]
    [return: MarshalAs( UnmanagedType.Bool )]
    static extern bool AllocConsole();

    [DllImport("kernel32.dll",SetLastError=true)]
    [return: MarshalAs( UnmanagedType.Bool )]
    static extern bool FreeConsole();

     

    Just declare those, and then call AllocConsole() to create a console and FreeConsole() to get rid of it. While you have a console, Console.WriteLine() etc will work.
    Monday, August 14, 2006 2:52 PM

All replies

  • To write debug information while running a Windows Application containing form, you may use a custom Console to print console output. Console can take a output stream where it can write console message. You can set a output stream in the following way:


      Console.SetOut(new ConsoleWriter(rtxtConsole));

    Where ConsoleWriter is a custom stream writer into which the console message will be printed. Here is the ConsoleWriter code:


    public class ConsoleWriter:

    TextWriter
    {
    private System.Windows.Forms.RichTextBox rTextBox;
    public ConsoleWriter(System.Windows.Forms.RichTextBox textBox)
    {
    this.rTextBox = textBox;
    }

    public override void WriteLine(string str)
    {
    this.rTextBox.AppendText(str + "\n");
    }
    public override System.Text.Encoding Encoding
    {
     get
    { return System.Text.Encoding.ASCII; }
    }
    }

     

    As you notice that the ConsoleWriter's constructor takes a parameter of type System.Windows.Forms.RichTextBox; on invocation of WriteLine() method in it, it will print the same message into that rich text box.

    Now you will need to have a form (let's name it 'frmMain') and follow these steps:

    • Drag a rich text box control and name it 'rtxtConsole' (for example)
    • Sets its 'ReadOnly' property to true as you wanted to make it nonwritable (from the property sheet)
    • Within your frmMain's constructor, write the following code:

    public frmMain()
    {
    InitializeComponent();
    Console.SetOut(new ConsoleWriter(rtxtConsole));
    Console.WriteLine("Application started..");
    }

     

    When you first run the application, you will see the line 'Application started..' in the rich text box, already you have in your form!

    Please note that, only invoking the WriteLine(string) on Console object will print the message on the text box, to support additional method, such as Write(), which has 17 overloads, you need to enhance the class ConsoleWriter by overriding Write() method (Write() method has 16 overloades those you can override).

    Hope this will help.

    Cheers

    • Proposed as answer by EdgarTaor Thursday, March 10, 2011 3:43 AM
    Monday, August 14, 2006 7:32 AM
  • Another easier (but not a pretty) way is just to set your program as a console application (by pulling up the properties of the project). It will create a console window as well as your form.

    Monday, August 14, 2006 9:00 AM

  • You can dynamically create and destroy a console window using PInvoke to call the Windows API:




    [DllImport("kernel32.dll",SetLastError=true)]
    [return: MarshalAs( UnmanagedType.Bool )]
    static extern bool AllocConsole();

    [DllImport("kernel32.dll",SetLastError=true)]
    [return: MarshalAs( UnmanagedType.Bool )]
    static extern bool FreeConsole();

     

    Just declare those, and then call AllocConsole() to create a console and FreeConsole() to get rid of it. While you have a console, Console.WriteLine() etc will work.
    Monday, August 14, 2006 2:52 PM
  • I am also looking for a solution for this problem. But the solutions above do not work. I have tried it already. The richtextbox variant looks nice, but is not working if you want to create a batch like program.

    I made a program that can be used interactively and in batch (-verbose). When in batch mode, I want the console output redirected to for example a file or just the console.

    Tuesday, August 15, 2006 8:35 AM
  • It sounds like you have a slightly different requirement - you want the output to (optionally) go to the existing console (from which the program is run), or for it to run with a UI.

    If you try the approach where you use a console app that creates a form, presumably you find that running it from the command line will "stall" that command line until the form is closed.

    Is that the problem?

    If so, there is no easy solution. Some people solve it by using TWO programs. The one that the user runs is a console app. If  the command line parameters dictate that it should run in form mode, it starts the form-based version of the program, and the console mode one exits, leaving the form-based version running.

    To avoid duplicate code, the form based app can call methods defined in the console version, or vice versa. (You can't have each calling methods defined in the other though - that would cause a circular dependency problem.)




    Tuesday, August 15, 2006 8:48 AM
  • I have another question related to this. If I allocate a console using the AllocConsole() call, and then close this console by clicking the Close button in the upper right corner, the application that created (Allocated) the console also exits (shuts down)... is there a way of preventing this from happening. Allocating the Console on a different thread? Checking the message que?
    Wednesday, August 16, 2006 3:26 AM
  • Haven't had a lot of luck with that. Closest I can get is this:



    // Delegate type to be used as the Handler Routine for SCCH

    delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType);

    // Enumerated type for the control messages sent to the handler routine

    enum CtrlTypes: uint
    {

        CTRL_C_EVENT=0,
        CTRL_BREAK_EVENT,
        CTRL_CLOSE_EVENT,
        CTRL_LOGOFF_EVENT=5,
        CTRL_SHUTDOWN_EVENT
    }

    [DllImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);

    private static bool ctrlHandler(CtrlTypes CtrlType)
    {
        if ((CtrlType == CtrlTypes.CTRL_C_EVENT) || (CtrlType == CtrlTypes.CTRL_BREAK_EVENT))
        {
            FreeConsole();
            return true;
        }

        if (CtrlType == CtrlTypes.CTRL_CLOSE_EVENT)
            return true;

        return false;
    }

     


    That let's the user press Ctrl-C to close the console, but clicking the console's close button will bring up a "program is not responding" message.

    Perhaps you may be able to tweak the code or find something better on the net. If you do, let me know. :)

    Wednesday, August 16, 2006 9:06 AM
  • I have a little problem with this.
    I attached the AllocConsole function to a button. When i click on the button the console opens, but i wrote a Console.WriteLine("asd") after the AllocConsole(), and the "asd" doesn't appear in the console window. :S
    I now tryed everything, and it's doesn't work. :(
    Sunday, November 8, 2009 2:41 PM
  • Use the program to compile the program using csc *.cs /target:winexe

    Then you can use the Console.WriteLine commands.

    Tuesday, March 8, 2011 2:07 AM
  • This was very useful and quite simple to implement. Thanks.
    I share my code for a Texbox control in WPF:

    http://www.mediafire.com/?4wwxo71mrr0vtwo 

    Thursday, March 10, 2011 4:08 AM