# ...running only one 'instance' of a program.

These two little demo's illustrate how one can write a program so that only one copy can be running at the same time. If one tries to start a second copy, it will detect the presence of the first, and shut down.

This feature has been added by using the same FindWindowA() function we used in the previous examples.

Since the first example is so short, I've added two lines at the beginning of the check_self() procedure, which insert the default Euphoria icon into this program's title bar.

-- kick-it3.exw

    -- start demo --
    include win32lib.ew

    atom ptr,  ptr2,  ok,  proghwnd

    constant

        -- new functions !
        zFindWindow = registerw32Function( user32,  "FindWindowA",  {C_POINTER, C_INT}, C_INT ),
        -- ok,  the above func is now in win32lib !
        zBeep = registerw32Function( user32,  "MessageBeep",  {C_INT}, C_INT )

        ptr = allocate_string( "Win32Lib AppWindow 1" ) -- classname
        ptr2 = allocate_string( "kick_self" ) -- title
        -- first,  try and find a window using:
        -- classname and title,  as in above strings.
        proghwnd = w32Func(  zFindWindow,  { ptr,  ptr2 }  )

    constant
        Win = create(  Window,  "kick_self",  0,  Default,  Default,  300,  100,  0  )

    procedure check_self(  integer self,  integer event,  sequence params  )

        -- get the default Euphoria icon from exw.exe,
        ok = w32Func(  xLoadIcon,  { instance(  ),  allocate_string( "exw" ) }  )
        -- and insert it in this program's title bar.
        ok = sendMessage(  Win,  128,  0,  ok  )
        if proghwnd != 0 then
            ok = w32Func(  zBeep,  { 0 }  )
            -- just to test,  lets see/report this instance for 3 seconds...
            setVisible( Win, 1 )
            setFont( Win, "System", 10, 1 )
            setPenPos( Win, 1, 1 )
            wPuts( Win, "...another instance found, so good-bye." )
            sleep( 3 )
            -- set focus to first instance
            ok = w32Func(  xSetForegroundWindow, {proghwnd} )
            --  closeWindow( Win )  -- no longer works here !!!???
            abort( 0 )  -- I'd rather closeWindow() than abort,
            -- but only this works now.
        end if

    end procedure
    setHandler(  Win,  w32HOpen,  routine_id( "check_self" )  )

    WinMain( Win, Normal )
    -- end demo --

The second example uses the CreateSemaphore() function to do essentially the same thing... detect if an instance of this program is already running. Since semaphores are actually used as simple objects to communicate between different applications, the CreateSemaphore() function will return an error message if the same semaphore already exists.

This error message can be retrieved by the GetLastError() function, so we'll know our previous instance has already created the semaphore, and shut down the second instance of our program.

-- kick-it4.exw

    -- start demo --
    include win32lib.ew

    atom ptr, ptr2, ok, proghwnd

    constant
        -- new functions !
        zCreateSemaphore = registerw32Function( kernel32, "CreateSemaphoreA", {C_POINTER, C_INT, C_INT, C_POINTER}, C_INT ),
        zGetLastError = registerw32Function( kernel32, "GetLastError", {}, C_INT ),
        zBeep = registerw32Function( user32, "MessageBeep", {C_INT}, C_INT ),
        zERROR_ALREADY_EXISTS = 183

        ptr = allocate_string( "Win32Lib AppWindow 1" ) -- classname
        ptr2 = allocate_string( "..using a semaphore" ) -- title
        -- first, try and find a window using:
        -- classname and title, as in above strings,
        -- *before* we create THIS window.
        proghwnd = w32Func( xFindWindow, { ptr, ptr2 } )

    constant
    Win = create( Window, "..using a semaphore", 0, Default, Default, 300, 100, 0 )

    procedure check_self( integer self, integer event, sequence params )

        -- create a semaphore for this instance, using pointer to classname
        ok = w32Func( zCreateSemaphore, {NULL, 0, 1, ptr} )
        ok = w32Func( zGetLastError, {} )
        if ok = zERROR_ALREADY_EXISTS then
            ok = w32Func( zBeep, { 0 } )
            setText( Win, "..semaphore found !" )
            -- just to test, lets see/report this instance for 3 seconds...
            setVisible( Win, 1 )
            setFont( Win, "System", 10, 1 )
            setPenPos( Win, 1, 1 )
            wPuts( Win, "...another instance found, so good-bye." )
            sleep( 3 )
            -- set focus to first instance
            ok = w32Func( xSetForegroundWindow, {proghwnd} )

            abort( 0 ) -- and quit.

        end if

    end procedure
    setHandler( Win, w32HOpen, routine_id( "check_self" ) )
    ------------------------------------------------------

    WinMain( Win, Normal )
    -- end second demo --

...end...

CONTENTS