One of the more neglected IPC technologies in Windows is Message Queuing. While in an AD domain you can do some fancy stuff with relay servers and such, it's quite possible to make use of MSMQ queues within a Workgroup LAN or just locally within one machine. Simple private local machine queues are all I need here. With WinXP the MSMQ facility is at version 3.0 and quite robust, though even NT 4.0 supported it, as did Win9x to a more limited extent.
MSMQ is an optional Windows component. If you don't have it in place just use Add/Remove Programs to install it. Prior to WinXP MSMQ Triggers is a separate download. Once these are in place you'll have two additional Services running on your machine. Queues and Triggers can be administered via the Computer Management MMC snap-in under Services and Applications.
Without going into the subject too deeply, a sending program creates and sends messages to a queue. These messages are held in sequence until processed. Queues can be persisted to disk so that messages are even retained in those queues across a reboot. Receivers process messages from the queues and optionally return results back to the sender via reply queues. Each message can designate its individual reply queue, and this lets one receiver (or queue service application) handle messages inserted into its queue by multiple senders (or requestors).
Since a message has several properties that can be used for identification (Label: a 0 to 250 Unicode character String, CorrelationID: a 20 byte Byte Array, and AppSpecific: a Long) it is even possible to have a single queue that is serviced by multiple readers. Each reader "walks through" the queue peeking messages looking for ones that it handles.
Receivers can process queues synchronously or asynchronously, and the MSMQ COM objects make this easy in VB programs.
Messages also have a Body property that contains the primary payload. The Body value is a Variant when using the MSMQ COM objects, and you can put in a String, Integer, Long, etc. or even an Object (any persistent COM object that supports IDispatch and IPersist). One could also manually serialize an Object into a PropertyBag and pass it's Contents property as a Body. Sadly, there is no direct support for VB's UDTs.
The point of writing this is that I searched all over but couldn't find any real detail on how MSMQ Triggers work.
Well that's not entirely true. But what I couldn't find was how the heck a Trigger's Rule Action works when set to "Invoke standalone executable."
So here's the scoop, based on some experimentation:
When a new message is inserted into the queue that meets the criteria specified in the Rule Condition, the EXE specified by the Rule is run. The EXE then does "whatever" such as processing queue messages. When the EXE chooses to (such as no additional messages left to process) it terminates. This "wakes up" the Rule again, which waits for new messages and when it sees one it runs the EXE again.
The process is slightly more involved but in principle that's about it.
A queue can have multiple Triggers and Triggers can have multiple Rules set up, and the Rules can examine various queue Properties to decide whether to fire off one or more EXEs. Rules can also invoke COM components but that's not what I was interested in at the time, and it's another story though quite similar.
I was worried that the Trigger Rule would fire for each message inserted, and start the EXE once for each one. Not very efficient! Fortunately things don't work that way.
I have a situation where another (non-Windows) platform no longer has vendor support for some specialized processing. This vendor does offer Windows versions of their software, which basically consists of callable standard DLLs that accept parameters, process them against a database, and return results. The internals of these things are in some sort of interpreted Cobol! The DLLs hook into that via some proprietary interop scheme I don't even want to think about.
The old platform doesn't do DCOM, doesn't do WinRPC, etc. What it does do is support application program calls into a service library that can remap the calls into request/response transactions over a TCP connection.
So I can write a small socket service in VB that will run as a Windows Service using NTSVC.ocx or SRVANY.exe to accept the requests and send them to a queue. As responses come back via a reply queue I can return them back to the other platform over the TCP connection. Since the "calling" platform will include a correlation value in its request I can simply return that value back with the reply... which lets requests and replies overlap in time, i.e. the requests do not require synchronous processing.
Using queues and triggers gives me a nice way to decouple the application code from the socket service, which becomes a small and easily maintained program. The individual service applications become fairly small isolated programs running in their own processes as well. A new service application is easily installed by disabling its Trigger, replacing the program, and enabling the Trigger again. Even better than placing the application logic into COM libraries called by the socket service!
Each service application can process messages for one or more request types which I indicate by the message's Label property, in turned based on a Request Type field in the TCP message from the old platform making requests. By writing these to use a long timeout reading the queue they can quietly terminate after a period of no work to do. The Trigger wil restart them upon demand.
By using the message's AppSpecific property to pass the socket index of the caller I can handle multiple TCP connections from one or more external platforms.
I can also add new services by creating a new EXE to handle them and adding a new Rule to the Trigger, and I never have to modify the socket service program.
A rough diagram is included below.
For those who haven't tried playing with MSMQ I've attached a tiny demo.
There is a VB6 program "QReader" that will create a test queue and listen for messages, displaying those it finds. If it doesn't see any messages for 30 seconds it gives you a chance to delete the queue, a cleanup option for when you're through.
Once QReader has been started (creating the queue) you can run the VB6 "QWriter" program. QWriter lets you enter Label and Body string values, which it uses to create a message and insert it into the test queue.
After running QReader once to create the queue, you can run QWriter even when QReader isn't running. When you do subsequently run QReader it will pick up those "offline" messages.
These will run "triggerless" or you can set up a Trigger on the queue to automatically start QReader when appropriate messages (as defined by a Rule) are inserted.
Note that these were written for MSMQ 3.0 so they'll only run on WinXP or later but can be modifed to run on Win2K or NT 4.0, though not Win9x.