当一个不同的C#应用程序(表单)即将关闭时,我希望在C#应用程序中接收一个事件。
我怎样才能做到这一点?这能用反射来完成吗?
编辑:详细描述
我知道我原来的问题不是很具体。我将尝试更详细地描述我的目标。
所以我有三份申请。让我们将它们命名为Container、Placer和ToPlace。我正在开发Contaner和Placer in C#,Placer是dll,Container是WinForm。我无法访问ToPlace的源代码。在Container中,我有一个自定义控件,将它放在ToPlace的主窗口中,并从Placer调用SetParent。其目标是在关闭ToPlace应用程序之前恢复的父窗口,或者过滤发送到ToPlace主窗口的WM_DESTROY消息(或其他消息)。最后,我们的目标不是在ToPlace退出时破坏的主窗口。
我试图在WndProc容器中重写自定义控件的,但是没有通过父窗口发送到子窗口的消息。
我还试图在容器应用程序上安装一个消息过滤器,但这也没有成功。
在编写这个问题之前,我最后一次尝试的是SetWindowsHookEx,但是在成功安装钩子之后,钩子过程永远不会被调用。也许是因为,我在某个地方读到,钩子函数必须在win32 dll中,而不是在托管dll中。下一次尝试将是使用SetWinEventHook,我了解到这一点,使它更容易从C#工作。
我在SetWindowsHookEx中尝试过的代码如下所示,也许在C#互操作方面更有经验的人会看到一个bug,并能让它正常工作:
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;
}
}
}发布于 2012-12-11 15:29:27
不,这不能用反射来完成。
你提供的信息很少能给出具体的答案..。例如:
请提供更多的细节,以便有可能得到一个具体的答案。
发布于 2012-12-11 15:45:03
如果您可以以某种方式找到要监视的进程(通过窗口标题,或者,如下面的示例所示,通过“友好”进程名称),则很容易监视其关闭。
下面的示例显示了如何监视“记事本”进程以查看它何时关闭:
using System;
using System.Diagnostics;
// To test this program:
// (1) Start Notepad.
// (2) Run this program.
// (3) Close Notepad.
// (4) This program should print "Notepad exited".
namespace Demo
{
internal class Program
{
public static void Main(string[] args)
{
foreach (var process in Process.GetProcessesByName("notepad"))
{
Console.WriteLine("Found a Notepad process to attach to.");
process.EnableRaisingEvents = true;
process.Exited += process_Exited;
}
Console.WriteLine("Press ENTER to quit.");
Console.ReadLine();
}
private static void process_Exited(object sender, EventArgs e)
{
Console.WriteLine("Notepad exited.");
}
}
}如果需要,可以使用Process.GetProcesses()枚举计算机上的所有进程,并对每个进程检查Process.MainWindowTitle以查看是否找到了所需的进程。
发布于 2012-12-11 15:28:30
我们在这里谈了多少IPC?如果这只是一个简单的通知,也许使用WM_COPYDATA就可以了。下面是这种方法的一个示例:http://www.codeproject.com/Articles/17606/NET-Interprocess-Communication
如果有更多的管道和/或内存映射文件,或者不仅仅是一条简单的“我要关闭”消息,那么使用命名管道和/或内存映射文件也是合适的。命名管道方法的示例如下:http://msdn.microsoft.com/en-us/library/bb546085.aspx
https://stackoverflow.com/questions/13822838
复制相似问题