老派 Win32 Message Only Window 无法接收消息
Old school Win32 Message Only Window cannot receive messages
我意识到控制台 win32 应用程序没有完全退出,所以我尝试切换到仅消息 windows。我正在从另一个进程启动该应用程序并试图将其彻底终止。
这是 win32 应用程序,它在启动和干净关闭时生成 calc.exe,它应该会杀死 calc.exe
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_USER: PostQuitMessage (0); break;
default: return DefWindowProc (hWnd, message, wParam, lParam);break;
}
return 0;
}
int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int show)
{
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof (WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"WindowClass1";
RegisterClassEx (&wc);
HWND hWnd = CreateWindowEx (NULL,
L"WindowClass1", // name of the window class
L"Our First Windowed Program", // title of the window
0,
//WS_OVERLAPPEDWINDOW, // window style
300,300,500,400,
HWND_MESSAGE,
//NULL, // parent window, NULL
NULL, hInstance, NULL);
//ShowWindow (hWnd, SW_HIDE);
PROCESS_INFORMATION pi;
CreateWindowProcess (L"calc.exe", pi); // helper class to createprocess
MSG msg = { 0 };
while (true)
{
if (PeekMessage (&msg, 0, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message)
break;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
// terminate the spawn process, this is not called cleanly
TerminateProcess (pi.hProcess, 0);
return (int)msg.wParam;
}
我通过发送 WM_QUIT/WM_CLOSE/WM_USER 消息为 start/kill 应用程序创建了一个 c# 程序(calc.exe 被破坏)。除非 window 可见(WS_OVERLAPPED 且 ShowWindow 为真),否则 Win32 应用程序不会接收消息。收到 PostMessage WM_QUIT 但 calc.exe 没有被销毁,这意味着它不是一个干净的出口。
我应该如何从 C# 应用程序中彻底杀死它?
class Program
{
[DllImport ("user32.dll")]
public static extern bool PostMessage (IntPtr hwnd, uint msg, int wparam, int lparam);
[DllImport ("User32.dll")]
public static extern int SendMessage (IntPtr hWnd, uint uMsg, int wParam, int lParam);
static void Main (string [] args)
{
try
{
Process myProcess;
myProcess = Process.Start ("My.exe");
// Display physical memory usage 5 times at intervals of 2 seconds.
for (int i = 0; i < 3; i++)
{
if (myProcess.HasExited) break;
else
{
// Discard cached information about the process.
myProcess.Refresh ();
Thread.Sleep (4000);
Console.WriteLine ("Sending Message");
const int WM_USER = 0x0400;
const int WM_CLOSE = 0xF060; // Command code for close window
const int WM_QUIT = 0x0012;
// Received only when windows is visible
//int result = SendMessage (myProcess.MainWindowHandle, WM_USER, 0, 0);
// not clean exit
PostMessage (myProcess.MainWindowHandle, WM_QUIT, 0, 0);
// doesn't receive
SendMessage (myProcess.MainWindowHandle, WM_QUIT, 0, 0);
}
}
}
}
}
Windows 上的进程实际上没有 "MainWindow"。 Process.MainWindowHandle 是 C# 进行的猜测,它通过查看所讨论的进程是否具有带焦点的 window 来进行猜测 - 它只会找到可见的 windows。使用 FindWindowEx
找到您要关闭的 window 句柄。
接下来,当一个window关闭时,它不会自动尝试退出当前线程的消息循环。您需要处理 WM_DESTROY
才能调用 PostQuitMessage
.
如果您不做任何其他工作,请在您的消息循环中使用 GetMessage
而不是 PeekMessage
PeekMessage
returns 如果没有消息意味着应用程序线程将永远没有机会休眠。
有了这些更改,您应该可以简单地 post 一个 WM_CLOSE
到有效的 window 句柄,因为它将被销毁,post 本身是一个 WM-QUIT
消息退出消息循环,正确终止计算过程。
我意识到控制台 win32 应用程序没有完全退出,所以我尝试切换到仅消息 windows。我正在从另一个进程启动该应用程序并试图将其彻底终止。
这是 win32 应用程序,它在启动和干净关闭时生成 calc.exe,它应该会杀死 calc.exe
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_USER: PostQuitMessage (0); break;
default: return DefWindowProc (hWnd, message, wParam, lParam);break;
}
return 0;
}
int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int show)
{
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof (WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"WindowClass1";
RegisterClassEx (&wc);
HWND hWnd = CreateWindowEx (NULL,
L"WindowClass1", // name of the window class
L"Our First Windowed Program", // title of the window
0,
//WS_OVERLAPPEDWINDOW, // window style
300,300,500,400,
HWND_MESSAGE,
//NULL, // parent window, NULL
NULL, hInstance, NULL);
//ShowWindow (hWnd, SW_HIDE);
PROCESS_INFORMATION pi;
CreateWindowProcess (L"calc.exe", pi); // helper class to createprocess
MSG msg = { 0 };
while (true)
{
if (PeekMessage (&msg, 0, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message)
break;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
// terminate the spawn process, this is not called cleanly
TerminateProcess (pi.hProcess, 0);
return (int)msg.wParam;
}
我通过发送 WM_QUIT/WM_CLOSE/WM_USER 消息为 start/kill 应用程序创建了一个 c# 程序(calc.exe 被破坏)。除非 window 可见(WS_OVERLAPPED 且 ShowWindow 为真),否则 Win32 应用程序不会接收消息。收到 PostMessage WM_QUIT 但 calc.exe 没有被销毁,这意味着它不是一个干净的出口。
我应该如何从 C# 应用程序中彻底杀死它?
class Program
{
[DllImport ("user32.dll")]
public static extern bool PostMessage (IntPtr hwnd, uint msg, int wparam, int lparam);
[DllImport ("User32.dll")]
public static extern int SendMessage (IntPtr hWnd, uint uMsg, int wParam, int lParam);
static void Main (string [] args)
{
try
{
Process myProcess;
myProcess = Process.Start ("My.exe");
// Display physical memory usage 5 times at intervals of 2 seconds.
for (int i = 0; i < 3; i++)
{
if (myProcess.HasExited) break;
else
{
// Discard cached information about the process.
myProcess.Refresh ();
Thread.Sleep (4000);
Console.WriteLine ("Sending Message");
const int WM_USER = 0x0400;
const int WM_CLOSE = 0xF060; // Command code for close window
const int WM_QUIT = 0x0012;
// Received only when windows is visible
//int result = SendMessage (myProcess.MainWindowHandle, WM_USER, 0, 0);
// not clean exit
PostMessage (myProcess.MainWindowHandle, WM_QUIT, 0, 0);
// doesn't receive
SendMessage (myProcess.MainWindowHandle, WM_QUIT, 0, 0);
}
}
}
}
}
Windows 上的进程实际上没有 "MainWindow"。 Process.MainWindowHandle 是 C# 进行的猜测,它通过查看所讨论的进程是否具有带焦点的 window 来进行猜测 - 它只会找到可见的 windows。使用 FindWindowEx
找到您要关闭的 window 句柄。
接下来,当一个window关闭时,它不会自动尝试退出当前线程的消息循环。您需要处理 WM_DESTROY
才能调用 PostQuitMessage
.
如果您不做任何其他工作,请在您的消息循环中使用 GetMessage
而不是 PeekMessage
PeekMessage
returns 如果没有消息意味着应用程序线程将永远没有机会休眠。
有了这些更改,您应该可以简单地 post 一个 WM_CLOSE
到有效的 window 句柄,因为它将被销毁,post 本身是一个 WM-QUIT
消息退出消息循环,正确终止计算过程。