Gra*_*ant 43 c# console hwnd window-handles
有人能告诉我如何在C#中获取Windows控制台应用程序的句柄吗?在Windows窗体应用程序中,我通常会尝试this.Handle.
Tho*_*que 62
不确定它是否有效,但您可以尝试:
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
Run Code Online (Sandbox Code Playgroud)
iva*_*eev 26
这是一种强有力的方法:
Console Win32 API的相关功能包括:
[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();
Run Code Online (Sandbox Code Playgroud)
GetConsoleWindow()足够了AttachConsole,调用GetConsoleWindow,它们立即分离FreeConsole.为了格外小心,请在附加之前注册一个控制台事件处理程序(并在分离后取消注册),这样如果控制台事件发生在您附加到控制台的微小时间范围内,则不会意外终止:
[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;
};
Run Code Online (Sandbox Code Playgroud)
对当前进程进行更改只是为了阅读某些东西是相当丑陋的(当这是一个控制台进程时,这变得非常难看,因为它需要帮助程序进程以避免终止当前控制台).然而,进一步的调查表明,除了注入csrss流程或目标流程之外别无他法.
控制台对应信息位于并由csrss.exe(或多个,每个会话一个,自Vista以来)管理,因此无法使用ReadProcessMemory.所有csrss暴露的都是CSRSS LPC API.完整的API列表中只有一个相关的功能SrvGetConsoleWindow.并且它不接受PID但是确定主叫方的那个,如在替代实现或函数的反汇编中所见winsrv.dll.
Zai*_*Ali 10
试试这个:
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
public static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
…
Console.Title = "Test";
…
IntPtr handle = FindWindowByCaption(IntPtr.Zero, Console.Title);
Run Code Online (Sandbox Code Playgroud)
我刚刚为自己解决了这个问题(不幸的是,在看到Thomas的答案要快得多之前).那么,对于那些对他的答案不满意的人来说,这是另一种方式.我写这个答案是因为我想提供另一个答案+ Program如果你把你的控制台视为一个窗口,那么设计一个更好的方法.让我们从这个设计开始:
我有点改变了Program班级的默认风格.我实际上把它变成了一个包含程序的类,而不仅仅是一个表示它并使用其他类来表示内容的方法.(如果你不知道我的意思,不重要).
我必须这样做的原因是因为我想编写以下事件处理程序:
private void CatchUnhandled(Object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
MessageBox.Show(this, exception.Message, "Error"); // Check out 1st arg.
}
Run Code Online (Sandbox Code Playgroud)
它会重载此方法MessageBox.Show(IWin32Window, String, String).
由于控制台没有实现IWin32Window,我必须实现它自己,当然,为了只是调用this在1 日的说法.
这是它的实现和其他一切:
注意:此代码是从我的应用程序中复制粘贴的,您可以随意更改访问修饰符
Program 类声明:
internal class Program : IWin32Window
{
...
}
Run Code Online (Sandbox Code Playgroud)
IWin32Window 执行:
public IntPtr Handle
{
get { return NativeMethods.GetConsoleWindow(); }
}
Run Code Online (Sandbox Code Playgroud)
它使用以下类:
internal static class NativeMethods
{
[DllImport("kernel32.dll")]
internal static extern IntPtr GetConsoleWindow();
}
Run Code Online (Sandbox Code Playgroud)
现在的问题是,你不能真正称之为this中Main,是一个静态方法,所以无论是在Main我的公司搬到了新的命名方法Start,所有Main做的是创造一个新的Program和调用Start.
private static void Main()
{
new Program().Start();
}
private void Start()
{
AppDomain.CurrentDomain.UnhandledException += CatchUnhandled;
throw new Exception();
}
Run Code Online (Sandbox Code Playgroud)
结果当然是一个消息框,我的控制台窗口是所有者.
对消息框使用此方法当然只是此方法的一个应用程序.
| 归档时间: |
|
| 查看次数: |
42532 次 |
| 最近记录: |