使用VB.NET编写DDE服务器

动态数据交换(DDE)是一种在Windows应用程序之间共享数据的旧协议。尽管现代应用程序更倾向于使用COM或.NET Remoting等技术,但在某些遗留系统中仍需要DDE支持。VB.NET可以通过Windows API实现DDE服务器功能。

DDE基础概念

DDE协议基于客户端-服务器模型,通过三个标识符建立连接:服务名(Service)、主题名(Topic)和项目名(Item)。服务器应用程序需要注册服务名和主题名,客户端通过这两个标识符建立连接后,可以请求特定的项目数据。

Windows API提供了DdeInitializeDdeNameService等函数用于DDE通信。在VB.NET中需要通过P/Invoke调用这些API函数:

Declare Function DdeInitialize Lib "user32" Alias "DdeInitializeA" (
    ByRef pidInst As Integer,
    ByVal pfnCallback As DdeCallback,
    ByVal afCmd As Integer,
    ByVal ulRes As Integer
) As Integer
实现DDE服务器类

创建一个DDEServer类封装DDE功能。该类需要处理DDE初始化、名称注册和回调函数:

Public Class DDEServer
    Private _instance As Integer
    Private _serviceName As String
    
    Public Sub New(serviceName As String)
        _serviceName = serviceName
        Dim result = DdeInitialize(_instance, AddressOf DdeCallback, APPCLASS_STANDARD, 0)
        If result <> DMLERR_NO_ERROR Then
            Throw New Exception("DDE初始化失败")
        End If
    End Sub
    
    Public Sub Register()
        Dim hszService = DdeCreateStringHandle(_instance, _serviceName, CP_WINANSI)
        Dim result = DdeNameService(_instance, hszService, IntPtr.Zero, DNS_REGISTER)
        DdeFreeStringHandle(_instance, hszService)
    End Sub
End Class
实现回调函数

DDE回调函数处理客户端请求,需要处理XTYP_CONNECTXTYP_REQUEST等事务类型:

Private Function DdeCallback(
    ByVal wType As Integer,
    ByVal wFmt As Integer,
    ByVal hConv As Integer,
    ByVal hsz1 As Integer,
    ByVal hsz2 As Integer,
    ByVal hData As Integer,
    ByVal dwData1 As Integer,
    ByVal dwData2 As Integer
) As IntPtr
    Select Case wType
        Case XTYP_CONNECT
            Dim topic = DdeQueryString(_instance, hsz2)
            If topic = "MyTopic" Then Return New IntPtr(1)
            
        Case XTYP_REQUEST
            Dim item = DdeQueryString(_instance, hsz2)
            If item = "MyItem" Then
                Dim data = "Sample Data"
                Return DdeCreateDataHandle(_instance, data, data.Length + 1, 0, hsz2, CF_TEXT, 0)
            End If
    End Select
    
    Return IntPtr.Zero
End Function
数据更新通知

当服务器数据变化时需要通知已连接的客户端,使用DdePostAdvise函数:

Public Sub UpdateData(topic As String, item As String)
    Dim hszTopic = DdeCreateStringHandle(_instance, topic, CP_WINANSI)
    Dim hszItem = DdeCreateStringHandle(_instance, item, CP_WINANSI)
    DdePostAdvise(_instance, hszTopic, hszItem)
    DdeFreeStringHandle(_instance, hszTopic)
    DdeFreeStringHandle(_instance, hszItem)
End Sub
清理资源

应用程序退出时需要注销DDE名称并释放资源:

Public Sub Unregister()
    Dim hszService = DdeCreateStringHandle(_instance, _serviceName, CP_WINANSI)
    DdeNameService(_instance, hszService, IntPtr.Zero, DNS_UNREGISTER)
    DdeFreeStringHandle(_instance, hszService)
    DdeUninitialize(_instance)
End Sub

使用示例

创建一个简单的DDE服务器并注册主题:

Dim server As New DDEServer("MyDDEService")
server.Register()

' 模拟数据更新
server.UpdateData("MyTopic", "MyItem")

注意事项

  1. DDE是16位Windows时代的旧技术,现代应用程序应考虑使用更先进的进程间通信方式
  2. DDE通信不提供安全机制,可能带来安全隐患
  3. 在高频率数据交换场景下性能较差
  4. 需要处理多线程问题,DDE回调可能在不同线程触发

通过上述方法可以在VB.NET中实现基本的DDE服务器功能,与支持DDE协议的客户端应用程序进行数据交换。对于新项目,建议考虑使用.NET Remoting、WCF或命名管道等现代IPC技术替代DDE。

https://github.com/fenrevnik/3fe_rhun
https://github.com/kezjanbato/21g_tpmv
https://github.com/ovenleg9/wp0_x5br
https://github.com/yashtripha/bsi_3rwo
https://github.com/chefline9/722_gn4o

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐