* test for mutex #DEFINE ERROR_ALREADY_EXISTS 183 private oMutex _SCREEN.Visible = .F. _SCREEN.Caption = "" oMutex = CREATEOBJECT('Mutex', u_AppName) IF oMutex.nMutexErr # ERROR_ALREADY_EXISTS * The instance doesn't exist _SCREEN.Visible = .T. _SCREEN.Caption = u_AppName ELSE * Mutex exists so display the original instance before terminating. oMutex.DisplayInstance() return && say goodbye, cause cleanup, object falls out of scope, destroy ENDIF.
************************************************************ DEFINE CLASS Mutex AS CUSTOM ************************************************************ cformcaption = "" hmutex = 0 nmutexerr = 0 PROCEDURE INIT LPARAMETER pcformcaption DECLARE INTEGER CreateMutex IN Win32API ; STRING @lpMutexAttributes, STRING bInitialOwner, STRING @lpName DECLARE INTEGER GetLastError IN Win32API LOCAL lcinitowner, lcname, lcformcaption * So that the Mutex name is different from the caption. lcformcaption = pcformcaption lcname = CHRTRAN(pcformcaption, SPACE(1), "") * Simulate a BOOL type equaling TRUE. lcinitowner = CHR(1) WITH THIS .cformcaption = lcformcaption .hmutex = createmutex(0, lcinitowner, @lcname) .nmutexerr = getlasterror() ENDWITH RETURN ENDPROC PROCEDURE displayinstance #DEFINE SW_SHOWNORMAL 1 #DEFINE SW_SHOW 5 DECLARE INTEGER FindWindow IN Win32API ; STRING @lpClassName, STRING @lpWindowName DECLARE SHORT IsIconic IN Win32API INTEGER HWND DECLARE LONG ShowWindow IN Win32API LONG HWND, LONG nCmdShow DECLARE SHORT BringWindowToTop IN Win32API INTEGER HWND LOCAL lcformcaption, lnhwnd, llicon lcformcaption = THIS.cformcaption lnhwnd = findwindow(0, @lcformcaption) IF NOT EMPTY(lnhwnd) * Determine if application is minimized IF isiconic(lnhwnd) # 0 = SHOWWINDOW(lnhwnd, SW_SHOWNORMAL ) ENDIF = bringwindowtotop(lnhwnd) ELSE * This handles applications with dynamic title text bars. = MESSAGEBOX("Application "+lcformcaption+" is already running.", ; 64, "Only One Instance Allowed") ENDIF ENDPROC PROCEDURE DESTROY DECLARE INTEGER WaitForSingleObject IN Win32API ; INTEGER hObject, INTEGER dwTimeOut DECLARE SHORT ReleaseMutex IN Win32API INTEGER hMutex DECLARE SHORT CloseHandle IN Win32API INTEGER hObject LOCAL lnresult IF THIS.hmutex # 0 lnresult = waitforsingleobject(THIS.hmutex, 50) * 258 = STATUS_TIMEOUT IF lnresult # 258 lnresult = releasemutex(THIS.hmutex) * 1 equals Boolean TRUE IF lnresult = 1 lnresult = closehandle(THIS.hmutex) ENDIF ENDIF ENDIF CLEAR DLLS ENDPROC ENDDEFINE