一緒にリンクしようとしている 2 つのアセンブリがあります。
- 1 つは、WinForms で構築され、Windows サービスとして実行するように設計された一種のバックグラウンド プロセスです。
- ユーザーが起動するたびにバックグラウンド プロセスの UI として機能する 2 つ目のプロジェクトがあります。
これまでマネージ コードでこのようなことを試みたことがないので、Windows メッセージを使用して 2 つのプロセス間で通信しようと試み始めました。ただし、IntPtrs 以外のものをやり取りすることになると苦労しています。
バックグラウンド プロセスに自身を登録する UI プロジェクトのコントロールのコードを次に示します。
public void Init()
{
IntPtr hwnd = IntPtr.Zero;
Process[] ps = Process.GetProcessesByName("BGServiceApp");
Process mainProcess = null;
if(ps == null || ps.GetLength(0) == 0)
{
mainProcess = LaunchApp();
}
else
{
mainProcess = ps[0];
}
SendMessage(mainProcess.MainWindowHandle, INIT_CONNECTION, this.Handle, IntPtr.Zero);
}
protected override void WndProc(ref Message m)
{
if(m.Msg == INIT_CONFIRMED && InitComplete != null)
{
string message = Marshal.PtrToStringAuto(m.WParam);
Marshal.FreeHGlobal(m.WParam);
InitComplete(message, EventArgs.Empty);
}
base.WndProc(ref m);
}
これは、UI プロセスからリクエストを受け取り、ステータスの更新を登録して確認メッセージを送信するバックグラウンド プロセスのコードです。
protected override void WndProc(ref Message m)
{
if(m.Msg == INIT_CONNECTION)
{
RegisterUIDispatcher(m.WParam);
Respond(m.WParam);
}
if(m.Msg == UNINIT_CONNECTION)
{
UnregisterUIDispatcher(m.WParam);
if(m_RegisteredDispatchers.Count == 0)
{
this.Close();
}
}
base.WndProc(ref m);
}
private void Respond(IntPtr caller)
{
string test = "Registration confirmed!";
IntPtr ptr = Marshal.StringToHGlobalAuto(test);
SendMessage(caller, INIT_CONFIRMED, ptr, IntPtr.Zero);
}
UI プロセスはINIT_CONFIRMED
バックグラウンド プロセスからメッセージを受け取りますが、IntPtr をマーシャリングして文字列に戻そうとすると、空の文字列が返されます。私が使用しているヒープの領域は、他のプロセスの範囲外ですか、それともセキュリティ属性が不足していますか? イベント駆動型モデルを使用して、このようなことを行うためのより良い、よりクリーンな方法はありますか?