Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When run a program in C#, all the messages go to the standard output, but the standard error contains nothing

My question is different with the one identified. Obviously I have called "BeginErrorReadLine" method (I mark it in the code below).

I want to parse the result produced by Handle


Command line

When run in a command line environment, it will output something like:

> handle64 -p [PID]

 

Nthandle v4.11 - Handle viewer

Copyright (C) 1997-2017 Mark Russinovich

Sysinternals - www.sysinternals.com

 

  10: File     C:\Windows

  1C: File     C:\Windows\SysWOW64

[PID] is any running process ID

The output is seperated.

First 5 lines (include empty lines) go to the standard error, last 2 lines go to the standard output.

So I can strip the header by redirecting:

> handle64 -p [PID] 2>nul

  10: File     C:\Windows

  1C: File     C:\Windows\SysWOW64


Winform application

Then I try to implement this command in a C# winform application:

Stream streamOut, streamErr;

var p = Process.Start(new ProcessStartInfo
{
    FileName = "handle64.exe",
    Arguments = "-p [PID]",
    CreateNoWindow = true,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
});

p.OutputDataReceived += (sender, e) =>
{
    streamOut.Write("Output => " + e.Data);
};

p.ErrorDataReceived += (sender, e) =>
{
    streamErr.Write("Error => " + e.Data);
};

p.BeginOutputReadLine();
p.BeginErrorReadLine(); // !!!
p.WaitForExit();

Then I find everything go to the standard output.


Question

Ok, I can seperate the header and the body by code.

The question is why the program's output behaves different between the 2 environments?

Can I make the result in the winform application behaves like it in the command line?


Update

For Damien's comment, I try to run the program via 'cmd', unfortunately I get the same result:

var p = Process.Start(new ProcessStartInfo
{
    FileName = "cmd",
    Arguments = "/C handle64.exe -p [PID]",
    CreateNoWindow = true,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
});

...

In output window:

Output =>

Output => Nthandle v4.11 - Handle viewer

Output => Copyright (C) 1997-2017 Mark Russinovich

Output => Sysinternals - www.sysinternals.com

Output =>

Output =>   10: File     C:\Windows

Output =>   1C: File     C:\Windows\SysWOW64

Error =>

like image 209
shingo Avatar asked Aug 30 '18 03:08

shingo


2 Answers

Not the answer of your question, but just a suggestion to achieve what you are trying do (i.e only get handle information in Winform application):

handle tool has -nobanner switch, you can use that to skip copyright message information.

handle64.exe -pid 11624 -nobanner
like image 74
Dipen Shah Avatar answered Oct 03 '22 11:10

Dipen Shah


As stated by Damien: CreateNoWindow = false,

Let it create the window the immediately hide it. We could create it offscreen, but it would still show on the taskbar.

Note: this code may be no better than letting the Window appear and disappear naturally.

At the top of the class add:

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

Then your code becomes:

var p = Process.Start(new ProcessStartInfo
{
    FileName = "cmd",
    Arguments = "/C handle64.exe -p [PID]",
    CreateNoWindow = false,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
});
p.WaitForInputIdle();
IntPtr windowHandle = p.MainWindowHandle;
if(windowHandle == 0) throw new Exception("This did not work");
// use win32 API's to hide window (May still flicker)
ShowWindow(windowHandle,0);
// ...

I am unable to test this, since I am only running Linux at the moment.
If the exception doesn't fire, you may see a flicker of a window, but you should have the proper output.

The other way I know of doing this involves inserting handlers into the Win32 message pump and respond to the specific process telling it what it needs to know to think it has a proper window when it does not. I will not publicly post any code related to this technique. Any errors would cause Windows to become unstable.

like image 39
Strom Avatar answered Oct 03 '22 12:10

Strom