NDDE: команда DDE Execute становится gibberi sh к тому времени, когда она достигает сервера - PullRequest
1 голос
/ 26 января 2020

Мне нужно получить доступ к устаревшему приложению через 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 в Do tNet, я решил go с библиотекой с открытым исходным кодом NDDE .

Вот как я переписал фрагмент кода выше:

using (var client = new DdeClient("LEGAPP", "DDECONV")
{
    client.Connect();
    client.Execute("START_SESSION_12345");
    strVar = client.Request("INFO_FIELD");
}

Соединение между клиентом и сервером установлено, я это проверил. К сожалению, сервер не понимает команду execute. Вместо команды "START_SESSION_12345", похоже, получено немного гиббери sh.

Error message legacy app

Первоначально я думал, что должна быть проблема с кодировкой строки. Строки в VBA - это 7-битные строки ANSI, а строки в Do tNet - 16-битные. Однако NDDE кажется умнее, чем при использовании контекста соединения, можно задать специфицированную кодировку c для всех данных, которыми обмениваются с сервером DDE. По умолчанию используется ASCII, который на самом деле должен быть правильным выбором, поскольку все символы в командной строке могут быть представлены в ASCII. Тем не менее, я попытался поиграть с контекстной кодировкой со всеми возможными значениями, такими как UTF-7, UTF-8, ANSI, ASCII, UTF-16 (младший и старший порядковый номер). Независимо от того, что я пытаюсь, я продолжаю получать гиббери sh, это просто немного другой гиббери sh, который доказывает, что кодировка действительно учитывается.

Я посмотрел на источник 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 нет общей проблемы. Я понятия не имею, почему это не работает.

РЕДАКТИРОВАТЬ

Я провел несколько тестов, чтобы выяснить для себя, какие данные передаются. Для целей этого теста я изменил команду execute просто на «ABCD».

Encoding.Default (= кодовая страница ANSI) создает следующий байтовый массив:

Byte Array ANSI

Приложение получает это как команду:

ANSI error

Encoding.ASCII создает следующий байтовый массив:

Byte Array ASCII

Приложение получает это как команду:

ASCII Error

Encoding.Unicode (т. е. UTF-16) создает следующий байтовый массив:

Byte Array Unicode UTF-16

Приложение получает это как команду:

Unicode Error

Может быть, это даст кому-то умнее меня правильная идея, что не так.

...