I want to receive an event in my C# application when a different C# application (Form) is about to close.
How can I accomplish this? Can this be done with Reflections?
Edit: detailed description
I realize that my original question is not very specific. I will try to describe my goal in more detail.
So I have 3 applications. Let's name them Container, Placer and ToPlace. I am developing Contaner and Placer in C#, Placer is a dll while Container is a WinForm. I have no access to the source code of ToPlace. In Container I have a custom control where I put in the main window of ToPlace with SetParent called from Placer. The goal would be to restore the parent window for the ToPlace before the Contaner app is closed, or to filter out the WM_DESTROY message (or other message) sent to the ToPlace main window. In the end the goal is not to destroy the main window of ToPlace when Container exits.
I tried to override the WndProc of the custom control in Container, but the message to the child window is not sent via the parent window.
I also tried to install a message filter on the Container app, but this was also not successfull.
My last try before writing this question was the SetWindowsHookEx, but after installing the hook successfully the hook procedure is never called. Maybe because, I read somewhere, that the hook function must be in a win32 dll, not in a managed one. The next try would be to use the SetWinEventHook, I read about this that it is easier to get it working from C#.
The code I tried with SetWindowsHookEx is below, maybe somebody who is more experienced in C# interop sees a bug and can get it working:
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;
}
}
}