This is a COM component to allow scripting of DDE Servers. It is an Automation Server (i.e. it is programmable via IDispatch) that houses two fundamental COM classes. The first is a DDE Client, which is a Singleton style object that can be used to make ad-hoc DDE queries and querying for running DDE servers. The second is for a specific DDE Conversation and can be used as an optimisation when you need to query many values from the same DDE source.
At present it only supports the requesting of data in CF_TEXT format, which is then converted to UNICODE to pass back over the COM interface. Most of the DDE servers I have dealt with were ANSI based and given the nature of scripting I felt this was probably good enough for a first attempt. If there is a need to allow access in other formats (e.g. CF_UNICODETEXT, CF_DIF etc) I will add to the API. It also only supports DDE Requests [XTYP_REQUEST], but could be easily extended to allow Pokes [XTYP_POKE] and Executes [XTYP_EXECUTE].
The other major feature of DDE that is missing is the asynchronous updating of values via advise loops (a.k.a. DDE Links). These have not been implemented as I did not know if it is possible to handle COM events from scripting languages such as VBScript.
The component is implemented using dual interfaces, so also supports early binding. However, if you're using C++ you would be better off using the underlying NCL library/DDE classes directly.
The DDE Client class is essentially a Singleton style class that provides simple access to DDE servers. If all you need to do is query for a few values from a DDE source or two you can do it with repeated calls to RequestTextItem. It also provides access to the Wildcard style request [XTYP_WILDCONNECT] so that you can query for running servers and their topics.
Finds out which DDE servers are currently running and returns a collection of the server names. The collection is an array of strings.
Finds out what topics are supported by a DDE server. The return value is an array of strings which are the topic names.
Open a DDE conversation for a specific Server and Topic.
See the DDE Conversation class for other ways to open a conversation.
Get the collection of open DDE conversations. This collection is enumerable
using the "For Each" idiom or can be indexed directly using the Item
method
NB: The Item method follows the VBScript and WMI convention of being 0-based.
Request the current value for a single item from a named service and topic. The item is requested in CF_TEXT (i.e. ANSI) format and then converted to UNICODE to pass back via COM as a string.
The DDE Conversation class is really an optimisation (and an excuse for me to implement a COM collection :-) that avoids the overhead of creating a conversation every time an item is requested. If you have many values to request from a single Service|Topic pair, open an explicit conversation either from the DDE Clients' OpenConversation method, or use the "ddelink:" moniker namespace, then use that to request the items.
This property is the DDE service name. It can be read at any time, but only modified when the conversation is not open.
This property is the DDE topic name. It can be read at any time, but only modified when the conversation is not open.
Opens the conversation specified by the Service and Topic properties. If the
conversation is already open, an error is returned.
This method allows a DDE conversation to be opened by creating an explicit
DDE Conversation object, setting the Service and Topic names and then calling
Open().
Checks if the conversation is currently open. Returns True or False.
Closes the DDE conversation. If the conversation is not open then the operation has no effect.
Request the current value for a single item. The item is requested in CF_TEXT (i.e. ANSI) format and then converted to UNICODE to pass back via COM as a string.
WMI uses a moniker namespace of "winmgmts" to support simpler creation of WMI queries by encoding the query as a moniker item, which in VBScript you pass to GetObject(). You can achieve a similar effect with DDE Conversations by using the "ddelink" namespace. The full moniker consists of the "ddelink:" prefix, a "//" separator and the moniker item is the Service and Topic name in DDE Link format, e.g.
ddelink://SERVICE|TOPIC
This helpfully gives the link a URL like syntax, and when support for true links are added the syntax can be updated to allow a "!Item" style suffix.
All the COM objects support IErrorInfo, so you will receive textual error messages along with the result code. If the underlying error comes from DDE itself, then the symbolic name for the error code will be included (e.g. DMLERR_BUSY) which you can look up in the DDE SDK.
The following set of examples should cover the most common scenarios. They are written in VBScript as scripting was the reason I created the components. The initial example shows how to create the DDE Client, which is then assumed in the subsequent code snippets.
Dim oDDEClient
Set oDDEClient = CreateObject("DDECOMClient.DDEClient")
Dim astrServers, astrTopics
Dim i, j
astrServers = oDDEClient.RunningServers()
For i = LBound(astrServers) To UBound(astrServers)
WScript.Echo "Server: " & astrServers(i)
astrTopics = oDDEClient.GetServerTopics(astrServers(i))
For j = LBound(astrTopics) To UBound(astrTopics)
WScript.Echo " Topic: " & astrTopics(j)
Next
Next
Dim strValue
strValue = oDDEClient.RequestTextItem("PROGMAN", "PROGMAN", "Accessories")
Dim oDDEConv
Set oDDEConv = oDDEClient.OpenConversation("PROGMAN", "PROGMAN")
or
Dim oDDEConv
Set oDDEConv = GetObject("ddelink://PROGMAN|PROGMAN")
or
Dim oDDEConv
Set oDDEConv = CreateObject("DDECOMClient.DDEConversation")
With oDDEConv
.Service = "PROGMAN"
.Topic = "PROGMAN"
End With
Dim oDDEConv
Set oDDEConv = GetObject("ddelink://PROGMAN|PROGMAN")
Dim strValue1, strValue2, strValue3
strValue1 = oDDEClient.RequestTextItem("Accessories")
strValue2 = oDDEClient.RequestTextItem("Games")
strValue3 = oDDEClient.RequestTextItem("Startup")
This COM component is freeware - you get what you pay for, nothing more, nothing less.
The full source code (C++) is available from my web site listed below.
Email: gort@cix.co.uk
Web: www.cix.co.uk/~gort
Chris Oldwood
19th July 2007