同じマシンで実行されているプロセスの場合、おそらく最も軽量な解決策はPostThreadMessage()を使用することです。誰もこの答えを出さなかったことに本当に驚いています。それは古い学校のWindowsプログラミングです。OPは非常に近かった。観察:
- すべてのプロセスにはメインスレッド(ネイティブスレッド)があります。
- メインスレッドにはメッセージキューがあります。
- メインスレッドには、システムに対してグローバルなスレッドIDがあります。
すべての材料がそこにあります、それはそれらを一緒にすることの問題です。概念的には簡単ですが、注意が必要なのは、RECEIVERのメインスレッドIDをSENDERに伝達することです。いくつかのオプションがあります。
- SENDERから、Win32では、RECEIVERのスレッド情報ブロックからスレッドIDを掘り出すことができます。 https://stackoverflow.com/a/8058710/420400
- RECEIVERが起動すると、Process.StartInfo.EnvironmentにスレッドIDを保存できます。それは本当にそこにあり、SysInternalsのProcess Explorerに表示されますが、それを理解するのは困難です。ここでも、このためのWin32ソリューションがあります。 https://www.codeproject.com/Articles/25647/Read-Environment-Strings-of-Remote-Process
- RECEIVERが起動すると、スレッドIDを共有メモリに保存できます。
- (またはもっと良いもの...)
オプション1と2はセキュリティの悪用のように見えるので、この例ではオプション3を使用して、小さなメモリマップファイルでスレッドIDを共有しました。
RECEIVERはこんな感じ
enum WM { USER = 0x400 }
class MyMessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if ((WM)m.Msg == WM.USER)
{
Console.WriteLine("WM_USER received.");
return true;
}
return false;
}
}
class RECEIVER : IDisposable
{
MemoryMappedFile mmf;
bool disposed = false;
public void MyMessageLoop()
{
uint mainThreadId = GetCurrentThreadId();
Console.WriteLine(mainThreadId);
mmf = MemoryMappedFile.CreateNew(Constants.ThreadIDFileName, IntPtr.Size, MemoryMappedFileAccess.ReadWrite);
using (var accessor = mmf.CreateViewAccessor(0, IntPtr.Size, MemoryMappedFileAccess.ReadWrite))
{
accessor.Write(0, mainThreadId);
}
Application.AddMessageFilter(new MyMessageFilter());
Application.Run();
}
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
// Implement IDisposable and ~RECEIVER() to delete the semaphore, omitted for brevity
// https://docs.microsoft.com/en-us/dotnet/api/system.idisposable?view=netframework-4.7.2
#region
...
#endregion
}
そしてSENDERはこんな感じ
enum WM { USER = 0x400 }
class Program
{
static void Main(string[] args)
{
string procName = "RECEIVER";
Process[] processes = Process.GetProcesses();
Process process = (from p in processes
where p.ProcessName.ToUpper().Contains(procName)
select p
).First();
uint threadId;
using (var mmf = MemoryMappedFile.OpenExisting(Constants.ThreadIDFileName, MemoryMappedFileRights.Read))
using (var accessor = mmf.CreateViewAccessor(0, IntPtr.Size, MemoryMappedFileAccess.Read))
{
accessor.Read(0, out serviceThreadId);
}
PostThreadMessage(threadId, (uint)WM.USER, UIntPtr.Zero, IntPtr.Zero);
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
public static extern bool PostThreadMessage(uint threadId, uint msg, IntPtr wParam, IntPtr lParam);
}