Making sure an application runs only in one instance
Especially on Windows Mobile 5 smartphones, it's difficult to handle an application that starts a new instance of itself each time it is started. You can't really easy get back to already open application windows, and you can't even easily close them.
But then, you most often don't really need multiple instances of an application running, since their mostly fullscreen anyway and another instance gives you no advantages. Now there are a bunch of methods to prevent that, for example creating a Mutex. If it gets created, you can continue, if it fails because the Mutex already exists, you can terminate the application.
Since Windows CE applications are centered around one main window usually, we'll make it even easier. We can use FindWindow if we know the class name or title of the window (or both) of your application (using my simple no-framework example, you can find the class name as FClassName, while using the LCL, it's probably the name of your main forms class). If this window is found, there's already another instance running, which you'll probably want to bring to the foreground.
var hExisting: THandle;
// ...
begin // main loop
hExisting := FindWindow(sMainWindowClassName, nil);
if hExisting<>0 then begin
SetForegroundWindow(hExisting);
Halt(1);
end;
// ...
end.
This code should be at the very beginning of your application of course, since it needs to run before your main window is created (otherwise it would always quit). The disadvantage of this code would be that your class name needs to be quite unique, because depending on window titles alone wouldn't be too safe.
Other methods would be:
Method 2 (Mutex): Use CreateMutex to create a system-wide named mutex, then check if the return value is ERROR_ALREADY_EXISTS, in which case there's already another instance of the application running (that previously succeeded in creating the mutex). The disadvantage is that you've got to make sure you release it using ReleaseMutex, no matter how your application terminates. Also, when you have the mutex, you still don't have the handle of the window to bring to the foreground.
Method 3 (Message Ping): You could broadcast your own custom message through the system, using PostMessage with HWND_BROADCAST and a new message you created using RegisterWindowMessage. Then you would need to catch that as well, and reply with another similar message. The disadvantage of this method is that you need to give your application some time to receive the echo for your ping. At least the echo will contain the handle of the window of the other running instance to bring to the foreground.
With Win32, you may want to at least think about using messages to pass along parameters (for files to be opened) to the running instance using WM_COPYDATA.
Method 4 (Process list): you could enumerate all running processes to see if another process with your filename, and path if available, is running (which you can either believe or do a MD5 check to be sure it's not someone just using the same filename). If you find more than one instance, you'll have to switch to the one that is not you (doesn't have the current processes process id). For getting a processes main window handle, which you need to bring to the foreground, you can use messages or FindWindow again for example.
As you can see, all methods have their up- and downsides, but the FindWindow one is probably the easiest one if you have some kind of main window you can depend on.

0 Comments:
Post a Comment
<< Home