In my search for the best way to communicate between processes (seperate exe’s), I’ve come across some interesting techniques. I’d like to highlight some of the features and downfalls of what I’ve found for future reference. This quest is just about over, as I’m finishing up my code for this project.
Sockets – The first method that comes to mind is to use a socket. TCP could be used for a stateful connection, or UDP to send information blindly and wait for a response. Localhost can be used for both sending and binding, which avoids hacks from over the network or the internet, but firewall exceptions will still need to be handled on some systems. None of this is very hard to do, but the down side of using a socket is the added overhead on the system. A single port or 2 may not sound like much, but TCP/UDP are complex protocols, which leads me to believe there’s a better way.
Memory Map – A memory map is when an isolated chunk of memory is shared and accessible by multiple processes. I’ve had a prototype project of this working, and seems stable enough to use in the right situation, but timing is a price you’ll have to pay. App A can send information to the shared memory space, but app B doesn’t know of its existence until a timer is triggered to check it. If the receiving app isn’t actively checking the memory space for incoming data, the data will be stuck there clogging the mailbox, so to speak. In this case, your only 2 options are to overwrite the contents, or keep waiting.
Subclassing – Subclassing is when a program inserts its own function in before the normal event handling. Let me try to explain this a little better. Say you click on a window, or type something into a text box. Those events get sent from the Windows OS into the program. Those events can be intercepted by subclassing, sorta like a man in the middle. As it sounds, there is a lot of power that can be harnessed using this method. Along with that power comes a lot of danger. If implemented improperly, your program can crash, or even the IDE (development environment) if you’re running it from there. I’ve found some great code by Paul Caton, on PlanetSourceCode.com, which doesn’t crash the IDE when stopping or pausing the project. I still have yet to see how it performs as part of my full Grow Control project, but I have high hopes. If it fails to meet my expectations, I may have to try moving the subclassing into a DLL or OCX to try preventing crashes while developing.
The second part of subclassing is SendMessage and WM_SETTEXT. This simulates sending an event to the app with a string. This can be captured by the subclass proc function before it makes it to the form. This is easy enough to do with a single line of code. The hard part was grabbing the string back from the captured event. I’ve uploaded my code to PlanetSourceCode, and below is the trick to getting the job done.
l = lstrlen(lParam)
If l Then
Call CopyMemory(sString, lParam, l)
PointerToString = StrConv(sString, vbUnicode)
End If
Mutex – The subclassing method above is what I plan to use, but I think this is worth mentioning too. Mutex stands for mutual exclusion. It’s an api for creating a named lock. Only one mutex can be created with a unique name. (they can be shared, but that’s not what we’re going for here, so nevermind that.) It can’t send strings or commands for communication, but it is very useful for managing the number of instances of an app are allowed to run. Most of the code examples I found on the internet are missing a critical part. You must first run the ReleaseMutex api before CloseHandle. If the handle is only closed and ReleaseMutex isn’t used, the Mutex lock remains until the apps process is ended. This works out fine if you’re only intending to use it to allow a single instance, but it poses a problem if another app is trying to test the lock and not leaving it enforced. Use this api properly and it will prove to be extremely useful.
Handle = CreateMutex(0&, 1&, Name)
If Handle <> 0 Then
If WaitForSingleObject(Handle, 0) = 0 Then
MsgBox Handle
ReleaseMutex Handle
End If
CloseHandle Handle
End If