Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do I ensure only one version of my executable is running

14 views
Skip to first unread message

Morris Neuman

unread,
Mar 4, 2007, 11:13:00 PM3/4/07
to
I have a VS 6.0 C++ executable that registers and runs as a service of the
operating system (Win 2000, Win XP Pro, WIndows 2003). What is the best
practice to ensuring only one instance of the excutable is running? The
executable will launch additional processes if someone double clicks the .EXE
file.

I also have a monitoring app also VS 6.0 C++ that displays the status of the
service. This app is not a service but I also want to allow only 1 version of
this program to run. This app will also start the service if it is stopped.

--
Thanks
Morris

Check Abdoul

unread,
Mar 4, 2007, 11:26:37 PM3/4/07
to
See if the following link helps you

http://bobmoore.mvps.org/Win32/w32tip7.htm

Cheers
Check Abdoul
---------------------

"Morris Neuman" <Mor...@online.nospam> wrote in message
news:28CAC759-24FD-46C7...@microsoft.com...

Tom Serface

unread,
Mar 5, 2007, 12:03:45 AM3/5/07
to
I use this class and it works pretty well for me. I haven't tried it for a
service, but...

http://www.naughter.com/sinstance.html

Tom

"Morris Neuman" <Mor...@online.nospam> wrote in message
news:28CAC759-24FD-46C7...@microsoft.com...

Joseph M. Newcomer

unread,
Mar 5, 2007, 1:13:34 PM3/5/07
to
There is no real need to worry about this. Since it is a service, it can only be run by
the Service Control Manager (SCM) which is not going to start two instances. And you
can't run it by double-clicking it.

For the monitoring app, see my essay on my MVP Tips site.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Dan Baker

unread,
Mar 5, 2007, 2:12:30 PM3/5/07
to
Why do you say "You can't run it by double-clicking it"? I thought services
were just applications.
DanB


"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:rbnou2dilspmv0155...@4ax.com...

Tom Serface

unread,
Mar 5, 2007, 4:12:19 PM3/5/07
to
NT Services are very special kinds of applications. They can have a GUI
(although it's not recommended) and you can wrap a standard application to
run as a service or not (that's why I thought you were trying to preclude
it). This is an interesting technique:

http://www.codeproject.com/system/xyntservice.asp

Tom

"Dan Baker" <dbmail> wrote in message
news:uxGQ5o1X...@TK2MSFTNGP02.phx.gbl...

Joseph M. Newcomer

unread,
Mar 5, 2007, 4:19:16 PM3/5/07
to
A service is not a typical application; it must follow very specific rules and it has no
capability of being run as an application. It can only be run as a service, and no other
way. Perhaps you are thinking of Unix, which allows any app to be a service. Which is
one of the reasons Unix services are so unreliable (I used to have to restart various
services several times a day)
joe

Charles Wang[MSFT]

unread,
Mar 8, 2007, 7:33:41 AM3/8/07
to
Hi, Morris,
For your Windows Service application, it is no need to worry about multiple
processes as Joe mentioned.

For your concerns about having only one instance of your monitor
application running, you can use the FindWindow function in the entry
function of your application to check if the application main window has
been existed. If so, exit the process; otherwise start the process.

We look forward to your response and let us know if you need further
assistance on this issue.

Have a good day!

Charles Wang
Microsoft Online Community Support
=====================================================
Get notification to my posts through email? Please refer to:
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications

If you are using Outlook Express, please make sure you clear the check box
"Tools/Options/Read: Get 300 headers at a time" to see your reply promptly.


Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
======================================================
When responding to posts, please "Reply to Group" via
your newsreader so that others may learn and benefit
from this issue.
======================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
======================================================

Joseph M. Newcomer

unread,
Mar 8, 2007, 2:18:12 PM3/8/07
to
This solution, which keeps getting promulgated as if it could actually ever work, is
simply wrong; I know it is wrong because I have seen it fail, solidly. See my essay on my
MVP TIps site. You CANNOT rely on FindWindow because of intrinsic race conditions that
exist! The ONLY reliable way is to create a named kernel object, such as an even, mutex,
or semaphore.

One of my successes was in getting the MSDN article that gave this algorithm FINALLY
removed from the MSDN, because it is completely erroneous! It cannot work, does not work,
and I have seen it fail.
joe
On Thu, 08 Mar 2007 12:33:41 GMT, chan...@online.microsoft.com (Charles Wang[MSFT])
wrote:

David Ching

unread,
Mar 8, 2007, 4:21:06 PM3/8/07
to
"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:q6o0v2pgmcd2a3n9h...@4ax.com...

> The ONLY reliable way is to create a named kernel object, such as an even,
> mutex,
> or semaphore.
>

Another reliable way is to put a simple BOOL global variable in a shared
data segment (yes, data segments can be shared for .exe's although they are
mostly used in DLL's).

#pragma data_seg(".sdata")
BOOL g_bAppRunning = FALSE;
#pragma data_seg()

// This comment makes the above data segment shareable
// It replaces having to add a linker option to the project
#pragma comment(linker, "/SECTION:.sdata,rws")

Then:

CMyApp::InitInstance()
{
if ( g_bAppRunning )
return FALSE; // another instance is running

g_bAppRunning = TRUE; // record app is running

...
}


This works great and is lighter weight than a mutex. The only negative I've
heard is that if you have 2 copies of the .exe (say one in RELEASE and
another in DEBUG), then the global variable is not shared between these
disparate copies of the .exe, so it is possible to launch both the release
and debug versions simultaneously. However, this doesn't happen in deployed
solutions.

-- David (MVP)


Tom Serface

unread,
Mar 8, 2007, 4:37:52 PM3/8/07
to
I've had great success with PJ's CSingleInstance class and it does not use
FindWindow() as part of the solution. That's why I always recommend it. I
also like how easy it is to pass the command line from one instance to
another.

http://www.naughter.com/sinstance.html

I understand how the class works (I have had to modify it slightly for my
solutions from time to time), but it's another one of those complex things
that I don't have to think about much now that it just works. This
solution uses a memory mapped file that can be accessed by all instances.

Tom

"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:q6o0v2pgmcd2a3n9h...@4ax.com...

Tom Serface

unread,
Mar 8, 2007, 4:47:33 PM3/8/07
to
HI David,

That's an interesting approach. I suppose you could also store information
about the original instance and pop it up or pass command line arguments to
it as well. I've never tried to do it this way, but I'll give this approach
a try. Thanks...

Tom

"David Ching" <d...@remove-this.dcsoft.com> wrote in message
news:67%Hh.1291$yW....@newssvr11.news.prodigy.net...

David Ching

unread,
Mar 8, 2007, 11:27:56 PM3/8/07
to
"Tom Serface" <tom.n...@camaswood.com> wrote in message
news:A14FD963-ED55-4B82...@microsoft.com...

> That's an interesting approach. I suppose you could also store
> information about the original instance and pop it up or pass command line
> arguments to it as well. I've never tried to do it this way, but I'll
> give this approach a try. Thanks...
>

Hi Tom, yes you most certainly can add a character array to hold the command
line... just make sure you declare it something like:

TCHAR g_szCommandLine[MAX_PATH] = {0}; // <-- don't forget to
init the shared memory, or else it won't be shared!

I've also declared shared HWND's so I can easily do a SetForegroundWindow()
of the existing one before exiting the second instance.

It sounds like the same capabilities as the class you mentioned, without the
need to create a memory mapped file.

Cheers,
David (MVP)


Charles Wang[MSFT]

unread,
Mar 9, 2007, 4:09:35 AM3/9/07
to
Hi, Joe,
Yes, you are right. I am sorry that I provided a bad solution here. A
simple scenario is that it will fail if there is an existed application
with the same title. It is common to use mutex for this scenario. For
example:
BOOL MyTestApp::InitInstance()
{
HANDLE hm =
CreateMutex(NULL,FALSE,L"F8EDEE44-DF7E-4ae3-B6AD-51B739E82EFC-MyTest-v1.0");

if ( hm && GetLastError () == ERROR_ALREADY_EXISTS)
{
return FALSE;
}
.....
}

Thank you for your point out.
Have a good day!

Best regards,

Joseph M. Newcomer

unread,
Mar 9, 2007, 11:11:55 AM3/9/07
to
That is indeed correct. The .exe segment which is shared must come from the same
executable image.
joe

Joseph M. Newcomer

unread,
Mar 9, 2007, 11:14:53 AM3/9/07
to
Some problems here...

The MAX_PATH value for the command line is far too small. Imagine six filenames with long
paths on the command line. There must be a lock protecting this variable, which is set by
the sender and released by the receiver, and a mutex or CRITICAL_SECTION will not work
for this; it must be a binary semaphore. It is usually better to use something llike
WM_COPYDATA to send the command line information across.
joe

Joseph M. Newcomer

unread,
Mar 9, 2007, 11:24:21 AM3/9/07
to
It is worse than that. I used a Microsoft template back around 1991 to avoid single
instances, but the window class it was looking for was the "Generic" class, and some other
programmer had done the same thing. My program would exit and bring his to the top. This
was pre-GUID, so in those (Win16) days I registered a class with the name of the program
in it.

Searching for the title doesn't work under conditions of localization and for MDI unless
you are careful. Most people who use this technique aren't.

The failure mode I saw was a programmer who chose to change from double-click-launch to
single-click-lauch, but neglected to reprogram his fingers. So he'd double-click and
launch two instances of the program, and due to the race condition I describe, it wouldn't
work because at the point where the decision was made, NEITHER app had yet created a
window, so each thought it was the only instance and went ahead and ran (this was when I
really began to realize that the Microsoft documentation, on which I'd based my design,
was a rewarmed and untested version of the Win16 documentation,,,and it only took five
years after that to get that article killed!)
joe
On Fri, 09 Mar 2007 09:09:35 GMT, chan...@online.microsoft.com (Charles Wang[MSFT])
wrote:

>Hi, Joe,

Tom Serface

unread,
Mar 9, 2007, 11:34:21 AM3/9/07
to
You're right if the second instance exited before the first instance got the
information that wouldn't work right, but perhaps the second instance could
copy the information to the first instance before exiting. The MAX_PATH
thing has always been a problem.

PJ's class uses WM_COPYDATA and it works fine. I'm going to play with
David's idea though. It sounds interesting and a lot more simple if it can
do all the same things. However, the CSingleInstance class has been working
for me for a long time so I kind don't want to fix something that isn't
broke... so to speak.

Tom

"Joseph M. Newcomer" <newc...@flounder.com> wrote in message

news:7r13v2h4js78kbk04...@4ax.com...

Tom Serface

unread,
Mar 9, 2007, 12:15:49 PM3/9/07
to
Hi Joe,

Wasn't that a different compiler back then? The first versions of
Microsoft's own compiler didn't include templates. Isn't that why all the
original MFC collection classes (circa 1994) were done as objects?

Tom

"Joseph M. Newcomer" <newc...@flounder.com> wrote in message

news:t023v29padfjhm4kv...@4ax.com...

David Ching

unread,
Mar 9, 2007, 3:53:06 PM3/9/07
to

"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:7r13v2h4js78kbk04...@4ax.com...

> Some problems here...
>
> The MAX_PATH value for the command line is far too small. Imagine six
> filenames with long
> paths on the command line.

Sure, storing the command-line has always been an issue, especially with UNC
filenames. In practice though, setting the buffer to something reasonable
like 4KB makes it deployable. Also using StringCbCopy to protect from
overrun.


> There must be a lock protecting this variable, which is set by
> the sender and released by the receiver, and a mutex or CRITICAL_SECTION
> will not work
> for this; it must be a binary semaphore. It is usually better to use
> something llike
> WM_COPYDATA to send the command line information across.

No, the variable is SHARED, there is no "sending across" any information.
When the app starts up, it checks if the command-line has been init by
another instance, and if so, it just reads it.

There is no more synchronization problem here than your usage of creating a
mutex. Both have the issue where it is possible for 2 instances to be
simultaneously started, check for the mutex, see it's not there, and create
it at the same time. This case is rightfully ignored because of the vitual
impossibility of starting 2 instances of an .exe that close together.

-- David

David Ching

unread,
Mar 9, 2007, 6:10:51 PM3/9/07
to
"David Ching" <d...@remove-this.dcsoft.com> wrote in message
news:SOjIh.301$JZ3...@newssvr13.news.prodigy.net...

>
> There is no more synchronization problem here than your usage of creating
> a mutex. Both have the issue where it is possible for 2 instances to be
> simultaneously started, check for the mutex, see it's not there, and
> create it at the same time. This case is rightfully ignored because of
> the vitual impossibility of starting 2 instances of an .exe that close
> together.
>

After looking at your code in more detail, I see that it is in fact NOT
possible to have a race condition, since even if both instances called
CreateMutex() simultaneously, only one instance would succeed. So, kudos,
your mutex solution does not have a race condition.

But the shared data segment solution can also be coded that way. If you
have a BOOL g_bAppIsRunning variable, you can use
InterlockedCompareExchange() to test and assign this to TRUE, in a
thread-safe manner. This then allows the shared data segment to replace the
mutex with no disadvantage.

Now for using the shared data segment to pass data (e.g. command-line)
between instances (assuming it is permissible to have multiple instances
running simultaneously). Well, I think you are right some thread safety
issues with this. The command-line storage needs to be protected somehow,
although I'm not sure why you say a mutex will not work for this. So
perhaps Mr. Naughter's method should not be discarded so quickly, as Tom
pointed out.

Finally, in your article, you say, "After you read the section on Race
Conditions you may see that this code has a race condition. If the Mutex was
created by instance 1, which is still coming up (it hasn't created its main
window yet), and instance 2 finds that the Mutex already exists, it tries to
find the window for Instance 1. But since Instance 1 is not yet there, this
code does not pop up the window for Instance 1. But that's OK. Because
Instance 1 has not yet created its window, it will proceed to create its
window successfully and pop up just like you'd expect. "

This is not always true, as your recent experience with the follies of
SetForegroundWindow() illustrate. The second instance has the focus, and if
the foreground lock timeout is not zero, then the first instance will be
prevented from bringing it's window to the foreground. To allow this, the
second instance can call:

AllowSetForegroundwindow(dwFirstInstanceProcessId);

And guess where you could store dwFirstInstanceProcessId? That's right, in
shared memory. :-)

-- David


Joseph M. Newcomer

unread,
Mar 10, 2007, 7:08:57 PM3/10/07
to
Largely the massive-file-name Unicode file name problem can be safely ignored; most code
will collapse the first time one of these filenames appears. The locking problem is a
serious issue, which is why WM_COPYDATA is useful. It used to be that some form of DDE
was used, but I haven't looked at the modern methods for doing this. I largely avoid the
problem by never dealing with filenames on the command line for apps that can only have
one instance.
joe

Joseph M. Newcomer

unread,
Mar 10, 2007, 7:48:46 PM3/10/07
to
No, by "template" I meant "a prototype for building an application". When we were writing
raw Win32 programs, everyone started either with Microsoft's template or Petzold's
template. By that time I had developed an aversion to Petzold's code, so I used the
Microsoft template for Windows applications. This was a pure C template; C++ was still
something for the future.
joe

Tom Serface

unread,
Mar 11, 2007, 12:17:02 AM3/11/07
to
Ah, that makes sense. Certainly all programs started with a copy and paste
effort. Yeah, I remember those days.

Tom

"Joseph M. Newcomer" <newc...@flounder.com> wrote in message

news:eck6v2pe5dqp9nv72...@4ax.com...

Charles Wang[MSFT]

unread,
Mar 12, 2007, 4:20:41 AM3/12/07
to
Hi, Joe,
Thanks for your detailed response. I can imagine that issue. Window
rendering need a time. If the application is double clicked multiple times
in a very short time, it is indeed possible to have multiple instances
started.

Thanks again for your clarification.

Jim Howard

unread,
Mar 14, 2007, 6:44:42 PM3/14/07
to
Joseph M. Newcomer wrote:
> This solution, which keeps getting promulgated as if it could actually ever work, is
> simply wrong; I know it is wrong because I have seen it fail, solidly. See my essay on my
> MVP TIps site. You CANNOT rely on FindWindow because of intrinsic race conditions that
> exist! The ONLY reliable way is to create a named kernel object, such as an even, mutex,
> or semaphore.
>

I've used the named kernel object technique for year in a number of
commercial applications. I know its easy to understand, because even I
can understand how it works. It is entirely reliable.

Why someone would want to take a window and try and use it for something
totally unrelated to the purpose of a window is beyond me, especially
when the findwindow method is more complicated and harder to understand
than the kernel object method. Even if it did work reliably, which it
doesn't.

Jim Howard

0 new messages