Я пытаюсь перенести некоторый код C ++ в C #, и одна из вещей, которые мне нужно сделать, это использовать PostMessage
для передачи байтового массива в окно другого процесса. Я пытаюсь получить исходный код для другой программы, чтобы я мог точно увидеть, чего он ожидает, но пока что вот как выглядит оригинальный код C ++:
unsigned long result[5] = {0};
//Put some data in the array
unsigned int res = result[0];
Text winName = "window name";
HWND hWnd = FindWindow(winName.getConstPtr(), NULL);
BOOL result = PostMessage(hWnd, WM_COMMAND, 10, res);
А вот что у меня сейчас:
[DllImport("User32.dll", SetLastError = true, EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll", SetLastError = true, EntryPoint = "SendMessage")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
public byte[] lpData;
}
public const int WM_COPYDATA = 0x4A;
public static int sendWindowsByteMessage(IntPtr hWnd, int wParam, byte[] data)
{
int result = 0;
if (hWnd != IntPtr.Zero)
{
int len = data.Length;
COPYDATASTRUCT cds;
cds.dwData = wParam;
cds.lpData = data;
cds.cbData = len;
result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
}
return result;
}
//*****//
IntPtr hWnd = MessageHelper.FindWindow(null, windowName);
if (hWnd != IntPtr.Zero)
{
int result = MessageHelper.sendWindowsByteMessage(hWnd, wParam, lParam);
if (result == 0)
{
int errCode = Marshal.GetLastWin32Error();
}
}
Обратите внимание, что мне пришлось переключиться с использования PostMessage
в C ++ на SendMessage
в C #.
Итак, что происходит сейчас, так это то, что я получаю и результат, и errCode равным 0, что, как я считаю, означает, что сообщение не было обработано - и действительно, глядя на другое приложение, я не вижу ожидаемого ответа. Я подтвердил, что hWnd != IntPtr.Zero
, поэтому я думаю, что сообщение отправляется в правильное окно, но данные сообщения неверны. Есть идеи, что я делаю не так?
Обновление
Мне все еще не повезло, попробовав предложения в комментариях. Вот что у меня сейчас есть:
[DllImport("User32.dll", SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
public struct BYTEARRDATA
{
public byte[] data;
}
public static IntPtr IntPtrAlloc<T>(T param)
{
IntPtr retval = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, retval, false);
return (retval);
}
public static void IntPtrFree(IntPtr preAllocated)
{
//Ignores errors if preAllocated is IntPtr.Zero!
if (IntPtr.Zero != preAllocated)
{
Marshal.FreeHGlobal(preAllocated);
preAllocated = IntPtr.Zero;
}
}
BYTEARRDATA d;
d.data = data;
IntPtr buffer = IntPtrAlloc(d);
COPYDATASTRUCT cds;
cds.dwData = new IntPtr(wParam);
cds.lpData = buffer;
cds.cbData = Marshal.SizeOf(d);
IntPtr copyDataBuff = IntPtrAlloc(cds);
IntPtr r = SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, copyDataBuff);
if (r != IntPtr.Zero)
{
result = r.ToInt32();
}
IntPtrFree(copyDataBuff);
copyDataBuff = IntPtr.Zero;
IntPtrFree(buffer);
buffer = IntPtr.Zero;
Это 64-битный процесс, пытающийся связаться с 32-битным процессом, так что может быть что-то есть, но я не уверен, что.