0

Just an FYI this question has been re-edited to be more concise.

I am working with .NET (whether help is in C# or VB, it doesn't matter). I have a console application, something basic:

using System;

namespace ConsolePrinter
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Output");
            Console.ReadLine();
        }
    }
}

In my Winforms application, I need to redirect standard error and standard input, but NOT standard output. Standard output should continue to display in the console window. By making a simple Winforms project and starting the above console EXE as a Process object, I can still view the console's output within the summoned console. As soon as I redirect standard error, the output disappears from the console window and all that displays is a blank console.

Here is an example Winforms project:

using System;
using System.Windows.Forms;
using System.Diagnostics;

namespace winformstest2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Process proc = new Process();
            proc.StartInfo.FileName = "ConsolePrinter.exe";
            //proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.UseShellExecute = false;

            proc.Start();
        }
    }
}

This code works as intended. Uncommenting that commented line provides the error I'm talking about.

I have tried just attaching forms to a console project, but unfortunately I need to show and hide the console frequently, so starting the console application as a process is ideal. Using Win32 API was also a thought, but the user should not be able to close the entire application by closing the console, which AllocConsole() and other Win32 API calls would cause as a bi-product of their use.

Any help is appreciated, thank you!

Dan
  • 1,163
  • 3
  • 14
  • 28
  • 1
    It's not clear what's going on - when you start the commandline app, does that start *with a console window*? It would definitely be helpful to have a [mcve] (of the console app and a tiny WinForms app - it just needs a window with a button to launch the console app...) – Jon Skeet Sep 21 '16 at 16:02
  • This is a duplicate of http://stackoverflow.com/questions/4362111/how-do-i-show-a-console-output-window-in-a-forms-application. Although you'll have to convert the code to vb.net – FloatingKiwi Sep 21 '16 at 16:10
  • @JonSkeet It's a C++ program that outputs to stdout, nothing special. In a console project it outputs directly to the .net console window, with Winforms it opens a console but outputs nothing. – Dan Sep 21 '16 at 16:30
  • Rather than telling us about it, why not try to provide a [mcve] so we can reproduce it ourselves? – Jon Skeet Sep 21 '16 at 16:30
  • @FloatingKiwi: No, I don't think it's a duplicate of that - this is about launching a new process, not attaching a console to an existing one. – Jon Skeet Sep 21 '16 at 16:30
  • @JonSkeet I still don't see why that's necessary but I've edited my original post to include an example. – Dan Sep 21 '16 at 16:41
  • That exact code works fine for me in a WinForms app. We really need to be able to reproduce the problem in order to help you... – Jon Skeet Sep 21 '16 at 16:46
  • Here's the WinForms app that works for me: https://gist.github.com/jskeet/dce5d4fdba80281eaf4365ce7ed8d80a – Jon Skeet Sep 21 '16 at 16:50
  • @JonSkeet I guess I should have provided my original code. I am redirecting stderr and stdin, but not stdout. Adding code to redirect stderr and stdin makes it not work in winforms while it still works fine in a console application. – Dan Sep 21 '16 at 16:55
  • Right, and this is *precisely* why it's important to give an example that actually demonstrates the problem. So if you want to see the output, just don't redirect it... If you're saying you want to redirect it to display it within the WinForms app, then you should give an example of that. – Jon Skeet Sep 21 '16 at 16:56
  • @JonSkeet I am only redirecting stderr and stdin. Not stdout. Output should remain in the console window. – Dan Sep 21 '16 at 18:07
  • So don't redirect anything. It sounds like you have requirements that you haven't told us about... That makes it really, really hard to help you. – Jon Skeet Sep 21 '16 at 18:19
  • I've just tried my code with the redirections - and I *still* get the output... https://gist.github.com/jskeet/016d9eaa9dcd485fd2b9f1df41c68800 So now we have requirements we don't have details of, and I still can't reproduce the original problem anyway. – Jon Skeet Sep 21 '16 at 21:33
  • @JonSkeet not sure why it makes a difference to run it in Program.cs as opposed to from the form's class, but if you used that Process code on a Windows Forms project and used it in the main form's class, you'd notice it doesn't work. The console shows up but there is no output. – Dan Sep 21 '16 at 23:29
  • @KingDan: well I'll try that, but as the question author the ball is really in your court to provide code that actually reproduces the problem. I strongly suspect I'll find it still doesn't change things... – Jon Skeet Sep 22 '16 at 05:06
  • Just tried it: 1) Create new WinForms app; 2) Drag button onto form; 3) In button Click handler, use code above, including redirect. The console still shows up. I'm done trying to reproduce this in the dark - if you want help, *please* do the work to produce a [mcve] and explain all your requirements. – Jon Skeet Sep 22 '16 at 05:34
  • @JonSkeet alright thanks for your help – Dan Sep 22 '16 at 20:31
  • @JonSkeet I have edited my original post to be more concise, hopefully we can come up with a solution now – Dan Sep 22 '16 at 20:47
  • @KingDan: I still can't reproduce the problem. Using your exact code (and uncommenting the problematic line), I *always* see the console output. Perhaps this depends on the version of Windows or .NET? Have you tried the *complete* program I included in [the gist](https://gist.github.com/jskeet/016d9eaa9dcd485fd2b9f1df41c68800)? You should be able to compile it very simply with `csc /target:winexe Test.cs`. It would be interesting to know how that behaves for you. – Jon Skeet Sep 22 '16 at 20:53
  • @JonSkeet Your code works because it is being executed in Program.cs. Why this works and running directly from a form started in VS from a Winforms project doesn't work is beyond me. This may not be a code issue at all but a VS issue. I have tried working with .NET 4.0 and 4.6.1. Are you able to replicate my issue by starting a Winforms project and adding the Process code directly in the Form class? – Dan Sep 22 '16 at 21:00
  • @KingDan: I think you're completely guessing as to the relevance of `Program.cs`... especially given that as I said 15 hours ago, I've tried creating a new WinForms app and I get the exact same behaviour. Are you able to put a zip file up with a complete project somewhere? My guess is that there's *something* else that is actually significant that you're overlooking. – Jon Skeet Sep 22 '16 at 21:19
  • @JonSkeet sure here, thanks for taking a look https://drive.google.com/file/d/0B88_xFZ9dKd-YXMwQTR1ck11ZlE/view?usp=sharing – Dan Sep 22 '16 at 21:40
  • @KingDan: I think I've got it. You're running from Visual Studio, in the debugger, right? Try not doing that. Launch the executable straight from Explorer, or choose "run without debugging". I don't know why running in a debugger makes a difference, but it certainly does for me. Admittedly it not working when debugging is a pain, but at least you can move past that... – Jon Skeet Sep 22 '16 at 21:44
  • @JonSkeet You're absolutely right. If you post your comment as an answer I can give it a checkmark. Thanks for your patience and your help! I really appreciate it. – Dan Sep 22 '16 at 22:32
  • Will do so in the (UK) morning. Glad we got there in the end. – Jon Skeet Sep 22 '16 at 22:33

2 Answers2

1

It turns out that the reason I had a hard time reproducing this was that it wasn't a code problem at all - it was how the code was being run.

If you run the program in a debugger, for some reason setting RedirectStandardError to true changes the behaviour, as noted. Outside a debugger - launching the app from the command line, or Explorer, or in Visual Studio via "Start without debugging" - the output appears as desired.

The simplest way to address this is to just live without debugging when you need the output. That may be awkward, but it's likely to be simpler than the alternatives.

Another option would be to redirect everything and build your own mini-console within your WinForms app, of course. That would be neater and more generally user friendly - no extra windows popping up all over the place - but more work. Probably worth considering if this is going to be a long-term app used frequently by many people, but not worth doing otherwise.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

Using this solution should work. Note this is a Winforms application.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ConsoleExRun
{

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

        static void Main(string[] args)
        {
            AllocConsole();

            Process proc = new Process();
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.FileName = "ping";
            proc.StartInfo.Arguments = "localhost";
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardInput = true;

            proc.Start();

            Form f = new Form();
            Application.Run(f);
        }
    }
}
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
FloatingKiwi
  • 4,408
  • 1
  • 17
  • 41
  • There's no need to allocate a console to *this* process. – Jon Skeet Sep 21 '16 at 16:50
  • I'll shoot you an upvote but I've already been through this solution. Closing the console closes the entire program so I may as well just make a console project and attach forms to it. – Dan Sep 21 '16 at 16:51
  • @JonSkeet - It wasn't clear from my code but this was a winforms application. The call to AllocConsole allows the stdout to appear in the Console window. I've modified the example to make this a bit more obvious – FloatingKiwi Sep 21 '16 at 17:13
  • @FloatingKiwi: But it's unnecessary. See https://gist.github.com/jskeet/dce5d4fdba80281eaf4365ce7ed8d80a - a WinForms app that launches the console app, and at that point, the console appears. Basically, the OP is redirecting output for no known reason, and that's causing the problem. – Jon Skeet Sep 21 '16 at 17:34
  • @JonSkeet I am not redirecting output – Dan Sep 21 '16 at 18:08
  • Well, stderr is a form of output. As we've seen, without that redirection, all is fine... – Jon Skeet Sep 21 '16 at 18:20
  • @JonSkeet stderr and stdout are different streams, they don't work on the same pipe as far as i know? – Dan Sep 21 '16 at 21:23
  • @KingDan: But they're still output (as opposed to input). But all this is somewhat irrelevant as you haven't provided any information as to why you're redirecting stderr and stdin to start with... so the obvious solution is to stop doing that. If that's *not* a viable solution, then presumably that's because of a requirement you haven't told us about. – Jon Skeet Sep 21 '16 at 21:30