NDDE: команда выполнения DDE становится бессмысленной к тому времени, когда достигает сервера.
Мне нужно получить доступ к устаревшему приложению через DDE. У меня нет доступа для отладки этого устаревшего приложения, так что для меня это в значительной степени черный ящик.
Однако я знаю, что это работает, потому что у меня есть код VBA, который без проблем взаимодействует с приложением через DDE. Первые несколько строк в коде VBA в основном выглядят так.
lngDDEChannel = DDEInitiate(App:="LEGAPP", Topic:="DDECONV")
DDEExceute channel:=lngDDEChannel, Command:="START_SESSION_12345"
strInfo$ = DDERequest(channel:=lngDDEChannel, Item:="INFO_FIELD")
NB. Фактические имена и команды отличаются от показанных здесь. Однако количество символов в команде такое же, как и в исходной команде. Только символы, которые могут быть представлены в ASCII.
Как уже упоминалось, этот код работает отлично. Кстати, DDERequest предоставит данные только после выполнения команды DDExecute. Если нет, он вернет пустые буферы.
Я пытаюсь перенести этот код на C#. Поскольку Microsoft не реализовала DDE в DotNet, я решил использовать библиотеку с открытым исходным кодом NDDE.
Вот как я переписал приведенный выше фрагмент кода:
using (var client = new DdeClient("LEGAPP", "DDECONV")
{
client.Connect();
client.Execute("START_SESSION_12345");
strVar = client.Request("INFO_FIELD");
}
Соединение между клиентом и сервером установлено, я это проверил. К сожалению, сервер не понимает команду выполнения. Вместо команды "START_SESSION_12345", похоже, появляется какая-то тарабарщина.
Моя первоначальная мысль заключалась в том, что должна быть проблема с кодировкой строки. Строки в VBA - это 7-битные строки ANSI, а в DotNet - 16-битные. Однако NDDE кажется более умным, чем то, что с помощью контекста соединения можно установить определенную кодировку для всех данных, которыми обмениваются с сервером DDE. По умолчанию используется ASCII, что на самом деле должно быть правильным выбором, поскольку все символы в командной строке могут быть представлены в ASCII. Тем не менее, я попытался поиграть с кодировкой контекста со всеми возможными значениями, такими как UTF-7, UTF-8, ANSI, ASCII, UTF-16 (прямой и большой порядок байтов). Что бы я ни пытался, я получаю тарабарщину, это просто немного другая тарабарщина, которая доказывает, что кодировка действительно принимается во внимание.
Я посмотрел исходник NDDE. Соответствующие строки находятся в исходном файле DdemlClient.cs.
var data = _Context.Encoding.GetBytes(command + "\0");
//Send the command to the server.
int returnFlags = 0;
var result = Ddeml.DdeClientTransaction(
data,
data.Length,
_ConversationHandle,
IntPtr.Zero,
Ddeml.CF_TEXT,
Ddeml.XTYP_EXECUTE,
timeout,
ref returnFlags);
Функция DDEClientTransaction подробно описана здесь. NDDE вызывает функцию двумя способами:
[DllImport("user32.dll", EntryPoint = "DdeClientTransaction", CharSet = CharSet.Ansi)]
public static extern IntPtr DdeClientTransaction(IntPtr pData, int cbData, IntPtr hConv, IntPtr hszItem, int wFmt, int wType, int dwTimeout, ref int pdwResult);
[DllImport("user32.dll", EntryPoint = "DdeClientTransaction", CharSet = CharSet.Ansi)]
public static extern IntPtr DdeClientTransaction(byte[] pData, int cbData, IntPtr hConv, IntPtr hszItem, int wFmt, int wType, int dwTimeout, ref int pdwResult);
Код в моем примере использует второе объявление pinvoke, но я также пробовал использовать первое, без разницы.
Я застрял. Поскольку диалог DDE через VBA работает нормально, я должен предположить, что с сервером DDE нет общей проблемы. Понятия не имею, почему это не работает.
РЕДАКТИРОВАТЬ
Я провел несколько тестов, чтобы уточнить, какие данные передаются. Для целей этого теста я просто изменил команду выполнения на "ABCD".
Encoding.Default (= кодовая страница ANSI) создает следующий массив байтов:
Приложение получает это как команду:
Encoding.ASCII создает следующий массив байтов:
Приложение получает это как команду:
Encoding.Unicode (например, UTF-16) создает следующий массив байтов:
Приложение получает это как команду:
Может быть, это даст кому-то умнее меня правильное представление о том, что не так.