Windows メッセージを使用して 2 つの C# / .NET 3.5 アプリケーション間で通信しようとしていますが、送信したメッセージが時々 (常にではありません) 受信されているように見えます。メッセージが常に適切に処理されること。次のようなクライアントオブジェクトがあります。
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern IntPtr SendMessage(IntPtr hWindow, int message, IntPtr wParam, IntPtr lParam);
public class WMTCPBridge
{
private IntPtr TargetHwnd
public void SendNumericMessage(Int32 messageCode,
Int32 MessagePayload)
{
//for some reason String.fomat("blah 0x{0:X}",TargetHwnd) shows the number in decimal
string sendNotice = String.Format("Sending to window 0x{0}", TargetHwnd.ToString("X"));
myTextOutput.Writeline(sendNotice);
sendNotice = String.Format("Sending to window {0}", TargetHwnd);
myTextOutput.Writeline(sendNotice);
IntPtr unmanagedInt = Marshal.AllocHGlobal(sizeof(Int32));
Marshal.WriteInt32(unmanagedInt,MessagePayload);
IntPtr result = IntPtr.Zero;
try
{
result = SendMessage(TargetHwnd, WM_COPYDATA, (IntPtr)messageCode,
unmanagedInt);
}
finally
{
Marshal.FreeHGlobal(unmanagedInt);
}
myTextOutput.Writeline("Result is " + result);
if ((int)result == 0)
{
myTextOutput.Writeline("Error code : " + GetThreadError());
}
}
public void GetTargetHandle(string targetName)
{
TargetHwnd = (IntPtr)FindWindow(null, targetName);
if (TargetHwnd == null)
{
myTextOutput.Writeline("Could not connect to UI");
}
else
{
String outputLine = string.Format("Connected to window number 0x{0}", TargetHwnd.ToString("X"));
myTextOutput.Writeline(outputLine);
outputLine = string.Format("Connected to window number {0}", TargetHwnd);
myTextOutput.Writeline(outputLine);
}
}
}
テスト アプリケーションのメイン フォームは、タイプ WMTCPBridge のオブジェクトを所有し、GetTargetHandle を呼び出して通信を開始し、SendNumericMessage メソッドを呼び出して個々のメッセージを送信します。サーバーは、不必要な変更を避けたい既存のアプリケーションの代わりとなるテスト ハーネスです。インターフェイスの選択を駆動するのは、この既存のアプリケーションです (WM_COPYDATA を使用する必要があります。wparam を介してメッセージ タイプ コードを送信する必要があります。単一の整数を送信する場合は、Copydatastruct ではなく lparam を介して整数を送信する必要があります)。サーバー アプリケーションのメイン フォームには、次のようにオーバーライドされた wndproc メソッドがあります。
protected override void WndProc(ref Message m)
{
Int32 messageCode=0;
Int32 messagePayload=0;
Debug.WriteLine(m);
switch (m.Msg)
{
case WM_COPYDATA:
{
messageCode = (int)m.WParam;
messagePayload = Marshal.ReadInt32(m.LParam);
WriteLine("Received message with code " + messageCode +
" and payload " + messagePayload);
break;
}
case WM_CLOSE:
{
WriteLine("Close blocked!");
return;
break;
}
}
base.WndProc(ref m);
}
サーバーとクライアントを一緒に実行すると、Winspector で確認できるハンドルにメッセージを送信しているとクライアントが報告し、sendMessage 関数は 0 を返し、アプリケーション エラーは 0 です。メッセージを取得したと報告し、Winspector はサーバーに送信されている WM_COPYDATA メッセージを表示しません。ただし、クライアントからメッセージを送信し続けると、一部がサーバーによって受信されます。通常、すべてのメッセージが通過するか、まったく通過しないというストリークがあります。WM_CLOSE メッセージを送信するようにクライアントを変更すると、上記のように WndProc メソッドを使用して WM_CLOSE メッセージをトラップしようとしても、サーバーは必然的にメッセージを受信して終了します。
メッセージはどうなりますか? MSDN によると、SendMessage 関数はメッセージが処理された後にのみ返されるため、私は特に混乱しています。