1

我需要通过 DDE 访问旧版应用程序。我没有对这个遗留应用程序的调试访问权限,所以它对我来说几乎是一个黑匣子。

但是,我确实知道它可以工作,因为我有一些 VBA 代码可以通过 DDE 与应用程序通信而没有问题。VBA 代码的前几行基本上是这样的。

lngDDEChannel = DDEInitiate(App:="LEGAPP", Topic:="DDECONV")
DDEExceute channel:=lngDDEChannel, Command:="START_SESSION_12345"
strInfo$ = DDERequest(channel:=lngDDEChannel, Item:="INFO_FIELD")

注意 实际名称和命令与此处显示的不同。但是,命令中的字符数等于原始命令的字符数。只有可以用 ASCII 表示的字符。

如前所述,这段代码工作得很好。附带说明一下,DDERequest 只会在 DDExecute 命令执行后提供数据。如果没有,它将返回空缓冲区。

我正在尝试将此代码移植到 C#。由于微软没有在 DotNet 中实现 DDE,我决定使用开源库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 声明,但我也尝试使用第一个,没有区别。

我被困住了。由于通过 VBA 的 DDE 对话工作得很好,我不得不假设 DDE 服务器没有一般问题。我不知道为什么这不起作用。

编辑

我做了一些测试,只是为了澄清自己正在传输什么样的数据。出于本次测试的目的,我将执行命令简单地更改为“ABCD”。

Encoding.Default (=ANSI Codepage) 创建以下字节数组:

字节数组 ANSI

应用程序将其作为命令接收:

ANSI 错误

Encoding.ASCII 创建以下字节数组:

字节数组 ASCII

应用程序将其作为命令接收:

ASCII 错误

Encoding.Unicode(即 UTF-16)创建以下字节数组:

字节数组 Unicode UTF-16

应用程序将其作为命令接收:

Unicode 错误

也许这会给比我更聪明的人一个正确的想法,什么是错的。

4

0 回答 0