Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the handle of a console application's window

Can someone tell me how to get the handle of a Windows console application in C#? In a Windows Forms application, I would normally try this.Handle.

like image 565
Grant Avatar asked Aug 14 '09 12:08

Grant


People also ask

What is a window handle HWND?

A window handle (usually shortened to hWnd) is a unique identifer that Windows assigns to each window created. By window in this case we are referring to everything from command buttons and textboxes, to dialog boxes and full windows.

How do I get HWND of a window in Python?

If you want to get window handles you can use with win32gui , use win32gui. EnumWindows instead of calling the raw function out of the user32 DLL.

What is a console application Windows?

A console application is a computer program designed to be used via a text-only computer interface, such as a text terminal, the command-line interface of some operating systems (Unix, DOS, etc.) or the text-based interface included with most graphical user interface (GUI) operating systems, such as the Windows Console ...

How can I get Hwnd from process id?

You can use EnumWindows and GetWindowThreadProcessId() functions as mentioned in this MSDN article.


2 Answers

Not sure it works, but you can try that :

IntPtr handle = Process.GetCurrentProcess().MainWindowHandle; 
like image 139
Thomas Levesque Avatar answered Oct 20 '22 22:10

Thomas Levesque


  • The aforementioned Process.MainWindowHandle method only works for the process that started the console
  • The FindWindowByCaption method is inherently unreliable

Here's a robust way to do this:

The related functions from the Console Win32 API are:

[DllImport("kernel32.dll", SetLastError = true)] static extern bool AttachConsole(uint dwProcessId); [DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow(); [DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)] static extern bool FreeConsole(); 
  • For the console the current process is attached to, just GetConsoleWindow() is enough
  • For the console another process is attached to, attach to it as well with AttachConsole, call GetConsoleWindow, them immediately detach with FreeConsole.

For the extra cautious, register a console event handler before attaching (and unregister it after detaching) as well so you don't accidentally get terminated if a console event happens in the tiny time frame you're attached to the console:

[DllImport("kernel32.dll")] static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine,    bool Add); delegate Boolean ConsoleCtrlDelegate(CtrlTypes CtrlType); enum CtrlTypes : uint {     CTRL_C_EVENT = 0,     CTRL_BREAK_EVENT,     CTRL_CLOSE_EVENT,       CTRL_LOGOFF_EVENT = 5,     CTRL_SHUTDOWN_EVENT }  bool is_attached=false;     ConsoleCtrlDelegate ConsoleCtrlDelegateDetach = delegate(CtrlType) {      if (is_attached = !FreeConsole())          Trace.Error('FreeConsole on ' + CtrlType + ': ' + new Win32Exception());      return true; }; 

Making changes to the current process just to read something is rather ugly (when this is a console process, this gets really ugly since it requires a helper process to avoid terminating the current console). Nevertheless, further investigation shows that there's no other way short of injecting into the csrss process or the target process.

Console correspondence information is located in and managed by csrss.exe (or a multitude of those, one for each session, since Vista), so it can't be retrieved with the likes of ReadProcessMemory. All that csrss exposes is the CSRSS LPC API. There's only one relevant function in the full API list, SrvGetConsoleWindow. And it doesn't accept a PID but determines that of the calling party as seen in an alternative implementation or the function's disassembly in winsrv.dll.

like image 44
ivan_pozdeev Avatar answered Oct 20 '22 21:10

ivan_pozdeev