LOCAL llQuit *!* Check for instance(s) of your application being loaded, using SYS(16) to determine application name and path oManager = GETOBJECT([winmgmts:]) cQuery = [select * from win32_process where name='] ; + LOWER(JUSTSTEM(SYS(16,0))) ; + [.exe'] oResult = oManager.ExecQuery(cQuery)
IF oResult.Count > 1 *!* At this point you can choose to abort loading your application should another instance of your application be loaded under the same executable name but from some other or this location. Put simply, any executable with the same name as the one currently loaded.
If so, remove the rest of the code within this IF ...ENDIF statement and replace it with 'llQuit = .T.'
Should you wish to prevent your application from being loaded only from this location, but allow other applications with the same name to be loaded from other locations, then leave the following code as is.
What the following code does is to compare both executable name and path/executable name, as opposed to executable name only in the simpler version.
Should you wish to prevent a user from running your application under a different executable name, check if the user has renamed the executable by comparing a hard coded name, such as 'myapp.exe', (your original executable name), with LOWER(JUSTFNAME(SYS(16))) in your main.prg.
If they are not the same, advise the user to rename the executable to its original name through a MESSAGEBOX(), before aborting the application. FOR EACH objEvent IN oResult FOR EACH oProp In objEvent.Properties_ IF oProp.Name = [CommandLine] ; AND LOWER(CHRTRAN(oProp.Value,["],)); = LOWER(CHRTRAN(SYS(16),["],)) llQuit = .T. EXIT ENDI ENDFOR IF llQuit EXIT ENDI ENDFOR ENDIF *!* Clean up oManager = .NULL. oResult = .NULL. RELEASE cQuery, oResult, oManager
IF llQuit && Myapp.exe loaded twice QUIT ENDI
If you have synchronous or asynchronous threads in a VFP app and want prevent a thread from being launched if the parent app is not running, then you can extend the first example code as follows.
LOCAL llQuit *!* Check for parentapp.exe being loaded, not using SYS(16) to determine name of application. If you want to check the path as well as the filename, use a modified version of the code posted in the first example oManager = GETOBJECT([winmgmts:]) oApps = oManager.InstancesOf([win32_process])
llQuit = .T. FOR EACH PROCESS IN oApps IF [parentapp.exe] = LOWER(PROCESS.Name) llQuit = .F. EXIT ENDIF NEXT
IF !llQuit cQuery = [select * from win32_process where name='childapp.exe'] oResult = oManager.ExecQuery(cQuery) IF oResult.Count > 1 llQuit = .T. oResult = .NULL. ENDI ENDI
*!* Clean up oApps = .NULL. oManager = .NULL.
RELEASE cQuery, oApps, oResult, oManager
IF llQuit && parentapp.exe not being loaded or childapp.exe being loaded twice QUIT ENDI
It also prevents curious users, bless 'em , from attempting to run childapp.exe from Windows.
This does assume that the Windows Management Instrumentation Service has not been stopped or disabled.
You should error trap the example code if you consider that is a real possibility, and use an alternative method.