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
http://bobmoore.mvps.org/Win32/w32tip7.htm
Cheers
Check Abdoul
---------------------
"Morris Neuman" <Mor...@online.nospam> wrote in message
news:28CAC759-24FD-46C7...@microsoft.com...
http://www.naughter.com/sinstance.html
Tom
"Morris Neuman" <Mor...@online.nospam> wrote in message
news:28CAC759-24FD-46C7...@microsoft.com...
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
"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:rbnou2dilspmv0155...@4ax.com...
http://www.codeproject.com/system/xyntservice.asp
Tom
"Dan Baker" <dbmail> wrote in message
news:uxGQ5o1X...@TK2MSFTNGP02.phx.gbl...
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.
======================================================
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:
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)
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...
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...
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)
Thank you for your point out.
Have a good day!
Best regards,
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
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,
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...
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...
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
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
Tom
"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:eck6v2pe5dqp9nv72...@4ax.com...
Thanks again for your clarification.
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