Articles   Members Online: 3
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to handle previous instances of an application Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
08-Jan-03
Category
Others
Language
Delphi 2.x
Views
71
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			Author: Lou Adler

I was surprised to find that I didn't have an article covering this topic - I wrote 
a couple of 'em for inquiry.com a couple of years ago. Oh well... they're in 
another place and time... In any case, what I'll give you here are two techniques 
for handling previous instances of your applications.

Answer:

Oh! Were that only the phrase I used when I was single! Alas, like most, it 
unfortunately wasn't. But at least I could apply that phrase in my professional 
life; of course, in a totally different way. Okay, enough of the play on words.

There are many applications that lend themselves to having more than one copy 
running at any time. But in my experience, most of the applications I build only 
lend themselves to a single instance. For instance, it isn't practical to run more 
than one instance of a data-entry application; especially when it updates local 
data. In cases such as this, I limit the execution of another instance of a program 
by executing some simple code.

What I'm going to show you is two different functions that do exactly the same 
thing. The only difference between the two is that the first function can only be 
run in Win32, and the other function can run in either Win16 or Win32. Here's the 
code:
1   
2   // ===================================================
3   // Called by your project file, prevents a 2nd
4   // instance of the program from executing and
5   // instead activates the already executing instance.
6   // Returns TRUE if a previous instance of the
7   // program is already running. Win32 ONLY
8   // ===================================================
9   
10  function IsPrevInst: Boolean;
11  var
12    semName,
13      appClass: PChar;
14    hSem: THandle;
15    hWndMe: HWnd;
16    appTitle: array[0..MAX_PATH] of Char;
17  begin
18    // Init
19    Result := FALSE;
20    GetMem(semName, 15);
21    GetMem(appClass, 15);
22    StrPCopy(semName, 'SemaphoreName');
23    StrPCopy(appClass, 'TApplication');
24    StrPCopy(appTitle, ExtractFileName(Application.Title));
25  
26    // Create a Semaphore in memory.  If this is the
27    // first instance, then hSem's value should be 0.
28    hSem := CreateSemaphore(nil, 0, 1, semName);
29  
30    // Check to see if the semaphore exists
31    if (hSem <> 0) and (GetLastError() =
32      ERROR_ALREADY_EXISTS) then
33    begin
34      CloseHandle(hSem);
35  
36      // Get the current window's handle then change
37      // its title so we can look for the other instance
38      hWndMe := FindWindow(appClass, appTitle);
39      SetWindowText(hWndMe, 'ZZZZZZZ');
40  
41      // Search for other instance of this window then bring
42      // it to the top of the Z-order stack.  We find it by
43      // matching the Application Class and
44      // Application Title.
45      hWndMe := FindWindow(appClass, appTitle);
46      if (hWndMe <> 0) then
47      begin
48        BringWindowToTop(hWndMe);
49        ShowWindow(hWndMe, SW_SHOWNORMAL);
50      end;
51  
52      Result := TRUE;
53    end;
54  
55    // Destroy PChars
56    FreeMem(semName, 15);
57    FreeMem(appClass, 15);
58  end;
59  
60  //This is a different twist on the previous example.
61  //It uses a mutex (MUTually EXclusive) instead of a sema-
62  //phore.
63  
64  procedure CheckPrevInstEx(MainFormClassName,
65    MainFormCaption: string);
66  var
67    PrevWnd: HWnd;
68    Mutex: THandle;
69  begin
70  {$IFDEF Win32}
71    Mutex := CreateMutex(nil, False, 'InstanceMutex');
72    if WaitForSingleObject(Mutex, 10000) = WAIT_TIMEOUT then
73      Application.Terminate;
74  {$ELSE}
75    if HPrevInst = 0 then
76      Application.Terminate;
77  {$ENDIF}
78  
79    PrevWnd := FindWindow(PChar(MainFormClassName),
80      PChar(MainFormCaption));
81    if PrevWnd <> 0 then
82      PrevWnd := GetWindow(PrevWnd, GW_OWNER);
83    if PrevWnd <> 0 then
84    begin
85      if IsIconic(PrevWnd) then
86        ShowWindow(PrevWnd, SW_SHOWNORMAL)
87      else
88  {$IFDEF Win32}
89        SetForegroundWindow(PrevWnd);
90  {$ELSE}
91        BringWindowToTop(PrevWnd);
92  {$ENDIF}
93      Application.Terminate;
94    end;
95    ReleaseMutex(Mutex);
96    CloseHandle(Mutex);
97  end;
98  
99  {To use the functions above, you can either embed them in the project file, or 
100 better yet, place them in a globally accessible library for use in all your 
101 applications that need them. Here's some example code for implementing them:}
102 
103 //This example uses the IsPrevInst function
104 program RxProto;
105 
106 uses
107   Forms,
108   Main in 'Main.pas' {MainForm},
109   Proc in 'Proc.pas',
110   //This is my global library
111   UTIL32 in '..\Lib\UTIL\Util32.pas',
112   LoopPnThr in '..\Packages\LoopPnThr.pas';
113 
114 {$R *.RES}
115 
116 begin
117   if not IsPrevInst then
118   begin
119     Application.Initialize;
120     Application.CreateForm(TMainForm, MainForm);
121     Application.Run;
122   end
123   else
124     Application.Terminate;
125 end.
126 //Here's the other way...
127 program RxProto;
128 
129 uses
130   Forms,
131   Main in 'Main.pas' {MainForm},
132   Proc in 'Proc.pas',
133   UTIL32 in '..\Lib\UTIL\Util32.pas',
134   LoopPnThr in '..\Packages\LoopPnThr.pas';
135 
136 {$R *.RES}
137 
138 begin
139   CheckPrevInstEx('TApplication', 'My Application');
140   //This code won't do anything if CheckPrevInstEx doesn't
141   //pass muster
142   Application.Initialize;
143   Application.CreateForm(TMainForm, MainForm);
144   Application.Run;
145 end.


As you can see, pretty simple stuff. Have fun with it!

			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC