2

I Have a GUI app that reads a console application that shows output and waits for F4 to exit, I've managed to launch the process with:

p.StartInfo.FileName = "consoleapp.exe";
p.StartInfo.RedirectStandardOutput = false;
p.StartInfo.RedirectStandardInput = false;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = false; 
p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(ConsoleOutputHandler);
p.Start();
p.BeginOutputReadLine();

And I can send F4 using:

PostMessage(p.MainWindowHandle, (uint)WM_KEYUP, (IntPtr) Keys.F4, (IntPtr) 0x3E0001 );

Everything works fine until I redirect StandardOutput with:

p.StartInfo.RedirectStandardOutput = true;

That way PostMessage still send the event (checked by Spy++), but the console app doesn't recognize it.

Changing "RedirectStandardInput" didn't make any progress.

Any thoughts?

Eugene Podskal
  • 10,270
  • 5
  • 31
  • 53
Nilson Morais
  • 821
  • 1
  • 7
  • 6
  • try looking at this Stackoverflow post for a working solution hope it solves your problem http://stackoverflow.com/questions/1145969/processinfo-and-redirectstandardoutput – MethodMan Jan 24 '13 at 20:49
  • In fact I don't have problem reading stdout, just PostMessage that stops work when I redirect output. Thanks for the comment. – Nilson Morais Jan 24 '13 at 22:17
  • I tried to redirect and write to stdin using StreamWriter, but didn't worked too. – Nilson Morais Jan 24 '13 at 22:24

2 Answers2

1

I did it!

I run this on my app start:

AllocConsole();
uint codepage = GetACP();
SetConsoleOutputCP(codepage);

IntPtr handleconsole = new IntPtr();
handleconsole = GetConsoleWindow();

then create the process with..

p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.RedirectStandardInput = false; 
p.StartInfo.RedirectStandardError = true;

That creates a console for my app, after doing that every process started inherits that console, so it's easy to read stdout, even if you call ShowWindow to hide it.

After that, I created a INPUT_RECORD to send F4 key:

inHandle = GetStdHandle(STD_INPUT_HANDLE);
record[0].EventType = KEY_EVENT;
record[0].KeyEvent.bKeyDown = true;
record[0].KeyEvent.dwControlKeyState = 0;
record[0].KeyEvent.wRepeatCount = 1;
record[0].KeyEvent.wVirtualKeyCode = VirtualKeys.F4;
record[0].KeyEvent.wVirtualScanCode = MapVirtualKey(VK_F4, MAPVK_VK_TO_VSC);

record[1].EventType = KEY_EVENT;
record[1].KeyEvent.bKeyDown = false;
record[1].KeyEvent.dwControlKeyState = 0;
record[1].KeyEvent.wRepeatCount = 1;
record[1].KeyEvent.wVirtualKeyCode = VirtualKeys.F4;
record[1].KeyEvent.wVirtualScanCode = MapVirtualKey(VK_F4, MAPVK_VK_TO_VSC);

WriteConsoleInput(inHandle, record, 1, out written);
Nilson Morais
  • 821
  • 1
  • 7
  • 6
0

You probably don't want to use PostMessage for this. Since your target is a console application, you should write the key to its input buffer using the Win32 API WriteConsoleInput via p/invoke, along the following lines:

p.StartInfo.RedirectStandardInput = true ;
// the rest of your code 

int written ;
var record = new KEY_INPUT_RECORD
{
    EventType = KEY_EVENT,
    bKeyDown  = true,
    wVirtualKeyCode = VK_F4,
    // maybe set other members, use ReadConsoleInput 
    // to get a sample and hard-code it
    // you might even use a byte array representation
    // of the input record, since you only need one key
} ;

WriteConsoleInput (((FileStream)p.StandardInput.BaseStream).SafeFileHandle,
    ref record, 1, out written) ;
Anton Tykhyy
  • 19,370
  • 5
  • 54
  • 56
  • I tried WriteConsoleInput but isn't working yet, I've got the Console Handle and the result says that it wrote on Console but no response from ConsoleApp. I'll keep trying. Thanks for the answer. – Nilson Morais Jan 28 '13 at 13:24