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 =>
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With