|
If it's already running how would one make it wait for previous of the same exe to quit? before proceeding with that instance. i.e.
test.exe is running.
test.exe is run again but waits until previous test.exe has quit before continuing to run.
Thanks,
Lee.
|
|
|
|
|
for WinXP and Multi-User desktops you gotta name the Mutex like "//Global/My Mutex" to be visible on the machine.
In Vista there are things different. AFAIK if a instance is running in Admin-Mode another in User-mode cant send messages successful. And other thing may happen to...
Greetings from Germany
|
|
|
|
|
Here is what I inted to do when using events for process communication.
step1:
Create an unique event in the ininstance method in Reset mode.
Check if event is already created.
If event not created then create event and create screenControl thread to listen for set/reset of that event.
If event is there then means window is already present and hence
set the event here so that running thread can wakeup.
// OnlyOne.cpp
// global data
HANDLE hEvent;
int ShutDownFlag;
void ScreenMonitor(LPVOID pParam);
// COnlyOneApp initialization
BOOL COnlyOneApp::InitInstance()
{
///// other stuff...
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(COnlyOneDoc),
RUNTIME_CLASS(CMainFrame), RUNTIME_CLASS(COnlyOneView));
AddDocTemplate(pDocTemplate);
//------
hEvent = CreateEvent(NULL,TRUE,FALSE,_T("ONLYONE-APP"));
AlreadyRunning = ( ::GetLastError() == ERROR_ALREADY_EXISTS || ::GetLastError() == ERROR_ACCESS_DENIED);
if (AlreadyRunning) {
MessageBox(NULL,"Already Running....","Message!!",MB_OK);
SetEvent(hEvent);
return TRUE;
}
//-------
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
//--------
CWinThread *wndThread = AfxBeginThread((AFX_THREADPROC)ScreenMonitor, m_pMainWnd->GetSafeHwnd(),THREAD_PRIORITY_NORMAL,0,0);
if (wndThread == NULL)
{
MessageBox(NULL,"Could not Create Thread...","MSG",MB_OK);
return FALSE;
}
//-------
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
step 2:
Thread method. This method waits for events to set. When event is set which signifies same application tried to start, this thread brings first instance in the foreground.
// COnlyOneApp message handlers
void ScreenMonitor(LPVOID pParam)
{
CWnd* wnd;
while(ShutDownFlag)
{
WaitForSingleObject (hEvent, INFINITE);
wnd = CWnd::FromHandlePermanent(static_cast(pParam));
if (wnd->IsIconic())
wnd->ShowWindow(SW_RESTORE);
wnd->SetForegroundWindow();
ResetEvent(hEvent);
}
}
Who lets the coder out...
|
|
|
|
|
Like many other implementations, yours again does not behave gracefully in a multiuser environment. This problem is well discussed in in Josephs' Article .
Sorry, but one could not say it loud enough: The common, well known and even Microsoft recommended(!) solution with the mutex is wrong!
It makes your app incomatible to multiuser/multidesktop environments. Check out the above article for details and solutions.
--
Daniel Lohmann
http://www.losoft.de
|
|
|
|
|
I have the problem too.
What is the best solution to resolve it.
|
|
|
|
|
The best solution to resolve this is to enrich the mutex name with additional information, to ensure the right definition of "unique instance" is used. If you want to ensure that there is only one instance per visible desktop, include the desktop name in the name of the mutex etc.
However, I am not going into details here, because this is already discussed in depth in this article.
Some ready to use code that takes these problems into account can be found here.
--
Daniel Lohmann
http://www.losoft.de
(Hey, this page is worth looking! You can find some free and handy NT tools there )
|
|
|
|
|
I've modified a dialog based app to use this.
It works fine for me, so long as I'm in debug!. When I use it on a release build I get:
"Unhandled Exception in xxx.exe (MFC42.DLL):0xC0000005:Access Violation."
The interestig thing is that it only happens on my second attempt to execute another application, the first attempt works fine.
The message handler 'OnCheckItsMe()' Is getting called fine the second time but after it returns it all goes pear shaped, has anyone else found this with a multiple re-execute?
|
|
|
|
|
Please show your OnCheckItsMe function, their might be another problem in your code.
|
|
|
|
|
Make certain that the message handler has this form:
afx_msg LRESULT OnCheckItsMe(WPARAM wParam, LPARAM lParam);
If you do not include the wParam and lParam parameters it will crash the Release version.
|
|
|
|
|
Ah, thanks for that fix!
J. Deinhard
|
|
|
|
|
Thanks a lot!
For a single document program, the original way poprposed by the author could do well. However, for a multiple documents program. Your comment is really important!
|
|
|
|
|
I just can't register the message.
Where shall I do that?
And where to put the message handler?
In the application.h or in my mainframe.h?
thanx for the answer and the excellent code.
ROUVIERE "CYCOSI" SIMON
|
|
|
|
|
As far as I know,you should register your message in initializing function (for example,OnInitDialog).
Second,message handler should be declared in mainframe.h.
|
|
|
|
|
It is a good implementation of the article written by Mr. Newcomer, but it does half of the job.
Now, perhaps the user can be completely happy with this half, ie. there is no need for anything else.
The other half I see missing is the capability to give to the existing instance the command line parameters of the new instance. Eg. when calling a text editor with the name of the file to edit. The advantage of looping on the windows is that you can get the handles, thus communicate with the window, eg. to send WM_COPYDATA.
In addition, I added the capability to indicate, by a menu check, if an instance can accept new files this way or not. Thus, if no instance accepts new file, a new instance can be spawned.
One day, once I clean and finalize my code, I may publish it too
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
Philippe Lhoste wrote:
the capability to give to the existing instance the command line parameters of the new instance
Just use the WPARAM/LPARAM of the registered message for flags, pointers or handles to pass whatever needed.
Its a nice and clean solution (does it it run correctly under TS?).
Vote against software patents in europe
|
|
|
|
|
Hi,
Below is a way I implement this in different Apps...can you tell me if this way is good enough (and if not why)??
BOOL AreWeAlone (LPSTR szName)
{
HANDLE hMutex = CreateMutex (NULL, TRUE, szName);
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
CloseHandle(hMutex);
return FALSE;
}
return TRUE;
}
MDI, SDI, Dialog, Console Implementation...
...
if (!AreWeAlone ((LPSTR) "Enter Something Here"))
return FALSE;
...
Thanks,
Dan
"Good programmers never dies, they just program away...then the new version comes!"
|
|
|
|
|
One problem I see with this code, is that a process can be stuck (not responding) but still have this mutex.
So the new instance will exit even if the user cannot access the other instance.
There may have other problems, see the mentioned article by Mr. Newcomer, which is excellent, on the issues of implementing such algorithm.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
Hi Philippe,
Thanks for the answer and information! I will check out Mr. Newcomer's article.
Thanks again,
Dan
|
|
|
|
|
I have seen some other notes that discussed the same problem.
Altough there is nothing new, it's really a good job.
Maybe it is the first one posted on the codetools.
|
|
|
|
|
I'm sure you've been asked this before: how do implement this for a dialog-based app? i could usually figure stuff like this out, but for some reason, my brain has been on a long vacation for this one. thanks.
and yeah, i too have the Princes of the Universe song stuck in my head now. "here we are.."
|
|
|
|
|
Just the same!
Best is to put everything up to point 5 before you
create the dialog and before you do a DoModal() on it
(if you're using MFC).
Then add the message handler to your dialog class.
|
|
|
|
|
As soon as I saw the title of the article Queen started playing inside my head.
And now I can't get the song 'Princes of the Universe' out of my head.
cheers,
Chris Maunder
|
|
|
|
|