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
.
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
Not sure it works, but you can try that :
In a console application which streamed diagostics to the console, and for which I wanted to disable mouse input, I tried
GetConsoleWindow(), Process.GetCurrentProcess().MainWindowHandle, and FindWindowByCaption(IntPtr.Zero, Console.Title)
. Each of these returned the same non-zero handle, but when I tried to use that handle in SetConsoleMode it threw a "Invalid Handle" exception. Finally I triedSetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode | ENABLE_EXTENDED_FLAGS))
with STD_INPUT_HANDLE defined as -10, and it worked. MS's documentation suggests that handles to consoles may be reassigned, and I am not comfortable or happy with this solution, but so far it is the only thing I've found that allows me to disable quick edit mode programmatically.GetStdHandle(STD_INPUT_HANDLE)
returns '3', the other calls return a 7 digit value that varies each time the program is run.Process.MainWindowHandle
method only works for the process that started the consoleFindWindowByCaption
method is inherently unreliableHere's a robust way to do this:
The related functions from the Console Win32 API are:
GetConsoleWindow()
is enoughAttachConsole
, callGetConsoleWindow
, them immediately detach withFreeConsole
.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:
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 ofReadProcessMemory
. All thatcsrss
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 inwinsrv.dll
.I don't think there is such a thing. The console window is not accessible to the application. You MIGHT try to iterate the process list looking for your own process name. The
Process
class IIRC contains a property for the program's main window handle, which might be the console window for console applications - which I'm not sure of.I've just solved this problem for myself (unfortunately before seeing Thomas's answer which is much quicker). Well, here's another way for those who are not satisfied with his answer. I'm writing this answer because I want to provide another answer + a better way to design the
Program
class if you're treating your console as a Window. Let's begin with that design:I've kind of changed the default style of the
Program
class. I've actually made it into a class that has a program in it, and not just one method which represent it and uses other classes for content. (If you don't know what I mean, not important).The reason I had to do it is because I wanted to write the following event handler:
It overloads this method
MessageBox.Show(IWin32Window, String, String)
.Because Console doesn't implement
IWin32Window
, I had to implement it myself, of course, in order to just callthis
in the 1st argument.Here is the implementation of it and everything else:
Note: this code is copy-pasted from my application, you can feel free to change the access modifiers
Program
Class Declaration:IWin32Window
Implementation:It uses the following class:
Now, the problem is that you can't actually call
this
inMain
, being a static method, so whatever was inMain
I've moved to a new method namedStart
and allMain
is doing is creating a newProgram
and callingStart
.The result was, of course, a message-box with my console's window as an owner.
Using this method for a message-box, is of course only one application of this method.
Try this: