Я получаю прерывистую ошибку при вызове Message.GetLParam, получая сообщения, отправленные между процессами.
У меня есть два процесса, оба написаны на C # (.Net 3.5). Я использую функцию Win32 SendMessage () для отправки данных от одного процесса (источник) к другому (цель). Главное окно целевого процесса (это приложение Windows Forms) переопределяет функцию WndProc () для получения сообщений.
Исходный процесс находит другой с помощью функции Process.GetProcessesByName (), а затем с помощью Process.MainWindowHandle, чтобы получить дескриптор окна, в который я хочу отправить сообщение. Код исходного кода выглядит так:
Process[] procs = Process.GetProcessesByName("MyTargetProcess");
if (procs != null
&& procs.Length > 0)
{
IntPtr win = procs[0].MainWindowHandle;
var someData = new Win32.COPYDATASTRUCT // This is a struct that I defined
{
// Initialize fields of the struct
};
Win32.SendMessage(win,
Win32.MyMsgCode, // my custom message
IntPtr.Zero, // wParam = 0
ref someData);
}
Код целевого процесса выглядит следующим образом:
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg == Win32.MyMsgCode)
{
Win32.COPYDATASTRUCT ds;
try
{
ds = (Win32.COPYDATASTRUCT)m.GetLParam(typeof(Win32.COPYDATASTRUCT));
}
catch (Exception ex)
{
log.ErrorFormat("Got exception in WndProc", ex);
}
// Do something with the message
....
}
Win32 - статический класс, который я определил, который получает все мои определения P / Invoke.
Я не понимаю, почему я ловлю AccessViolationException в WndProc.
У кого-нибудь есть идея, почему? и почему это происходит только иногда?
Спасибо за внимание!
-------------------------------- РЕДАКТИРОВАТЬ -------------- ----------------------------
Еще одна вещь, которая ставит меня в тупик: COPYDATASTRUCT объявлен как
public static readonly int WM_COPYDATA = 0x004a;
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
// Specifies data to be passed to the receiving application.
public string dwData;
// Specifies the size, in bytes, of the data pointed to by the lpData member.
public int cbData;
// Pointer to data to be passed to the receiving application. This member can be NULL.
public string lpData;
}
Инициализируется так:
string payload = " some data ";
var someData = new Win32.COPYDATASTRUCT // This is a struct that I defined
{
dwData = "bogusData",
cbData = sizeof(char) * payload.Length,
lpData = payload
};
А в целевом коде я всегда получаю dwData = null.
----------------------- 2-е редактирование ---------------------- ----------------
Я только что попытался с добавлением нулевого терминатора, и я все еще получаю ошибку.
Если я изменю код маршаллинга, чтобы сделать свой собственный маршаллинг, как в
IntPtr pcds = Marshal.AllocHGlobal(Marshal.SizeOf(someData));
Marshal.StructureToPtr(someData, pcds, true);
Win32.SendMessage(win, (uint)Win32.WM_COPYDATA, IntPtr.Zero, pcds);
Тогда ошибка происходит ВСЕ ВРЕМЯ! Однако, если я повторю вызов GetLParam () в блоке catch, он будет успешен почти все время, со второй попытки.