This is a slight variation of the earlier post with a Mutex.

o Now Events are used (Events and Mutexes behave the same in respect to being created and opened).

o The function has been split into SetStaticEvent() and GetStaticEvent().

o Another addition is the detection of name conflicts (return value = -2).

The two routines are still very simple and effective for flagging inter-process events.

The method is also quite safe, because only the program that has created an event object keeps the handle.
If the user "forgets" to close the handle, and thus does not destroy the Event object, it gets killed automatically, when the process terminates.
Note that there is no "event signaling"; the mere existence of an Event object is being used.

Attached are also the PB/CC-compiled .exe files of StaticEvent_Test.bas and UseEventNameSpace.bas.
The latter one occupies a few Event names by Mutexes. The program should be started before or during execution of the event tests.

Best regards,
Gert Voland.


Code:
' StaticEvent_Test.bas

' Compiler:     PBCC 5.01
' OS:           Windows XP
' Author:       Gert Voland
' Date:         27. Apr. 2009

#COMPILE EXE "StaticEvent_Test.exe"
#DIM ALL
#BREAK ON
#CONSOLE OFF

#INCLUDE "Win32Api.inc"

$ProgName = "StaticEvent_Test.exe"

'---------------------------------------------------------------

FUNCTION PBMAIN () AS LONG

    LOCAL x$, y$, txt$
    LOCAL hGW, hDC      AS DWORD
    LOCAL hFont         AS LONG
    LOCAL i, ist        AS LONG
    LOCAL hProg         AS LONG
    LOCAL pID           AS DWORD
    LOCAL imin, imax    AS LONG
    LOCAL ret, hBS      AS LONG

    imin = ASC("A")
    imax = ASC("Z")
    DIM hcreated(imin TO imax)   AS LONG

    ' Use it here for flagging this test program
    IF GetStaticEvent($ProgName) = 0 THEN                       ' Check
        ' It does not exist yet -> create it
        hProg = SetStaticEvent($ProgName)                       ' Create
        txt$ = "First instance of " + $ProgName
        pID = SHELL($ProgName, 1)                               ' Start the first instance of this program
    ELSE
        ' Program is already loaded
        txt$ = "Another instance of " + $ProgName               ' Second instance. 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 several Events
    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$ = "Event_" + x$
                ret = SetStaticEvent(y$)                        ' Create Event
                IF ret > 0 THEN
                    hcreated(ASC(x$)) = ret                     ' Store create handle
                END IF

            CASE $BS                                            ' Close handles from _Z backwards ...
                FOR i = imax TO imin STEP -1
                    hBS = hcreated(i)
                    IF hBS > 0 THEN
                        CloseHandle(hBS)
                        hcreated(i) = 0
                        EXIT FOR
                    END IF
                    NEXT i

            CASE $ESC
                EXIT LOOP

        END SELECT

        GRAPHIC PRINT

        FOR i = ASC("A") TO ASC("Z")
            y$ = "Event_" + CHR$(i)
            GRAPHIC PRINT " "; y$; "   ";

            ' Check if locally created
            IF hcreated(i) > 0 THEN
                GRAPHIC PRINT "locally created: ";hcreated(i)
                ITERATE FOR
            END IF

            ' Check if events exists
            ret = GetStaticEvent(y$)                            ' Check Event
            SELECT CASE ret
                CASE 0
                    GRAPHIC PRINT "---"

                CASE -1
                    GRAPHIC PRINT "exists"

                CASE -2
                    GRAPHIC PRINT "name not available"
            END SELECT
        NEXT i

        GRAPHIC REDRAW
    LOOP

    CloseHandle(hProg)                                          ' This is pc (programmatically correct)
    GRAPHIC WINDOW END

END FUNCTION

'---------------------------------------------------------------

FUNCTION SetStaticEvent(BYVAL szEventName AS ASCIIZ * 64) AS LONG
' #INCLUDE "Win32API.inc"    ' needed
'
' Purpose:  Create a static Event
'
' Method:   The mechanism of Window's named Events is used to create and check the status of an Event.
'           Therefore it can be used as a system-wide flag that can be monitored by any process.
'           Only the existence of an Event is used. Since there is no call to any wait function, the signaling
'           state of the Events does not matter and the use of SetEvent() and ResetEvent() has no effect.
'
' Usage:
' (1) The first call of  SetStaticEvent("EventName")  creates an Event and returns the create-handle.
'     This handle may be kept for executing  CloseHandle() later. A second call with same name returns -1 (Event exists).
'
' (2) When an Event is checked (in whichever program) by  GetStaticEvent("EventName")  an OpenEvent() is executed.
'     The open-handle gets closed again. Thus, the creating program is the only one to keep the Event handle.
'
' (3) CloseHandle(create-handle)  has to be used in the program where it was created to destroy the Event.
'     When the creating program terminates, all Event objects created this way get destroyed in any case.
'
' Input:    szEventName          :  Name of the Event to be created (here limited to 63 characters)
'
' Output:   FUNCTION = > 0       :  = Handle hEvent after creating Event
'                    = -1        :  Event exists
'                    = -2        :  Event not created due to name conflict

    LOCAL hEvent    AS LONG     ' Create-handle of Event

    hEvent = CreateEvent($NUL, 1, 1, szEventName)               ' Manual reset = 1, Event is signaled

    SELECT CASE LONG GetLastError
        CASE %ERROR_ALREADY_EXISTS
            ' Close this handle in order to keep only the first create-handle
            CloseHandle hEvent
            FUNCTION = -1                                       ' Event exists

        CASE %ERROR_INVALID_HANDLE
            ' Name exist already
            FUNCTION = -2                                       ' Event not created due to name conflict

        CASE ELSE
            ' Do not close the create-handle. The calling program is the only one to keep the handle
            FUNCTION = hEvent                                   ' Return the Event create-handle
    END SELECT

END FUNCTION    ' SetStaticEvent

'---------------------------------------------------------------

FUNCTION GetStaticEvent(BYVAL szEventName AS ASCIIZ * 64) AS LONG
' #INCLUDE "Win32API.inc"    ' needed
'
' Purpose:  Check if an Event exists
'
' Method and Usage:    See  SetStaticEvent()
'
' Input:    szEventName          :  Name of the Event to be checked (here limited to 63 characters)
'
' Output:   FUNCTION = 0         :  Event does not exist
'                    = -1        :  Event exists
'                    = -2        :  Event not checked due to name conflict

    LOCAL hEvent    AS LONG     ' Create-handle of Event

    hEvent = OpenEvent(%Event_ALL_ACCESS, 0, szEventName)

    IF hEvent = 0 THEN
        IF GetLastError = %ERROR_INVALID_HANDLE THEN
            FUNCTION = -2                                       ' Event object not opened due to name conflict
        ELSE
            ' No need to close a handle; there is none.
            FUNCTION = 0                                        ' Event does not exist
        END IF
    ELSE
        ' Close the open-handle
        CloseHandle(hEvent)
        FUNCTION = -1                                           ' Event exist
    END IF

END FUNCTION    ' GetStaticEvent

'---------------------------------------------------------------

Program to cover some Event names by using Mutexes:

Code:
' UseEventNameSpace.bas

' Compiler:     PBCC 5.01
' OS:           Windows XP
' Author:       Gert Voland
' Date:         27. Apr. 2009

#COMPILE EXE "UseEventNameSpace.exe"
#DIM ALL
#BREAK ON
#CONSOLE ON

#INCLUDE "Win32Api.inc"

'---------------------------------------------------------------

FUNCTION PBMAIN () AS LONG

    LOCAL hMutex    AS LONG

    CONSOLE SET SCREEN 10, 35

    PRINT " Create Mutexes with Event names"
    PRINT

    hMutex = CreateMutex(BYVAL 0, BYVAL 1, "Event_M")
    PRINT " Event_M created as Mutex"; hMutex

    hMutex = CreateMutex(BYVAL 0, BYVAL 1, "Event_U")
    PRINT " Event_U created as Mutex"; hMutex

    hMutex = CreateMutex(BYVAL 0, BYVAL 1, "Event_T")
    PRINT " Event_T created as Mutex"; hMutex

    hMutex = CreateMutex(BYVAL 0, BYVAL 1, "Event_E")
    PRINT " Event_E created as Mutex"; hMutex

    hMutex = CreateMutex(BYVAL 0, BYVAL 1, "Event_X")
    PRINT " Event_X created as Mutex"; hMutex
    PRINT

    PRINT " ... any key to finish";
    WAITKEY$

END FUNCTION

'---------------------------------------------------------------
Attached Files