общение между приложениями с помощью выигрышных сообщений - PullRequest
0 голосов
/ 15 января 2010

Я пытаюсь разрешить 2 приложениям общаться друг с другом с помощью сообщения Windows.Тем не менее, я получил AccessViolationException (попытка чтения или записи защищенной памяти) во время выделения памяти и маршалинга данных.

Может кто-нибудь объяснить мне, что не так или предложить лучший способ?Благодарю.

РЕДАКТИРОВАТЬ: используя WM_COPYDATA как предложено, но теперь у меня есть другая проблема - другое приложение не получает сообщение WM_COPYDATA.что случилось?

код для отправки сообщения:

public const int WM_COPYDATA = 0x004A;
public struct COPYDATASTRUCT
{
    public int dwData;
    public int cbData;
    public DATA lpData;
}

public struct DATA
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=50)]
    public char[] msg1;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=50)]
    public char[] msg2;
}

[DllImport("User32.dll")]
public static extern int SendMessage(int hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);

private void button1_Click(object sender, EventArgs e)
{
    // data, with null terminated strings
    COPYDATASTRUCT cds = new COPYDATASTRUCT();
    cds.lpData.msg1 = textBox2.Text.PadRight(50, '\0').ToCharArray();
    cds.lpData.msg2 = textBox3.Text.PadRight(50, '\0').ToCharArray();
    cds.cbData = Marshal.SizeOf(cds.lpData);
    int result = SendMessage(hwnd, WM_COPYDATA, System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle, ref cds); // winAPI

}

код для получения сообщения (в другом приложении):

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_COPYDATA)
    {
        // doesn't get into this part

        COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
        ....
    }
    base.WndProc(ref m);
}

Ответы [ 3 ]

2 голосов
/ 15 января 2010

Указатели в Windows (и других современных операционных системах) относятся к процессу. Вы отправляете указатель на адрес в виртуальной памяти вашего исходного процесса. В целевом процессе это же местоположение виртуальной памяти может не отображаться, и если оно сопоставлено, это будет нечто совершенно иное.

Чтобы скопировать данные между процессами, используйте сообщение WM_COPYDATA и ОС Windows COPYDATASTRUCT . ОС обеспечивает специальную обработку: она копирует ссылочные данные между процессами и дает целевому процессу указатель на скопированные данные в области памяти целевого процесса.

Кроме того, ваш вызов Marshal.StructureToPtr выглядит неправильно. Ваша структура содержит два указателя (потому что char [] является ссылочным типом), поэтому вы копируете два указателя в ваш HGLOBAL, а не содержимое байтовых массивов. Вы можете использовать MarshalAsAttribute (UnmanagedType.ByValArray), чтобы обойти это, но вам нужно будет добавить информацию о размерах в этом случае. Более простым решением может быть использование метода Marshal.Copy для копирования массивов в неуправляемую память.

Наконец, если вы управляете обоими приложениями и можете использовать .NET 3.0 или выше, рассмотрите возможность размещения службы WCF и отправки данных таким образом. Возможно, вам будет проще, чем использовать сообщения Windows, потому что они будут обрабатывать сериализацию и десериализацию данных для вас - но я понимаю, что это может быть не вариант для вас, или вы, возможно, уже исключили это.

0 голосов
/ 15 января 2010

Чтобы ответить на ваш отредактированный вопрос:

Вы уверены, что у вас есть правильный HWND?

Используйте Spy ++, чтобы убедиться, что HWND указан правильно, и проверьте, видит ли Spy ++ сообщение.

Убедитесь, что вы правильно определили константу WM_COPYDATA в обоих приложениях.

0 голосов
/ 15 января 2010

Вам необходимо отправить сообщение WM_COPYDATA.

См. эту тему .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...