views:

296

answers:

2

Hi, I have a winform app that is writing to console and it seems to work well. I'm using this code:

AttachConsole(-1)
 Console.Out.WriteLine("Hellow world")
  FreeConsole()

The question is: If I run the app's exe file from command line, and try to redirect the output into a file. It doesn't work. For example:

C:\ > myapp.exe > c:\output.txt

I still get the output to console screen (c:\output.txt file is created but empty), but I want it to to be saved into c:\output.txt What's going wrong ? How to do that?

Many thanks!

A: 

You are attaching to the parent process to provide output, which in your case is probably cmd.exe. The parent process' stdout stream has not been redirected and therefore continues to display the output on the screen.

I am not aware of a direct approach. If you do not call AttachConsole you will find that the redirect works as expected, but of course then you loose the option to have a console window. However, there is a work around that I think is reasonable.

If you want the output to go to a console window then you provide your application with a commandline switch that indicates this requirement, something like

C:\> myapp.exe /console

When the /console argument is present you call AttachConsole and the output will be written to the console. When this switch is not present you do not make the call to AttachConsole and you will be able to redirect the output to a file.

Chris Taylor
That sounds true. So what should I do to resolve it..?Thanks
Dave
@emc2, please see my edit for a possible solution that might suite your requirement.
Chris Taylor
Thanks! I'm going to use this approach. Is there a way to figure out if the command-line contains redirects (> >>) signs?I tried to figure it our by using "Environment.GetCommandLineArgs" but it seems not to find it.If I could find if it contains redirect signs, it would be much better for me than "/console" switch.Thanks!
Dave
@emc2, the redirects are handled by the shell (cmd.exe) so by the time the commandline reaches your application the redirects are already stripped from the commandline. I have not tried this, but you could detect that the output has been redirected by comparing the output handle to the standard output handle. The standard output handle can be found by using CreateFile to open "CONOUT$", here is a post of mine that could help you with this. http://stackoverflow.com/questions/3173750/deleting-previously-written-lines-in-console/3174089#3174089
Chris Taylor
+1  A: 

You can have your cake and eat it too if you first check if output was redirected. Here's a little helper class that contains the P/Invoke voodoo:

using System;
using System.Runtime.InteropServices;

public static class ConsoleEx {
    public static bool OutputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
    }
    public static bool InputRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
    }
    public static bool ErrorRedirected {
        get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stderr)); }
    }

    // P/Invoke:
    private enum FileType { Unknown, Disk, Char, Pipe };
    private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
    [DllImport("kernel32.dll")]
    private static extern FileType GetFileType(IntPtr hdl);
    [DllImport("kernel32.dll")]
    private static extern IntPtr GetStdHandle(StdHandle std);
}

Usage:

bool redir = ConsoleEx.OutputRedirected;
if (!redir) AttachConsole(-1);
// etc...
Hans Passant
Thanks. Can you provide link the equivalent code for VB.NET ?
Dave
Thanks. Can you provide the link for the same code in VB.NET? Or how to use it with VB.NET ?
Dave
Hmm, a link. This code is original, my brain isn't online yet. Here's one: http://www.developerfusion.com/tools/convert/csharp-to-vb/
Hans Passant
Thanks Hans. I translated it to VB and tried it. It always returns true even when not redirected...
Dave