🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.os.ms-windows.programmer.misc
18 messages
18 total messages Started by Alois Buecherl Mon, 03 Feb 1997 00:00
How to avoid multiple instances of a program in NT and 95?
#2923
Author: Alois Buecherl
Date: Mon, 03 Feb 1997 00:00
15 lines
1417 bytes
Hello,
I've been striving for so long now to find a SAVE way to start only one 
instance of my C++ program under Windows NT and 95. As you might recall, this 
used to be that easy in Windows 3.1 using the prevInstance variable. Now this 
option is gone.
I've tried using a semaphore that get's locked when the programm's up. But
it still can happen, that the program starts up more than once when multiple 
prgram spawns occur very rapidly. The program then did not get enough 
startup-time to create and lock the semaphore. 
Is there ANY solution to this problem?

Any hint into a possibly right direction would be greatly appreciated!

Alois
Re: How to avoid multiple instances of a program in NT and 95?
#2924
Author: Richard Baldwin
Date: Mon, 03 Feb 1997 00:00
100 lines
4300 bytes
In article <5d4eeb$n6u$1@euler.space.net>, Alois Buecherl
<Alois.Buecherl@terraSat.de> writes
>Hello,
>I've been striving for so long now to find a SAVE way to start only one 
>instance of my C++ program under Windows NT and 95. As you might recall, this 
>used to be that easy in Windows 3.1 using the prevInstance variable. Now this 
>option is gone.
>I've tried using a semaphore that get's locked when the programm's up. But
>it still can happen, that the program starts up more than once when multiple 
>prgram spawns occur very rapidly. The program then did not get enough 
>startup-time to create and lock the semaphore. 
>Is there ANY solution to this problem?
>
>Any hint into a possibly right direction would be greatly appreciated!
>
>Alois
This is how to do it. This method uses the application class name to
prevent multiple instances. If you want to change the name of your class
to something other than the app name, then replace all three items with
^^^^^^ under them to the same variable/literal. If you have problems
with this code then email me.



In CMainFrame
=============
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
        // TODO: Modify the Window class or styles here by modifying
        //  the CREATESTRUCT cs

        cs.lpszClass=AfxGetAppName();
                     ^^^^^^^^^^^^^^^
        return CFrameWnd::PreCreateWindow(cs);
}



In CYourApp
===========
static BOOL bReg = FALSE;

BOOL CYourApp::InitInstance()
{
        // Only allow one instance - if one already exists bring
        // it to the top and make it active.
        if (!CheckFirst()) return FALSE;

        // Register my class using my name
        WNDCLASS wndclass;
        memset(&wndclass,0,sizeof(WNDCLASS));
*****YOUR STYLES MAY REPLACE THOSE BELOW*******
        wndclass.style=CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc= ::DefWindowProc;
        wndclass.hInstance=AfxGetInstanceHandle();
        wndclass.hIcon=LoadIcon(IDR_MAINFRAME);
        wndclass.hCursor=LoadCursor(IDC_ARROW);
        wndclass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
        wndclass.lpszClassName=m_pszAppName;
                               ^^^^^^^^^^^^   
        if (!AfxRegisterClass(&wndclass)) return FALSE;
        
        // Set a flag to show we've done it
        bReg=TRUE;
        
******THE REST OF INITINSTANCE GOES HERE*********
}

int CYourApp::ExitInstance() 
{
        // If I registered my class, unregister it
        if (bReg) UnregisterClass(m_pszAppName,AfxGetInstanceHandle()); 
                                  ^^^^^^^^^^^^ 
        return CWinApp::ExitInstance();
}

// This function check's to see if there is another window of my 
// class. If there is, bring it and any children or popups to the top
// and activate it. Returns TRUE if this instance is the first.
BOOL CYourApp::CheckFirst() 
{
        CWnd* wndPrev;
        CWnd* wndChild;
        if (wndPrev=CWnd::FindWindow(m_pszAppName,NULL))
        {
                wndChild=wndPrev->GetLastActivePopup();
                if (wndPrev->IsIconic()) wndPrev-ShowWindow(SW_RESTORE);
                wndChild->SetForegroundWindow();
                return FALSE;
        }
        return TRUE;
}

Add to the header file for CYourApp
===================================
        BOOL CheckFirst();

-- 
Richard Baldwin
Re: How to avoid multiple instances of a program in NT and 95?
#2925
Author: Mickey Williams
Date: Mon, 03 Feb 1997 00:00
21 lines
1790 bytes
Alois Buecherl <Alois.Buecherl@terraSat.de> wrote in article <5d4eeb$n6u$1@euler.space.net>...
> Hello,
> I've been striving for so long now to find a SAVE way to start only one 
> instance of my C++ program under Windows NT and 95. As you might recall, this 
> used to be that easy in Windows 3.1 using the prevInstance variable. Now this 
> option is gone.
> I've tried using a semaphore that get's locked when the programm's up. But
> it still can happen, that the program starts up more than once when multiple 
> prgram spawns occur very rapidly. The program then did not get enough 
> startup-time to create and lock the semaphore. 
> Is there ANY solution to this problem?

Create a mutex when your program starts up.  GetLastError will return
ERROR_ALREADY_EXISTS if the mutex name is already created.

-- 
Mickey Williams
Co Author - Programming Windows NT Unleashed
Author - Essential Visual C++,
Develop a Professional Visual C++ Application in 21 Days
Re: How to avoid multiple instances of a program in NT and 95?
#2926
Author: Raymond Chen
Date: Tue, 04 Feb 1997 00:00
16 lines
1411 bytes
>BOOL CYourApp::CheckFirst() 
>{
>        CWnd* wndPrev;
>        CWnd* wndChild;
>        if (wndPrev=CWnd::FindWindow(m_pszAppName,NULL))
>        {

This still won't work if a second instance is started before the
first gets a chance to create its window.

Create a named event and check if you get ERROR_ALREADY_EXISTS
from GetLastError.
--
(My return address is intentionally invalid; delete ".---" to get my real address.
My responses are not to be considered official technical support or advice.)
Re: How to avoid multiple instances of a program in NT and 95?
#2927
Author: Richard Baldwin
Date: Tue, 04 Feb 1997 00:00
22 lines
1909 bytes
In article <01bc11ec$dfe21120$b8bfabc7@pongo>, Mickey Williams
<mickeyw@deltanet.com> writes
>Alois Buecherl <Alois.Buecherl@terraSat.de> wrote in article <5d4eeb$n6u$1@euler
>.space.net>...
>> Hello,
>> I've been striving for so long now to find a SAVE way to start only one 
>> instance of my C++ program under Windows NT and 95. As you might recall, this 
>> used to be that easy in Windows 3.1 using the prevInstance variable. Now this 
>> option is gone.
>> I've tried using a semaphore that get's locked when the programm's up. But
>> it still can happen, that the program starts up more than once when multiple 
>> prgram spawns occur very rapidly. The program then did not get enough 
>> startup-time to create and lock the semaphore. 
>> Is there ANY solution to this problem?
>
>Create a mutex when your program starts up.  GetLastError will return
>ERROR_ALREADY_EXISTS if the mutex name is already created.
>
Does this method work under Win32s?
-- 
Richard Baldwin
Re: How to avoid multiple instances of a program in NT and 95?
#2928
Author: Sean Kennedy
Date: Tue, 04 Feb 1997 00:00
9 lines
1094 bytes
On Mon, 03 Feb 97 10:24:56 GMT, Alois.Buecherl@terraSat.de (Alois
Buecherl) wrote:

A terrible hack could be upon startup immediately create a file in the
%TEMP% directory.  If the create function returns a 'File exists'
return, otherwise, continue.  

-Sean Kennedy
Re: How to avoid multiple instances of a program in NT and 95?
#2929
Author: Heiner Eichmann
Date: Wed, 05 Feb 1997 00:00
29 lines
1647 bytes
raymondc@microsoft.com.--- (Raymond Chen) wrote:


>This still won't work if a second instance is started before the
>first gets a chance to create its window.

>Create a named event and check if you get ERROR_ALREADY_EXISTS
>from GetLastError.

Hi!

What happens if the program crashes before it can release the event?
It is improbably also possible that a different program uses the same 
name for an event.

What about this:

Open your own EXE file for read access and do not allow other
tasks to open the file. If this fails someone als has a lock on
this file and another instance is still running.

Yours


Heiner Eichmann
Inst. of Quantum Optics
University of Hanover, Germany
h.eichmann@mbox.iqo.uni-hannover.de
Re: How to avoid multiple instances of a program in NT and 95?
#2930
Author: Seth Allen
Date: Wed, 05 Feb 1997 00:00
12 lines
1514 bytes
Sean Kennedy wrote:
> A terrible hack could be upon startup immediately create a file in the
> %TEMP% directory.  If the create function returns a 'File exists'
> return, otherwise, continue.

This may be more terrible than you imagined. Do you intend that the
program delete the file when it exits? What happens if the program
crashes and the file is never deleted? In that case it would seem that
the program could never be run again, unless the person running it was
sophisticated enough to know to delete the file, and with most users
that will never happen.
Re: How to avoid multiple instances of a program in NT and 95?
#2931
Author: Amol Deshpande
Date: Wed, 05 Feb 1997 00:00
20 lines
1495 bytes
In article <32f6d5ca.86355796@news.ecs.fullerton.edu>, 
skennedy@ecs.fullerton.edu says...
>
>On Mon, 03 Feb 97 10:24:56 GMT, Alois.Buecherl@terraSat.de (Alois
>Buecherl) wrote:
>
>A terrible hack could be upon startup immediately create a file in the
>%TEMP% directory.  If the create function returns a 'File exists'
>return, otherwise, continue.  
>
>-Sean Kennedy

you might be better of creating a named mutex that the program tries to 
accquire on startup.

-amol
-- 
The opinions expressed in this message are my own personal views 
and do not reflect the official views of Microsoft Corporation.
Re: How to avoid multiple instances of a program in NT and 95?
#2932
Author: Amol Deshpande
Date: Wed, 05 Feb 1997 00:00
44 lines
2133 bytes
In article <5da29d$bs$2@newsserver.rrzn.uni-hannover.de>, 
h.eichmann@mbox.iqo.uni-hannover.de says...
>
>raymondc@microsoft.com.--- (Raymond Chen) wrote:
>
>
>>This still won't work if a second instance is started before the
>>first gets a chance to create its window.
>
>>Create a named event and check if you get ERROR_ALREADY_EXISTS
>>from GetLastError.
>
>Hi!
>
>What happens if the program crashes before it can release the event?
>It is improbably also possible that a different program uses the same 
>name for an event.

If the program crashes (terminates), the event is released.

>
>What about this:
>
>Open your own EXE file for read access and do not allow other
>tasks to open the file. If this fails someone als has a lock on
>this file and another instance is still running.
>
>Yours
>
>
>Heiner Eichmann
>Inst. of Quantum Optics
>University of Hanover, Germany
>h.eichmann@mbox.iqo.uni-hannover.de
>

But then I could always copy the .exe to a different name and run another
instance. 

-amol
-- 
The opinions expressed in this message are my own personal views 
and do not reflect the official views of Microsoft Corporation.
Re: How to avoid multiple instances of a program in NT and 95?
#2933
Author: Chris Becke
Date: Wed, 05 Feb 1997 00:00
20 lines
1438 bytes

Sean Kennedy <skennedy@ecs.fullerton.edu> wrote in article
<32f6d5ca.86355796@news.ecs.fullerton.edu>...
> On Mon, 03 Feb 97 10:24:56 GMT, Alois.Buecherl@terraSat.de (Alois
> Buecherl) wrote:
> 
> A terrible hack could be upon startup immediately create a file in the
> %TEMP% directory.  If the create function returns a 'File exists'
> return, otherwise, continue.  

Or worse, make a small initialized data section, mark it as "Shared", and
put a refrence counter in it =0;

First app increment to 1; and instance check counter and abort if >= 1

Chris.
-- 
chris@dbn.lia.net
<http://www.dbn.lia.net/users/chris>
Re: How to avoid multiple instances of a program in NT and 95?
#2934
Author: Doug Stevens
Date: Wed, 05 Feb 1997 00:00
13 lines
1541 bytes
> raymondc@microsoft.com.--- (Raymond Chen) wrote:
> >Create a named event and check if you get ERROR_ALREADY_EXISTS
> >from GetLastError.

Heiner Eichmann wrote:
> What happens if the program crashes before it can release the event?
> It is improbably also possible that a different program uses the same
> name for an event.

If the program crashes, any handles that it holds become abandoned.
If you wait on them, the OS returns a WAIT_ABANDONED value, and
if you try to create them, it will let you.
Re: How to avoid multiple instances of a program in NT and 95?
#2935
Author: Pete MacLiesh
Date: Thu, 06 Feb 1997 00:00
56 lines
2623 bytes

The following appears to work - it also restricts to a single instance
system-wide
on machines running citrix derived systems like WinDD.

Return is true if it succeeded in creating the mutex, FALSE if failed
because it's
already running

PMac

--

BOOL	CheckandCreateMutex(const char * mutexName)
{
	BOOL	ret = FALSE;

	// The nastiness here is because of multi-user NT derivatives ala Citrix.
	// To make a global resource on these, \SYSTEM must be appended -- but
this
	// fails on vanilla NT, so I try both (\SYSTEM first) ... because I cannot
	// determine portably if the system is multi-user !!!
	HANDLE hMutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, mutexName);
	HANDLE hMutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, CString(mutexName) +
"\\SYSTEM");
	if (hMutex1 == NULL && hMutex2 == NULL)
	{
		HANDLE hMutex = CreateMutex(0, TRUE, CString(mutexName) + "\\SYSTEM");
		if (hMutex == NULL)
			hMutex = CreateMutex(0, TRUE, mutexName);

		DWORD err = GetLastError();
		ret = !(hMutex == NULL || err == ERROR_ALREADY_EXISTS);
		ASSERT(ret);
	}
	else
	{
		if (hMutex1)
			CloseHandle(hMutex1);
		if (hMutex2)
			CloseHandle(hMutex2);
	}

	return ret;
}


-- 
________________________________________________________________
All Opinions are my own ... not necessarily those of my employer
________________________________________________________________
Peter MacLiesh                *      Email:  pmac@synopsys.com
Synopsys Inc.                 *      Phone:  (415)694-4423
700A E. Middlefield Rd.       *      Fax:    (415)694-1626
Mountain View, CA 94043       *
Re: How to avoid multiple instances of a program in NT and 95?
#2936
Author: Raymond Chen
Date: Thu, 06 Feb 1997 00:00
18 lines
1619 bytes
On Wed, 05 Feb 1997 13:38:05 GMT,
h.eichmann@mbox.iqo.uni-hannover.de (Heiner Eichmann) wrote:
>What happens if the program crashes before it can release the event?

Windows automatically closes unclosed HANDLE objects when the
application exits (either normally or abnormally).

>It is improbably also possible that a different program uses the same 
>name for an event.

If you use a GUID, then you can be pretty sure that no other
program is using the same name.


--
(My return address is intentionally invalid; delete ".---" to get my real address.
My responses are not to be considered official technical support or advice.)
Re: How to avoid multiple instances of a program in NT and 95?
#2937
Author: Mario Schlesinger
Date: Thu, 06 Feb 1997 00:00
32 lines
1862 bytes
Someday (Mon, 03 Feb 97 10:24:56 GMT) someone
(Alois.Buecherl@terraSat.de (Alois Buecherl)) wrote:

>I've been striving for so long now to find a SAVE way to start only one 
>instance of my C++ program under Windows NT and 95. As you might recall, this 
>used to be that easy in Windows 3.1 using the prevInstance variable. Now this 
>option is gone.

Most of the time, I'm just going the easy way:

hWnd = FindWindow( szNameOfMyMainWindowClass, NULL );
if ( hWnd )  {
	BringWindowToTop( hWnd );
	SetForegroundWindow( hWnd );
	};



see 'ya
	/\/\ario


* FIDO:  2:2480/141.15 *
* EMail: schlesinger@augsburg.baynet.de *
* Homepage: http://www.schlesi-edv.com *

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   Da ertoente eine Stimme und sagte: "Laechle und sei froh,
   es koennte schlimmer kommen!"
   Und ich laechelte und war froh - und es kam schlimmer.
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Re: How to avoid multiple instances of a program in NT and 95?
#2938
Author: Slawomir Marczynski
Date: Fri, 07 Feb 1997 00:00
17 lines
1603 bytes
Richard Baldwin (richard@ormesci.demon.co.uk) wrote:
: >I've been striving for so long now to find a SAVE way to start only one 
: >instance of my C++ program under Windows NT and 95. As you might recall, this 

: In CMainFrame
: =============
: BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

There is also an example (I've forgotten this name) on BC5.01 CDROM
with OWL instead MFC.

--
Slawomir Marczynski (Mr) 
Institute of Physics, Technical University of Szczecin
Al. Piastow 48/49, 70-310 Szczecin, Poland
slawek@arcadia.inter.tuniv.szczecin.pl, tel:+(048-91)-494056 
Re: How to avoid multiple instances of a program in NT and 95?
#2939
Author: Don Lance
Date: Sat, 08 Feb 1997 00:00
45 lines
2892 bytes
Alois.Buecherl@terraSat.de (Alois Buecherl) wrote:

>Hello,
>I've been striving for so long now to find a SAVE way to start only one 
>instance of my C++ program under Windows NT and 95. As you might recall, this 
>used to be that easy in Windows 3.1 using the prevInstance variable. Now this 
>option is gone.
>I've tried using a semaphore that get's locked when the programm's up. But
>it still can happen, that the program starts up more than once when multiple 
>prgram spawns occur very rapidly. The program then did not get enough 
>startup-time to create and lock the semaphore. 
>Is there ANY solution to this problem?
>
>Any hint into a possibly right direction would be greatly appreciated!
>
>Alois


Here's what I did to solve the problem for one of my apps; it worked
really well.

As someone suggested, create a mutex kernel object that's exclusive for the
app.  When your app starts up, the first thing you should do is look to 
see if it's present.  It is there, then you know you have an instance 
already running.  If it's not, then it's the first instance and proceed
with startup.  

You can enhance your program a little more by switching focus and 
bringing your app to the foreground when someone attempts to start a
second instance.  To handle this, have the app create a "wait" thread to
wait for a created event object to become signalled.  When the event
becomes signalled, the wait thread maximizes its main window, switches
its focus to the foreground, then waits once more.  Note that you should
check your pointer to the apps main window frame, as it could possibly
be NULL during a set of "rapid-fire" clicks from the user.  Since a
thread wait has almost no overhead, you're not chewing up processor time
with it.

Now your app should check for the existance of the mutex, and if present,
signal the previous app's event.  The other app will come to front, while
your new app exits.  You might can optimize this technique a little more 
by using a single kernel object instead of two.

Good luck.
Re: How to avoid multiple instances of a program in NT and 95?
#2940
Author: Horst Schmid
Date: Sun, 09 Feb 1997 00:00
98 lines
4427 bytes
Slawomir Marczynski wrote:
> 
> Richard Baldwin (richard@ormesci.demon.co.uk) wrote:
> : >I've been striving for so long now to find a SAVE way to start only one
> : >instance of my C++ program under Windows NT and 95. As you might recall, this
> 
> : In CMainFrame
> : =============
> : BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
> 
> There is also an example (I've forgotten this name) on BC5.01 CDROM
> with OWL instead MFC.
> 
> --
> Slawomir Marczynski (Mr)
> Institute of Physics, Technical University of Szczecin
> Al. Piastow 48/49, 70-310 Szczecin, Poland
> slawek@arcadia.inter.tuniv.szczecin.pl, tel:+(048-91)-494056

For Delphi programmers I have a solution that ask user in case of starting the 2nd time to switch 
to the first or to cancel:

Horst Schmid, http://ourworld.compuserve.com/homepages/Horst_Schmid


unit once; {Ask User to switch to the first Instance instead of starting a second}
{Simply add this Unit to your uses-Statement of your Delphi2.0-Project.dpr
 to prevent starting Your App. more than once!}

interface
const Titel:pchar='Warning'; {You can change this to whatever you want}
      Msg:String='App. %s is already running, switch to it?';
implementation
uses windows,sysutils,tlhelp32;

procedure SwitchToThisWindow(h1:hWnd; x:bool);stdCall; external user32 name 'SwitchToThisWindow';
{x=false: Size unchanged, x=true: normal size}

function EnumThreadWndProc(h1:hWnd;LPARAM:lParam):bool;stdCall;  {Callback}
var hp:word;
begin
  if IsWindowVisible(h1) then begin
    hp:=GetLastActivePopup(h1);
    if IsWindow(hp) then begin
      SwitchToThisWindow(hp,true);
      end end;
  EnumThreadWndProc:=true;
end;

var mHandle: THandle;    // Mutexhandle
    s:string;
    i:integer;
    b:bool;
    h,h2:tHandle;
    lppe: TProcessEntry32;
    lpte: TThreadEntry32;
    pid0,tid:dWord;
    x:array[0..255]of char;

Initialization     {called when App is started}
  s:=ParamStr(0);   {Progname as MutexName}
  i:=length(s);
  while (i>0) and (s[i]<>'\') do dec(i); {without Path}
  mHandle := CreateMutex(nil,True,pchar(copy(s,i+1,255)));
  if GetLastError = ERROR_ALREADY_EXISTS then begin   // App is running
    i:=MessageBox(0,pchar(Format(Msg,[copy(s,i+1,255)]))
     ,Titel,MB_ICONQUESTION+MB_OKCANCEL);
    if i=IDOK then begin   {find the other Task and bring to top}
      tid:=0;
      h:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
      lppe.dwSize:=SizeOf(lppe);
      b:=Process32First(h,lppe);
      pid0:=GetCurrentProcess;
      s:=s+#0; {make String to ASCIIZ}
      while b do begin {Proccess-Loop}
        if (StrComp(@s[1],lppe.szExeFile)=0)and(lppe.th32ProcessID<>pid0) then begin
          h2:=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
          lpte.dwSize:=SizeOf(lpte);
          b:=Thread32First(h2,lpte);
          tid:=0;
          while b do begin {Thread-Loop}
            if lpte.th32OwnerProcessID=lppe.th32ProcessID then begin
              tid:=lpte.th32ThreadID;
              EnumThreadWindows(tid,@EnumThreadWndProc,0) end;
            b:=Thread32Next(h2,lpte) end;
          end
        else b:=Process32Next(h,lppe) end;
      CloseHandle(h2);
      CloseHandle(h);
      end;
    halt;{Cancel second start. Delete this line if the the second Choice
     should be to start a second App.}
  end;

finalization {End of App:Delete Mutex}
  if mHandle <> 0 then CloseHandle(mHandle)
end.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads