【发布时间】:2012-12-11 15:19:25
【问题描述】:
当另一个 C# 应用程序(窗体)即将关闭时,我想在我的 C# 应用程序中接收一个事件。
我怎样才能做到这一点?这可以用反射来完成吗?
编辑:详细说明
我意识到我最初的问题不是很具体。 我将尝试更详细地描述我的目标。
所以我有 3 个应用程序。我们将它们命名为 Container、Placer 和 ToPlace。 我正在用 C# 开发 Contaner 和 Placer,Placer 是一个 dll,而 Container 是一个 WinForm。我无法访问 ToPlace 的源代码。在 Container 中,我有一个自定义控件,我在 ToPlace 的主窗口中放置了从 Placer 调用的 SetParent。目标是在 Contaner 应用程序关闭之前恢复 ToPlace 的父窗口,或者过滤掉发送到 的 WM_DESTROY 消息(或其他消息) >ToPlace 主窗口。最终目标是在 Container 退出时不破坏 ToPlace 的主窗口。
我尝试在Container中重写自定义控件的WndProc,但是没有通过父窗口发送给子窗口的消息。
我也尝试在 Container 应用上安装消息过滤器,但这也不成功。
我在写这个问题之前的最后一次尝试是 SetWindowsHookEx,但是在成功安装钩子后,钩子程序永远不会被调用。也许是因为,我在某处读到,钩子函数必须在 win32 dll 中,而不是在托管的。下一个尝试是使用 SetWinEventHook,我读到了这个,它更容易从 C# 中工作。
我尝试使用 SetWindowsHookEx 的代码如下,也许在 C# 互操作方面更有经验的人看到了一个错误并可以让它工作:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace AppMonitor
{
public class AppMonitor
{
private const int WH_GETMESSAGE = 3;
private const int HC_ACTION = 0;
private const int PM_NOREMOVE = 0x0000;
private const int PM_REMOVE = 0x0001;
private const int WM_QUIT = 0x0012;
[DllImport("user32.dll")]
private static extern int SetWindowsHookEx(int idHook, GetMsgProcDelegate lpfn, int hMod, int dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(int hhk);
[DllImport("user32.dll")]
private unsafe static extern int CallNextHookEx(int hhk, int nCode, int wParam, void* lParam);
[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
[DllImport("kernel32.dll")]
private static extern int GetLastError();
private struct Msg {
public int hwnd;
public int message;
public int wParam;
public int lParam;
public int time;
public int pt;
};
[DllImport("kernel32.dll")]
public static extern int LoadLibrary(string dllToLoad);
public AppMonitor()
{
}
private int hHook;
private int hMod;
public event EventHandler AppClosing;
private unsafe delegate int GetMsgProcDelegate(int code, int wParam, void* lParam);
private unsafe GetMsgProcDelegate m_dlgt;
private unsafe int GetMsgProc(int code, int wParam, void* lParam)
{
if (code != HC_ACTION || wParam != PM_REMOVE)
return CallNextHookEx(this.hHook, code, wParam, lParam);
Msg* msg = (Msg*)lParam;
//if (msg.message == WM_QUIT)
// OnAppClosing(new EventArgs());
return CallNextHookEx(this.hHook, code, wParam, lParam);
}
protected virtual void OnAppClosing(EventArgs e)
{
EventHandler h = AppClosing;
if (h != null)
{
h(this, e);
}
}
public unsafe bool setHook(int hWnd)
{
hMod = LoadLibrary("AppMonitor.dll"); //this dll
int procId = 0;
int threadId = GetWindowThreadProcessId(hWnd, out procId);
if (threadId == 0)
throw new System.Exception("Invalid thread Id");
m_dlgt = GetMsgProc;
this.hHook = SetWindowsHookEx(WH_GETMESSAGE, m_dlgt, hMod, threadId);
if (this.hHook == 0)
throw new System.Exception("Hook not successfull! Error code: " + GetLastError());
return this.hHook != 0;
}
public bool unSetHook()
{
bool result = false;
if (hHook != 0)
result = UnhookWindowsHookEx(hHook);
return result;
}
}
}
【问题讨论】:
-
进程是否在同一台机器上?
-
使用message hook 并查找 WM_CLOSE 消息,或者设置一个计时器来轮询其他窗口句柄是否消失引发事件。
-
是的,进程在同一台机器上。
标签: c# winapi reflection window ipc