485
edits
(Updated "createmutex succeeded" test to test for NULL not ERROR_INVALID_HANDLE as per Frank Cheng's recommendation see https://support.dataaccess.com/Forums/showthread.php?67791-Limiting-Dataflex-Instances-to-1-per-Laptop&p=368346#post368346) |
|||
(14 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
The question on how to make sure that your application is only started once by your users can be approached in several ways. | The question on how to make sure that your application is only started once by your users can be approached in several ways. | ||
# Using mutexes | |||
# Using FindWindow WinAPI | |||
# Using Atoms | |||
=== Using mutexes === | === Using mutexes === | ||
Line 10: | Line 11: | ||
Here is the code if you want to go that route." | Here is the code if you want to go that route." | ||
In the SRC file: | In the SRC file within the panel object put this piece of code: | ||
<source lang="dataflex"> | |||
Procedure Exit_Application | |||
integer iVoid | |||
If (ghMuteX) Move (CloseHandle(ghMutex)) to iVoid | |||
move 0 to ghMuteX | |||
Forward Send Exit_Application | |||
End_Procedure | |||
</source> | |||
And in a package that gets hit on startup: | |||
<source lang="dataflex"> | |||
// Constants | |||
Define ERROR_INVALID_HANDLE for 6 // taken from error.h of VS7 | |||
Define ERROR_ALREADY_EXISTS for 183 | |||
Handle ghMuteX | |||
// external functions | |||
#IFNDEF Get_CreateMuteX | |||
External_Function CreateMuteX "CreateMutexA" Kernel32.dll Integer i1 Integer i2 Integer i3 Returns Integer | |||
#ENDIF | |||
#IFNDEF Get_CloseHandle | |||
External_Function CloseHandle "CloseHandle" Kernel32.dll Integer i1 Returns Integer | |||
#ENDIF | |||
// function to create a mutex | |||
Procedure Create_MuteX_Object | |||
Integer iVoid iErr | |||
String sID | |||
Move "Unique String For My Application" To sID | |||
Move (CreateMuteX(0,1,AddressOf(sID))) To ghMuteX | |||
If (ghMuteX <> 0) Begin | |||
Move (GetLastError()) To iErr | |||
If (iErr = ERROR_ALREADY_EXISTS) Begin // program is already | |||
// running | |||
Move (CloseHandle(ghMuteX)) To iVoid | |||
Move 0 To ghMuteX | |||
// kill the application here if you do not want to allow | |||
// multiple instances | |||
ABORT | |||
End | |||
Else Send None // program is not already running | |||
End | |||
Else Send None // rare error; object could not be created | |||
End_Procedure // Create_MuteX_Object | |||
// create the mutex | |||
Send Create_MuteX_Object | |||
</source> | |||
Dave Robinson says - | |||
A warning: We found CodeJock skinning broke this, though YMMV. | |||
=== Using FindWindow WinAPI === | === Using FindWindow WinAPI === | ||
Line 56: | Line 70: | ||
Usage in SRC: | Usage in SRC: | ||
<source lang="dataflex"> | |||
Use myPanel,pkg | Use myPanel,pkg | ||
Object Main is a myPanel | Object Main is a myPanel | ||
</source> | |||
Source myPanel.pkg | Source myPanel.pkg | ||
<source lang="dataflex"> | |||
//////////////////////////////////////////// | //////////////////////////////////////////// | ||
// | // | ||
Line 73: | Line 88: | ||
Class myPanel is a Panel | Class myPanel is a Panel | ||
// DoCheckProgramActive | |||
// Checks if the program already is active. | |||
// If so, it activates the running application and closes this one. | |||
Procedure DoCheckProgramActive | |||
String sTitle | |||
Handle hWnd | |||
Integer iVoid | |||
Register_Object Main | |||
Get Label of Main to sTitle | |||
Move (FindWindow("",sTitle)) to hWnd | |||
If (hWnd) Begin | |||
Send Stop_Box (sTitle + " Already is Running and Can only be Started Once.") "Error:" | |||
Move (ShowWindow(hWnd,SW_MAXIMIZE)) to iVoid // 9 =SW_RESTORE SW_NORMAL | |||
Move (SetForegroundWindow(hWnd)) to iVoid | |||
Abort | |||
End | |||
End_Procedure // DoCheckProgramActive | |||
// End_Construct_Object | |||
Procedure End_Construct_Object | |||
Send DoCheckProgramActive | |||
Forward Send End_Construct_Object | |||
End_Procedure // End_Construct_Object | |||
End_class | |||
</source> | |||
The FindWindow technique is also discussed in the book [http://starzen.com/products/books-and-magazines/mastering-visual-dataflex/ Mastering Visual DataFlex] from Starzen. | |||
Dave Robinson says: | |||
The FindWindow method depends on the Title in the program taskbar being known and consistent. | |||
[[Category: Tutorials]] |