C # строка для длинного указателя - PullRequest
2 голосов
/ 22 июня 2010

Я работаю с приложением в C #, которому нужно отправить сообщение в приложение C ++.

Я импортировал

[DllImport("user32.dll")]
        public static extern IntPtr SendMessage(
              int hWnd,      // handle to destination window
              uint Msg,       // message
              IntPtr wParam,  // first message parameter
              IntPtr lParam   // second message parameter
              );

но теперь моя проблема в том, что мне нужно вставить строку в wParam и lParam . Я пробовал небезопасный код, но кажется, что строка просто не работает, как остальные переменные. Как я могу этого достичь? Спасибо.

Ответы [ 3 ]

11 голосов
/ 22 июня 2010

Объявление неверное, аргументы wParam и lParam имеют тип IntPtr, не длинный.

Существует сложность, поскольку вы пытаетесь отправить строки.Что имеет значение, если в целевом окне включен Юникод или нет.Существует две версии SendMessage, SendMessageA () и SendMessageW ().Первый нужно использовать, если программа датирована и использует 8-битные символьные строки, а не строки в кодировке UTF-16.

Это можно узнать с помощью Spy ++.Используйте инструмент поиска, чтобы выбрать окно приложения.На вкладке Общие свойства вы увидите «Window proc».Он скажет (Unicode), если окно поддерживает Unicode.Если вы этого не видите, строки должны быть переведены в 8-битные символы.

Для генерации указателей строк, которые вам нужно передать, вы можете использовать Marshal.StringToHGlobalAnsi или StringToHGlobalUni (соответственно 8-битный иUnicode).Однако вы можете подшутить, чтобы маршаллер P / Invoke перевел вам строку.Избавляет вас от необходимости освобождать строки после звонка.Для версии Ansi вы можете объявить функцию API следующим образом:

    [DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA", ExactSpelling = true)]
    private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);

И версию Unicode, например:

    [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
    private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);

Последнее замечание: это не будет работатькак есть, если окно принадлежит другому приложению, вы его сломаете.Передаваемые вами значения указателя действительны только в вашем собственном процессе, а не в процессе C ++.Чтобы обойти это, вы должны выделить память в целевом процессе, чтобы указатель был действительным.Для этого требуется OpenProcess, чтобы получить дескриптор процесса, VirtualAllocEx () для выделения памяти в целевом процессе, достаточно большой для хранения строки, WriteProcessMemory для записи строки.Теперь вы можете вызвать SendMessage (), использовать версию, объявленную с IntPtr для аргументов wParam и lParam, передать значение, полученное из VirtualAllocEx.Затем используйте VirtualFreeEx () для освобождения памяти и CloseHandle для очистки.Или сохраните память в следующий раз, если вы будете делать это часто.

Довольно много P / Invoke, чтобы ошибиться там.Не говоря уже о проблемах безопасности, WriteProcessMemory требует прав администратора, повышение прав UAC.

0 голосов
/ 25 июня 2010

Мы решили использовать WmCpyDta_d.dll для всего этого.

0 голосов
/ 22 июня 2010

Передача адреса строки может привести к небезопасному коду, поскольку вызовы Win32 API ожидают адреса (в собственном окружении C / C ++).Какое оконное сообщение вы отправляете, для которого требуется строка в wParam или lParam?

...