160

I'm using Console.WriteLine() from a very simple WPF test application, but when I execute the application from the command line, I'm seeing nothing being written to the console. Does anyone know what might be going on here?

I can reproduce it by creating a WPF application in VS 2008, and simply adding Console.WriteLine("text") anywhere where it gets executed. Any ideas?

All I need for right now is something as simple as Console.WriteLine(). I realize I could use log4net or somet other logging solution, but I really don't need that much functionality for this application.

Edit: I should have remembered that Console.WriteLine() is for console applications. Oh well, no stupid questions, right? :-) I'll just use System.Diagnostics.Trace.WriteLine() and DebugView for now.

riQQ
  • 9,878
  • 7
  • 49
  • 66
Rob
  • 25,984
  • 32
  • 109
  • 155
  • Possible duplicates [here](http://stackoverflow.com/questions/3057852/how-do-i-write-to-command-line-from-a-wpf-application/3058921#3058921) and [here](http://stackoverflow.com/questions/10415807/output-console-writeline-from-wpf-windows-applications-to-actual-console) (newer, but with some interesting answers using [AttachConsole from Kernel32.dll](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681952%28v=vs.85%29.aspx)) – Max Jun 22 '15 at 16:01
  • 3
    @Max, those questions are possible duplicates of *this* question. This question was asked 2-4 years before either of those questions you posted. – Rob Jun 22 '15 at 20:42
  • This isn't a stupid question at all @Rob. Over the years I've seen Debug and Console change roles a number of times. – Hey Mikey Jul 31 '22 at 17:50

9 Answers9

216

You can use

Trace.WriteLine("text");

This will output to the "Output" window in Visual Studio (when debugging).

make sure to have the Diagnostics assembly included:

using System.Diagnostics;
Phobis
  • 7,524
  • 10
  • 47
  • 76
  • 10
    this is the best answer, but has not the highest rating – kiltek Oct 19 '13 at 09:33
  • I agree - this is exactly what op is asking for. Great alternative to Console.WriteLine() - the solution marked as the answer is a neat exercise but unreasonable to include in a production application. – Shawn J. Molloy Nov 23 '13 at 23:01
  • 5
    PS for Windows Store apps (Windows Runtime) the equivalent of Trace.WriteLine is Debug.WriteLine() – Shawn J. Molloy Nov 23 '13 at 23:05
  • This is a simple, clean solution, however didn't work for me. Didn't work in entity framework's seed method during update-database. Otherwise, works everywhere else! – Charles W Mar 07 '14 at 15:19
  • 1
    This is the best solution. Would be better if the answer also explained that `Console.WriteLine` is not intended for WPF applications at all, and that it is intended only for command-line apps. – Andrew Koster Mar 20 '20 at 20:38
  • Perfect, but no "tw(tab)(tab)" output which is just a pain. – rayzinnz Apr 01 '22 at 00:16
  • Key point here is "when debugging". It won't work if you run without debugging. – user32882 Jun 07 '22 at 12:42
154

Right click on the project, "Properties", "Application" tab, change "Output Type" to "Console Application", and then it will also have a console, the WPF Applications still runs as expected (even if the Application output type is switched to "Console Application").

Tom
  • 357
  • 1
  • 5
  • 18
Brian
  • 117,631
  • 17
  • 236
  • 300
  • 3
    The only issue with that is you will have a cmd open in the background, but it works :). – ykatchou May 02 '12 at 09:22
  • 5
    Great, but command-line window will be created when application is not executed from cmd.exe (two windows created for one application). But for this there is also solution: you can hide cmd window by ShowWindow(hWnd, 0). http://stackoverflow.com/a/10416180/1457197 . Using this solution you will see text in console only when WPF application is executed from command-line. – CoperNick May 09 '13 at 17:44
  • Note you'll have to switch it back to "Window Application" while working in Blend, as it only shows XAML (with no access to the Design View) for "Console Application" types. (as of Blend 2013) –  Oct 07 '14 at 22:12
  • 3
    Not correct ans. Hides main Windows. Just console comes up. – Yash Jul 25 '15 at 16:27
  • Thanks! This solution is MUST when you do what @John Leidegren showed in the answer above – gil123 Dec 05 '20 at 15:50
  • 2
    For people not using Visual Studio, set `Exe` instead of `WinExe` in your csproj file (see here https://learn.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-properties?view=vs-2022). – AvahW Aug 10 '22 at 08:48
  • right click where? 'project' is pretty vague... I don't see any application tab – john k Mar 11 '23 at 16:14
102

You'll have to create a Console window manually before you actually call any Console.Write methods. That will init the Console to work properly without changing the project type (which for WPF application won't work).

Here's a complete source code example, of how a ConsoleManager class might look like, and how it can be used to enable/disable the Console, independently of the project type.

With the following class, you just need to write ConsoleManager.Show() somewhere before any call to Console.Write...

[SuppressUnmanagedCodeSecurity]
public static class ConsoleManager
{
    private const string Kernel32_DllName = "kernel32.dll";

    [DllImport(Kernel32_DllName)]
    private static extern bool AllocConsole();

    [DllImport(Kernel32_DllName)]
    private static extern bool FreeConsole();

    [DllImport(Kernel32_DllName)]
    private static extern IntPtr GetConsoleWindow();

    [DllImport(Kernel32_DllName)]
    private static extern int GetConsoleOutputCP();

    public static bool HasConsole
    {
        get { return GetConsoleWindow() != IntPtr.Zero; }
    }

    /// <summary>
    /// Creates a new console instance if the process is not attached to a console already.
    /// </summary>
    public static void Show()
    {
        //#if DEBUG
        if (!HasConsole)
        {
            AllocConsole();
            InvalidateOutAndError();
        }
        //#endif
    }

    /// <summary>
    /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
    /// </summary>
    public static void Hide()
    {
        //#if DEBUG
        if (HasConsole)
        {
            SetOutAndErrorNull();
            FreeConsole();
        }
        //#endif
    }

    public static void Toggle()
    {
        if (HasConsole)
        {
            Hide();
        }
        else
        {
            Show();
        }
    }

    static void InvalidateOutAndError()
    {
        Type type = typeof(System.Console);

        System.Reflection.FieldInfo _out = type.GetField("_out",
            System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);

        System.Reflection.FieldInfo _error = type.GetField("_error",
            System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);

        System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
            System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);

        Debug.Assert(_out != null);
        Debug.Assert(_error != null);

        Debug.Assert(_InitializeStdOutError != null);

        _out.SetValue(null, null);
        _error.SetValue(null, null);

        _InitializeStdOutError.Invoke(null, new object[] { true });
    }

    static void SetOutAndErrorNull()
    {
        Console.SetOut(TextWriter.Null);
        Console.SetError(TextWriter.Null);
    }
} 
John Leidegren
  • 59,920
  • 20
  • 131
  • 152
  • I like this, it works, & I can use this in other projects. However because it launches a new console window it causes an issue with a current project. If I pass in command line options would like to be able to output to the console that it was launched from so the user gets the output there. In my app if command line options are provided it stays a console app and then does its work and then exits. This allows for the app to be automated and schedule to do tasks, or the user can just do something quickly and get out. However I want to output some things , like the help usage stuff, etc. – Rodney S. Foley Jan 29 '10 at 23:56
  • Is it possible to embed the console window within a WPF window using this or any other technique? – InfinitiesLoop Jul 19 '10 at 16:53
  • Why would you want to do this? After all -- it won't look good, and I can easily make WPF control to have the same features (but it would look better). – greenoldman Aug 26 '10 at 10:08
  • 9
    It's possible to try to call AttachConsole(-1) first and check its return value to attach to the parent process' console; if it returns false, call AllocConsole. However, the application still 'returns' first and only then outputs to the console, I'll post more if I find a solution. Also, if you set the WPF app type to Console Application, the problem disappears but you can't detach the console without it showing on the screen briefly when the program is started, so it kinda looks awkward (but if you can live with it, it works great). – Alex Paven Dec 16 '10 at 08:25
  • 4
    Eh, actually no, I don't think it's possible to have it both ways; a Console application is marked as CUI in its PE header and thus cooperates well with CMD automatically. A GUI application on the other hand returns control to CMD immediately, and even if it can reattach to the console, reading and writing will be intermingled with the next outputs in the pipeline, which is obviously very bad. If on the other hand you mark the application as Console application, you only have to live with CMD showing briefly at app startup; you can then use FreeConsole to detach and Attach/Alloc later etc – Alex Paven Dec 16 '10 at 10:33
  • 1
    Why do this when the answer from Brian works as well and much easier. – Wouter Janssens Feb 10 '12 at 09:55
  • 2
    Might be obvious, but I found that Console.WriteLine still did not work using this technique when the Visual Studio debugger was attached. When I ran the app outside of VS it worked a treat. Thanks. – aboy021 Mar 15 '13 at 05:53
  • Problem with using this Apporach is that when you close this Console from close button, the whole application closes. – Mark Aug 22 '13 at 12:45
  • @Mark I know, that sucks but that's not necessarily a limitation of Windows and I actually do believe that it's possible to detach the console from the process in such a way that this does not happen. Anyway, if you really want an interactive console session with your app, just roll your own GUI, it's going to be superior to the ConHost either way. This really just is something you can do, if you want to and not something that's particularly great. It does work but I don't think it's what you ought to really be doing... – John Leidegren Aug 23 '13 at 07:26
  • @John Leidegren any lead to help me on deattaching the consle from the process as I am new to this ? will be much apperciated :) I created a question for this that can be found here : http://stackoverflow.com/questions/18378804/closing-console-window-from-wpf?noredirect=1#comment26988949_18378804 – Mark Aug 26 '13 at 07:33
  • 2
    @Mark Yeah, but it doesn't work... There's a `SetConsoleCtrlHandler` function that allows to be notified when the `CTRL_CLOSE_EVENT` event happens but you can't do anything with it, there's nothing that's allowing your application to continue. You will be shut down. If you feel like hacking, you could probably swap the windows message handler for the console process and just drop the WM_CLOSE message, I have never tried this but it could work. It's just another window but with that said, unless you want to entertain this idea you effort is probably better spent doing something else. – John Leidegren Aug 27 '13 at 18:08
  • Fantastic. Works for me, in VS 2013 over Win Pro 8.1. Good apport!! – Bull Aug 10 '15 at 10:22
  • Even though everyone uses the other solution where to convert the app to Console Application, I really prefer this solution. – Everyone Jan 19 '17 at 03:21
  • finally something that works, many thanks. it's an absolute shame how VS makes it so terribly confusing and intricate to just monitor console output. -100 for microsoft – alp Aug 13 '20 at 15:09
  • If I start the app from cmd, do I still need this? – ed22 Dec 08 '20 at 11:57
29

Old post, but I ran into this so if you're trying to output something to Output in a WPF project in Visual Studio, the contemporary method is:

Include this:

using System.Diagnostics;

And then:

Debug.WriteLine("something");
Smitty
  • 1,765
  • 15
  • 22
15

Although John Leidegren keeps shooting down the idea, Brian is correct. I've just got it working in Visual Studio.

To be clear a WPF application does not create a Console window by default.

You have to create a WPF Application and then change the OutputType to "Console Application". When you run the project you will see a console window with your WPF window in front of it.

It doesn't look very pretty, but I found it helpful as I wanted my app to be run from the command line with feedback in there, and then for certain command options I would display the WPF window.

13

It's possible to see output intended for console by using command line redirection.

For example:

C:\src\bin\Debug\Example.exe > output.txt

will write all the content to output.txt file.

Ilya Serbis
  • 21,149
  • 6
  • 87
  • 74
  • Best answer as it is simple and doesn't require changes to the source – buckley Jan 07 '20 at 13:08
  • 1
    ... and of course, the next step is to open the file in notepad++ and select 'View -> Monitoring (tail -f)' to watch it update in real time – mcalex Sep 15 '20 at 07:05
4

I use Console.WriteLine() for use in the Output window...

erodewald
  • 1,815
  • 20
  • 45
  • 5
    It's a 4 year old question that's been edited heavily since I first saw it. Now of course the question has been better worded and my response was made irrelevant. – erodewald May 02 '12 at 16:42
4

Brian's solution is to always open a console when your WPF application starts. If you want to dynamically enable console output (for example, only when launched with certain commandline arguments) call AttachConsole:

[DllImport("kernel32.dll")]
static extern bool AttachConsole(uint dwProcessId);

const uint ATTACH_PARENT_PROCESS = 0x0ffffffff;

Then, when you want to start writing to the console:

AttachConsole(ATTACH_PARENT_PROCESS);
Console.WriteLine("Hello world!");
Console.WriteLine("Writing to the hosting console!");
Bip901
  • 590
  • 6
  • 22
  • This solution seems works, but if you write something like "yourapp.exe > result.txt" You will notice that the output does not redirect to the file. – Leo Li Jan 19 '23 at 10:41
  • i couldnt figure out where to put this code. everywhere I tried gave me an error – john k Mar 11 '23 at 16:24
  • @johnk The first part should go inside a class, outside of any functions. The second part should be in the function where you want to write to the console. – Bip901 Mar 11 '23 at 17:47
2

I've create a solution, mixed the information of varius post.

Its a form, that contains a label and one textbox. The console output is redirected to the textbox.

There are too a class called ConsoleView that implements three publics methods: Show(), Close(), and Release(). The last one is for leave open the console and activate the Close button for view results.

The forms is called FrmConsole. Here are the XAML and the c# code.

The use is very simple:

ConsoleView.Show("Title of the Console");

For open the console. Use:

System.Console.WriteLine("The debug message");

For output text to the console.

Use:

ConsoleView.Close();

For Close the console.

ConsoleView.Release();

Leaves open the console and enables the Close button

XAML

<Window x:Class="CustomControls.FrmConsole"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:CustomControls"
    mc:Ignorable="d"
    Height="500" Width="600" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Topmost="True" Icon="Images/icoConsole.png">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="40"/>
    </Grid.RowDefinitions>
    <Label Grid.Row="0" Name="lblTitulo" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" FontFamily="Arial" FontSize="14" FontWeight="Bold" Content="Titulo"/>
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="10"/>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="1" Name="txtInner" FontFamily="Arial" FontSize="10" ScrollViewer.CanContentScroll="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" TextWrapping="Wrap"/>
    </Grid>
    <Button Name="btnCerrar" Grid.Row="2" Content="Cerrar" Width="100" Height="30" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center"/>
</Grid>

The code of the Window:

partial class FrmConsole : Window
{
    private class ControlWriter : TextWriter
    {
        private TextBox textbox;
        public ControlWriter(TextBox textbox)
        {
            this.textbox = textbox;
        }

        public override void WriteLine(char value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value.ToString());
                textbox.AppendText(Environment.NewLine);
                textbox.ScrollToEnd();
            }));
        }

        public override void WriteLine(string value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value);
                textbox.AppendText(Environment.NewLine);
                textbox.ScrollToEnd();
            }));
        }

        public override void Write(char value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value.ToString());
                textbox.ScrollToEnd();
            }));
        }

        public override void Write(string value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value);
                textbox.ScrollToEnd();
            }));
        }

        public override Encoding Encoding
        {
            get { return Encoding.UTF8; }

        }
    }

    //DEFINICIONES DE LA CLASE
    #region DEFINICIONES DE LA CLASE

    #endregion


    //CONSTRUCTORES DE LA CLASE
    #region CONSTRUCTORES DE LA CLASE

    public FrmConsole(string titulo)
    {
        InitializeComponent();
        lblTitulo.Content = titulo;
        Clear();
        btnCerrar.Click += new RoutedEventHandler(BtnCerrar_Click);
        Console.SetOut(new ControlWriter(txtInner));
        DesactivarCerrar();
    }

    #endregion


    //PROPIEDADES
    #region PROPIEDADES

    #endregion


    //DELEGADOS
    #region DELEGADOS

    private void BtnCerrar_Click(object sender, RoutedEventArgs e)
    {
        Close();
    }

    #endregion


    //METODOS Y FUNCIONES
    #region METODOS Y FUNCIONES

    public void ActivarCerrar()
    {
        btnCerrar.IsEnabled = true;
    }

    public void Clear()
    {
        txtInner.Clear();
    }

    public void DesactivarCerrar()
    {
        btnCerrar.IsEnabled = false;
    }

    #endregion  
}

the code of ConsoleView class

static public class ConsoleView
{
    //DEFINICIONES DE LA CLASE
    #region DEFINICIONES DE LA CLASE
    static FrmConsole console;
    static Thread StatusThread;
    static bool isActive = false;
    #endregion

    //CONSTRUCTORES DE LA CLASE
    #region CONSTRUCTORES DE LA CLASE

    #endregion

    //PROPIEDADES
    #region PROPIEDADES

    #endregion

    //DELEGADOS
    #region DELEGADOS

    #endregion

    //METODOS Y FUNCIONES
    #region METODOS Y FUNCIONES

    public static void Show(string label)
    {
        if (isActive)
        {
            return;
        }

        isActive = true;
        //create the thread with its ThreadStart method
        StatusThread = new Thread(() =>
        {
            try
            {
                console = new FrmConsole(label);
                console.ShowDialog();
                //this call is needed so the thread remains open until the dispatcher is closed
                Dispatcher.Run();
            }
            catch (Exception)
            {
            }
        });

        //run the thread in STA mode to make it work correctly
        StatusThread.SetApartmentState(ApartmentState.STA);
        StatusThread.Priority = ThreadPriority.Normal;
        StatusThread.Start();

    }

    public static void Close()
    {
        isActive = false;
        if (console != null)
        {
            //need to use the dispatcher to call the Close method, because the window is created in another thread, and this method is called by the main thread
            console.Dispatcher.InvokeShutdown();
            console = null;
            StatusThread = null;
        }

        console = null;
    }

    public static void Release()
    {
        isActive = false;
        if (console != null)
        {
            console.Dispatcher.Invoke(console.ActivarCerrar);
        }

    }
    #endregion
}

I hope this result usefull.