While looking into communication between processes, I wrote the routine SetMutex()
which is quite simple but very effective, and I thought it is worth sharing ...
The routine can be used to signal the execution of a command, routine or process
which then may be monitored by any other process.
The demo program lets you create and monitor lots of named Mutexes.
At start it launches a second instances but additional ones can be loaded at any time.
Keep in mind that a Mutex can only be destroyed in the program where it was created
- by CloseHandle() or by terminating the program.
In this demo the BackSpace key closes only the last handle that was created locally.
The demo has been compiled under PB/CC 5.01. I would assume that it works with PB/Win,
if the #CONSOLE OFF is left out.
Gert Voland.
Attached are .bas and .exe.
which is quite simple but very effective, and I thought it is worth sharing ...
The routine can be used to signal the execution of a command, routine or process
which then may be monitored by any other process.
The demo program lets you create and monitor lots of named Mutexes.
At start it launches a second instances but additional ones can be loaded at any time.
Keep in mind that a Mutex can only be destroyed in the program where it was created
- by CloseHandle() or by terminating the program.
In this demo the BackSpace key closes only the last handle that was created locally.
The demo has been compiled under PB/CC 5.01. I would assume that it works with PB/Win,
if the #CONSOLE OFF is left out.
Gert Voland.
Code:
' SetMutex.bas ' Compiler: PBCC 5.01 ' OS: Windows XP ' Author: Gert Voland ' Date: 20. Apr. 2009 #COMPILE EXE "SetMutex_Test.exe" #DIM ALL #CONSOLE OFF #INCLUDE "Win32Api.inc" $ProgName = "SetMutex_Test.exe" '--------------------------------------------------------------- FUNCTION PBMAIN () AS LONG LOCAL x$, y$, lasty$, txt$ LOCAL ret, last AS LONG LOCAL hGW, hDC AS DWORD LOCAL hFont AS LONG LOCAL i, ist AS LONG LOCAL pID AS DWORD ' Use it here for flagging this test program IF SetMutex($ProgName, 0) = 0 THEN ' Check ' It does not exist yet -> create it SetMutex($ProgName, 1) ' Create txt$ = "First instance of " + $ProgName pID = SHELL($ProgName, 1) ' Start two more instances of this program ELSE ' It is already loaded txt$ = "Another instance of " + $ProgName ' Note: This does not get updated when the first instance terminates END IF IF pID > 0 THEN GRAPHIC WINDOW txt$, 10, 10, 280, 500 TO hGW ELSE GRAPHIC WINDOW txt$, 310, 10, 280, 500 TO hGW END IF GRAPHIC ATTACH hGW, 0, REDRAW FONT NEW "Courier New", 9 TO hFont GRAPHIC SET FONT hFont ' Use it here to create, check and destroy more Mutexes DO GRAPHIC GET DC TO hDC IF hDC = 0 THEN EXIT LOOP ' In case GW has been closed externally SLEEP 0 ' Allow some CPU to other processes GRAPHIC CLEAR ' Always start at top GRAPHIC PRINT " Press the following keys for testing: GRAPHIC PRINT GRAPHIC PRINT " Create: A - Z Destroy: BS Quit: Esc" GRAPHIC INSTAT TO ist IF ISTRUE ist THEN GRAPHIC INKEY$ TO x$ x$ = UCASE$(x$) ELSE x$ = "" END IF SELECT CASE x$ CASE "A" TO "Z" y$ = "Mutex_" + x$ ret = SetMutex(y$, 1) ' Create Mutex IF ret > 0 THEN last = ret ' Mutex did not exist yet - it is the last one being created lasty$ = y$ ' Remember the last one END IF CASE $BS ' Only close the handle created last! IF last > 0 THEN CloseHandle(last) last = 0 ' Forget the last one lasty$ = "" END IF CASE $ESC EXIT LOOP END SELECT GRAPHIC PRINT FOR i = ASC("A") TO ASC("Z") y$ = "Mutex_" + CHR$(i) ret = SetMutex(y$) ' Check Mutex GRAPHIC PRINT " "; y$; " "; SELECT CASE ret CASE 0 GRAPHIC PRINT "---" CASE -1 IF y$ = lasty$ THEN GRAPHIC PRINT "last handle created :"; USING$(" ####", last) ELSE GRAPHIC PRINT "exists" END IF END SELECT NEXT i GRAPHIC REDRAW LOOP GRAPHIC WINDOW END END FUNCTION '--------------------------------------------------------------- FUNCTION SetMutex(BYVAL szMutexName AS ASCIIZ * 64, OPT BYVAL createMx AS LONG) AS LONG ' #INCLUDE "Win32API.inc" ' needed ' ' Purpose: Test if a command/routine/program has been activated by means of a named Mutex. ' ' Usage: ' (1) The first call of SetMutex("MutexName", 1) creates a Mutex and returns the create-handle. ' It may be kept for possibly using CloseHandle() later. ' ' (2) When a Mutex is checked (in whichever program) by SetMutex("MutexName", 0) an OpenMutex is executed. ' The open-handle gets closed again. Thus, the creating program is the only one to keep the Mutex handle. ' Almost any type of activity can be monitored this way, e.g. if a program is loaded, ' or if part of a program is active (or done), etc. ' ' (3) Optionally one can destroy the Mutex using CloseHandle(create-handle) in the program where it was created. ' Still, when the creating program terminates, the Mutex object gets destroyed in any case. ' ' (4) Limitation: A non-creating program cannot find out which program created the Mutex. ' For that, more inter-process communication is needed. ' ' Input: szMutexName : Name of the Mutex to be created or checked (here limited to 63 characters) ' createMx (optional) : 1 => Create the Mutex, 0 => Check the Mutex ' ' Output: FUNCTION = 0 : Mutex does not exist ' = > 0 : = Handle hMutex after creating Mutex ' = -1 : Mutex exists LOCAL hMutex AS LONG ' Create-handle of Mutex IF createMx = 0 THEN ' Check existence. Do not create a new handle, though. hMutex = OpenMutex(BYVAL %MUTEX_ALL_ACCESS, BYVAL 0, szMutexName) IF hMutex = 0 THEN ' No need to close a handle; there is none. FUNCTION = 0 ' Mutex does not exist ELSE ' Close the open-handle CloseHandle(hMutex) FUNCTION = -1 ' Mutex exists END IF ELSE ' Create a Mutex hMutex = CreateMutex(BYVAL 0, BYVAL 1, szMutexName) IF GetLastError = %ERROR_ALREADY_EXISTS THEN ' Close this handle in order to keep only the first create-handle CloseHandle hMutex FUNCTION = -1 ' Mutex exists ELSE ' Do not close the create-handle. The calling program is the only one to "keep" the handle FUNCTION = hMutex ' Return the Mutex create-handle END IF END IF END FUNCTION ' SetMutex '---------------------------------------------------------------
Attached are .bas and .exe.