Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

System-wide flags using Windows Events

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • System-wide flags using Windows Events

    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
    Gert Voland
Working...
X