can't bring "single instance" tray app to foreground

I'm using the single instance class found at
<http://www.codeproject.com/threads/simplesingleinstanceapp.asp>.

When the first instance of my app receives the notification that
another instance was launched, it shows a dialog displaying the args
received.  The problem is that this dialog does not become the
frontmost/active window.

I'm doing something like this:

void CTrayApp::OnSecondInstance(UINT, LPARAM)
{
  m_pMainWnd->SetForegroundWindow();
  AfxMessageBox(GetSecondInstanceCmdLine(), IDOK);
}

which throws up the dialog but it's behind the active window
(generally the windows explorer file browser).

I guess it makes sense that SetForegroundWindow() isn't doing
anything since (because this is a trap app) the main window
was hidden.

void CTrayApp::InitInstance()
{
  ...
  m_pMainWnd->ShowWindow(SW_HIDE);
}

Now if, in OnSecondInstance(), I do ShowWindow(SW_RESTORE), my app
does come to the foreground, but I have a big blank main window
there now.

Any hints, or is what I'm trying to do even possible?  Normally
when my app is launched with args, it needs to import a file and
that requires interaction with the user.  That interaction involves
a dialog, so there is a window besides the main window that I can
bring to the foreground, but currently I use a modal dialog (using
DoModal()).  If I used a modeless dialog could I just bring that
to the foreground after it is created?  I'd rather stick to the
modal dialog for simplicity.

-frank
0
fcusack (69)
7/3/2007 12:51:53 AM
vc.mfc 33608 articles. 0 followers. Follow

14 Replies
423 Views

Similar Articles

[PageSpeed] 57

"Frank Cusack" <fcusack@fcusack.com> wrote in message 
news:m2fy46ia1i.fsf@sucksless.local...
> I'm using the single instance class found at
> <http://www.codeproject.com/threads/simplesingleinstanceapp.asp>.
>
> When the first instance of my app receives the notification that
> another instance was launched, it shows a dialog displaying the args
> received.  The problem is that this dialog does not become the
> frontmost/active window.
>
> I'm doing something like this:
>
> void CTrayApp::OnSecondInstance(UINT, LPARAM)
> {
>  m_pMainWnd->SetForegroundWindow();
>  AfxMessageBox(GetSecondInstanceCmdLine(), IDOK);
> }
>
> which throws up the dialog but it's behind the active window
> (generally the windows explorer file browser).
>
> I guess it makes sense that SetForegroundWindow() isn't doing
> anything since (because this is a trap app) the main window
> was hidden.
>
> void CTrayApp::InitInstance()
> {
>  ...
>  m_pMainWnd->ShowWindow(SW_HIDE);
> }
>
> Now if, in OnSecondInstance(), I do ShowWindow(SW_RESTORE), my app
> does come to the foreground, but I have a big blank main window
> there now.
>
> Any hints, or is what I'm trying to do even possible?  Normally
> when my app is launched with args, it needs to import a file and
> that requires interaction with the user.  That interaction involves
> a dialog, so there is a window besides the main window that I can
> bring to the foreground, but currently I use a modal dialog (using
> DoModal()).  If I used a modeless dialog could I just bring that
> to the foreground after it is created?  I'd rather stick to the
> modal dialog for simplicity.
>


You need to do two things.  First, the second instance of your app needs to 
call AllowSetForegroundWindow() so that the first instance (another process) 
is allowed to bring windows to the top.

Second, the first instance needs to create dialogs with the "Set Foreground" 
style.  In the dialog editor, this is a property you can set.  For 
AfxMessageBox(), the second parameter can be MB_OK | MB_SETFOREGROUND.  In 
your code, you should replace IDOK with MB_OK.

Cheers,
David


0
dc2983 (3206)
7/3/2007 1:56:36 AM
On Tue, 03 Jul 2007 01:56:36 GMT "David Ching" <dc@remove-this.dcsoft.com> wrote:
> "Frank Cusack" <fcusack@fcusack.com> wrote in message 
> news:m2fy46ia1i.fsf@sucksless.local...
>> I'm using the single instance class found at
>> <http://www.codeproject.com/threads/simplesingleinstanceapp.asp>.
>>
>> When the first instance of my app receives the notification that
>> another instance was launched, it shows a dialog displaying the args
>> received.  The problem is that this dialog does not become the
>> frontmost/active window.
>>
>> I'm doing something like this:
>>
>> void CTrayApp::OnSecondInstance(UINT, LPARAM)
>> {
>>  m_pMainWnd->SetForegroundWindow();
>>  AfxMessageBox(GetSecondInstanceCmdLine(), IDOK);
>> }
>>
>> which throws up the dialog but it's behind the active window
>> (generally the windows explorer file browser).
>>
>> I guess it makes sense that SetForegroundWindow() isn't doing
>> anything since (because this is a trap app) the main window
>> was hidden.
>>
>> void CTrayApp::InitInstance()
>> {
>>  ...
>>  m_pMainWnd->ShowWindow(SW_HIDE);
>> }
>>
>> Now if, in OnSecondInstance(), I do ShowWindow(SW_RESTORE), my app
>> does come to the foreground, but I have a big blank main window
>> there now.
>>
....
>
> You need to do two things.  First, the second instance of your app needs to 
> call AllowSetForegroundWindow() so that the first instance (another process) 
> is allowed to bring windows to the top.
>
> Second, the first instance needs to create dialogs with the "Set Foreground" 
> style.  In the dialog editor, this is a property you can set.  For 
> AfxMessageBox(), the second parameter can be MB_OK | MB_SETFOREGROUND.  In 
> your code, you should replace IDOK with MB_OK.

Thanks.  The docs at
<http://msdn2.microsoft.com/en-us/library/as6se7cb(VS.80).aspx>
have a pointer to
<http://msdn2.microsoft.com/en-us/library/w0kywcw3(VS.80).aspx>
which doesn't mention MB_SETFOREGROUND.  Now I found the MessageBox()
docs which do mention this flag.

So I added a call at app startup to AllowSetForegroundWindow(ASFW_ANY),
which succeeds.

But adding MB_SETFOREGROUND to my dialog doesn't work.  But I am not
having the first instance bring the window to the top, I am having the
second instance do it itself.

Is it the case that a background app cannot bring itself to the
foreground?  *Must* the second instance (I guess, the currently
foreground app) do this?

-frank
0
fcusack (69)
7/3/2007 2:47:54 AM
"Frank Cusack" <fcusack@fcusack.com> wrote in message 
news:m2odiu9p9h.fsf@sucksless.local...
> So I added a call at app startup to AllowSetForegroundWindow(ASFW_ANY),
> which succeeds.
>
> But adding MB_SETFOREGROUND to my dialog doesn't work.

MB_SETFOREGROUND should be used when calling MessageBox (or probably 
AfxMessageBox too), not for a dialog.  This is set in the dialog resource 
editor, in the Properties view when the dialog form (and not any of its 
controls) is selected.  BTW, how were you adding MB_SETFOREGROUND to your 
dialog??



> But I am not
> having the first instance bring the window to the top, I am having the
> second instance do it itself.
>

How are you doing that?  Since the first instance owns the dialog, it's the 
one that needs to bring it to the top.  Well, I've never called 
::SetForegroundWindow(hwndOfAnotherProcess) before.  Maybe it works, but 
I've never done it.


> Is it the case that a background app cannot bring itself to the
> foreground?  *Must* the second instance (I guess, the currently
> foreground app) do this?
>

As long as the second instance (foreground app) calls 
AllowSetForegroundWindow(), then the first instance can bring it's 
window/dialog to the foreground.  The concept is that only the app with the 
foreground focus can give it away, by calling AllowSetForegroundWindow.  Any 
other process, including the first instance of your app, will be blocked 
from having SetForegroundWindow() take effect... at least if the "foreground 
lock timeout", a user setting, is enabled.

You may want to post your code, it may make it easier.

-- David





0
dc2983 (3206)
7/3/2007 3:34:05 AM
On Tue, 03 Jul 2007 03:34:05 GMT "David Ching" <dc@remove-this.dcsoft.com> wrote:
> "Frank Cusack" <fcusack@fcusack.com> wrote in message 
> news:m2odiu9p9h.fsf@sucksless.local...
>> So I added a call at app startup to AllowSetForegroundWindow(ASFW_ANY),
>> which succeeds.
>>
>> But adding MB_SETFOREGROUND to my dialog doesn't work.
>
> MB_SETFOREGROUND should be used when calling MessageBox (or probably 
> AfxMessageBox too), not for a dialog.  This is set in the dialog resource 
> editor, in the Properties view when the dialog form (and not any of its 
> controls) is selected.  BTW, how were you adding MB_SETFOREGROUND to your 
> dialog??

I meant I added it to AfxMessageBox().

>> But I am not
>> having the first instance bring the window to the top, I am having the
>> second instance do it itself.
>>
>
> How are you doing that?  Since the first instance owns the dialog, it's the 
> one that needs to bring it to the top.  Well, I've never called 
> ::SetForegroundWindow(hwndOfAnotherProcess) before.  Maybe it works, but 
> I've never done it.

Damn, confused myself again.  I meant, I have the first (already running,
now in the background) instance bring itself to the foreground.  It does
this when the new instance posts the message to it.  But it doesn't
make it to the foreground unless I do ShowWindow(SW_RESTORE) which is
terrible.

>> Is it the case that a background app cannot bring itself to the
>> foreground?  *Must* the second instance (I guess, the currently
>> foreground app) do this?
>>
>
> As long as the second instance (foreground app) calls 
> AllowSetForegroundWindow(), then the first instance can bring it's 
> window/dialog to the foreground.  The concept is that only the app with the 
> foreground focus can give it away, by calling AllowSetForegroundWindow.  Any 
> other process, including the first instance of your app, will be blocked 
> from having SetForegroundWindow() take effect... at least if the "foreground 
> lock timeout", a user setting, is enabled.

hmm, are you saying ASWF() has to be called in the newly launched 2nd
instance?  I was only calling it in the first (now running in bg)
instance.  If it's that easy of a fix, that will be very cool.

If that's the case, I completely misunderstood how ASWF() works.

> You may want to post your code, it may make it easier.

If this round doesn't get it I'll do that.  I'll try fixing ASWF()
to also be called in the new instance, but in the meantime if you
can clarify it's operation that would be great.

-frank
0
fcusack (69)
7/3/2007 8:33:03 AM
"Frank Cusack" <fcusack@fcusack.com> wrote in message 
news:m2ir91zy2o.fsf@sucksless.local...
>
> I meant I added it to AfxMessageBox().
>

I guess I'm not understanding what you want to have happen when the second 
instance detects the first instance.  You want some window to display, but 
your main window is meant to be hidden.  You keep mentioning some "dialog" 
but then your code has AfxMessageBox().  So could you please clarify what 
exactly you want to come to the foreground?


> Damn, confused myself again.  I meant, I have the first (already running,
> now in the background) instance bring itself to the foreground.  It does
> this when the new instance posts the message to it.  But it doesn't
> make it to the foreground unless I do ShowWindow(SW_RESTORE) which is
> terrible.
>

Yes, you don't want to call ShowWindow(SW_RESTORE) on your main window, 
because that is meant to be hidden.  I think the only reason for the main 
window is because something must "own" the tray icon.  But this main window 
is never to be displayed because it has no useful content.  You are right 
that the first instance needs to bring the desired window (either dialog or 
messagebox) to the foreground... or create itself anew with the foreground 
style.


>> As long as the second instance (foreground app) calls
>> AllowSetForegroundWindow(), then the first instance can bring it's
>> window/dialog to the foreground.  The concept is that only the app with 
>> the
>> foreground focus can give it away, by calling AllowSetForegroundWindow. 
>> Any
>> other process, including the first instance of your app, will be blocked
>> from having SetForegroundWindow() take effect... at least if the 
>> "foreground
>> lock timeout", a user setting, is enabled.
>
> hmm, are you saying ASWF() has to be called in the newly launched 2nd
> instance?  I was only calling it in the first (now running in bg)
> instance.  If it's that easy of a fix, that will be very cool.
>
> If that's the case, I completely misunderstood how ASWF() works.
>

Yes, the second instance must be the one to call ASFW(), as it is the one 
with the focus, and is the only one that can then allow other apps to 
"steal" it.


-- David 


0
dc2983 (3206)
7/3/2007 1:56:30 PM
On Tue, 03 Jul 2007 13:56:30 GMT "David Ching" <dc@remove-this.dcsoft.com> wrote:
> "Frank Cusack" <fcusack@fcusack.com> wrote in message 
> news:m2ir91zy2o.fsf@sucksless.local...
>>
>> I meant I added it to AfxMessageBox().
>>
>
> I guess I'm not understanding what you want to have happen when the second 
> instance detects the first instance.  You want some window to display, but 
> your main window is meant to be hidden.  You keep mentioning some "dialog" 
> but then your code has AfxMessageBox().  So could you please clarify what 
> exactly you want to come to the foreground?

I want a dialog, from the first instance, to come to the foreground.
I am using AfxMessageBox() for simplicity and just to prove the concept
of being able to switch foregound apps/windows.

> Yes, the second instance must be the one to call ASFW(), as it is the one 
> with the focus, and is the only one that can then allow other apps to 
> "steal" it.

I still cannot get this to work.  Here, I hope, is enough code to
see what I'm doing wrong.

====
CTrayApp::CTrayApp()
  : CSingleInstanceApp(TEXT("{...}"))
{
  // if this is the 2nd instance, allow the 1st instance to come to fg
  if (!AllowSetForegroundWindow(ASFW_ANY))
    throw 1;
}

CTrayApp theApp;

BOOL
CTrayApp::InitInstance()
{
  if (!AmITheFirst()) {
    // wait just a bit so ASFW() in 2nd instance works
    // (don't exit before 2nd instance calls SFW())
    Sleep(500);
    return FALSE;
  }

  CMainFrame *pMainFrame = new CMainFrame;
  m_pMainWnd = pMainFrame;
  if (!pMainFrame->Create(NULL, "foo"))
    return FALSE;

  m_pMainWnd->ShowWindow(SW_HIDE);
  m_pMainWnd->UpdateWindow();

  return TRUE;
}

void CTrayApp::OnSecondInstance(UINT, LPARAM)
{
  m_pMainWnd->SetForegroundWindow(); // no effect (but main wnd was hidden)
  AfxMessageBox("hello world!", MB_OK|MB_SETFOREGROUND); // not in fg
}
====

In the dialog version, instead of AfxMessageBox(), I would create the
dialog and expect it to be in the foreground when I call DoModal(),
since I had just set the main window to the foreground.

-frank
0
fcusack (69)
7/5/2007 11:28:22 PM
"Frank Cusack" <fcusack@fcusack.com> wrote in message 
news:m2abuaig6h.fsf@sucksless.local...
> CTrayApp::CTrayApp()
>  : CSingleInstanceApp(TEXT("{...}"))
> {
>  // if this is the 2nd instance, allow the 1st instance to come to fg
>  if (!AllowSetForegroundWindow(ASFW_ANY))
>    throw 1;
> }
>
> CTrayApp theApp;
>
> BOOL
> CTrayApp::InitInstance()
> {
>  if (!AmITheFirst()) {
>    // wait just a bit so ASFW() in 2nd instance works
>    // (don't exit before 2nd instance calls SFW())
>    Sleep(500);
>    return FALSE;
>  }
>
>  CMainFrame *pMainFrame = new CMainFrame;
>  m_pMainWnd = pMainFrame;
>  if (!pMainFrame->Create(NULL, "foo"))
>    return FALSE;
>
>  m_pMainWnd->ShowWindow(SW_HIDE);
>  m_pMainWnd->UpdateWindow();
>
>  return TRUE;
> }
>
> void CTrayApp::OnSecondInstance(UINT, LPARAM)
> {
>  m_pMainWnd->SetForegroundWindow(); // no effect (but main wnd was hidden)
>  AfxMessageBox("hello world!", MB_OK|MB_SETFOREGROUND); // not in fg
> }
> ====

OK, let's start from scratch:

//////////////////////////////////////////////////////////////////////////
// Shared global variables - visible to all instances of this .exe

#pragma data_seg(".sdata")
 HWND sh_hwndMainFrame = NULL;
#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")


 CTrayApp::CTrayApp()
  : CSingleInstanceApp(TEXT("{...}"))
 {
 }

 CTrayApp theApp;


 BOOL
 CTrayApp::InitInstance()
 {
  if (!AmITheFirst()) {
    // this instance (the second instance) has the focus and must explicity 
give it away
    AllowSetForegroundWindow(ASFW_ANY);

    // Request the first instance to bring its window to foreground
    // Post message to CMainFrame of first instance
    // Assume CMainFrame::OnSecondInstance() is called when it receives a 
UWM_SECOND_INSTANCE message
    ASSERT (sh_hwndMainFrame != NULL);
    ::PostMessage ( sh_hwndMainFrame, UWM_SECOND_INSTANCE, 0, 0);
    return FALSE;
  }

  // First instance - create mainframe window that is hidden
  CMainFrame *pMainFrame = new CMainFrame;
  m_pMainWnd = pMainFrame;
  if (!pMainFrame->Create(NULL, "foo"))
    return FALSE;

  // No need to show or update the window, as it is hidden --- comment out
  //m_pMainWnd->ShowWindow(SW_HIDE);
  //m_pMainWnd->UpdateWindow();

  // Save main window handle for use in second instance
  sh_hwndMainFrame = m_pMainWnd->GetSafeHwnd();

  return TRUE;
}


Does this make sense?

-- David


0
dc2983 (3206)
7/5/2007 11:43:26 PM
On Thu, 5 Jul 2007 16:43:26 -0700 "David Ching" <dc@remove-this.dcsoft.com> wrote:
> "Frank Cusack" <fcusack@fcusack.com> wrote in message 
> news:m2abuaig6h.fsf@sucksless.local...
>> CTrayApp::CTrayApp()
>>  : CSingleInstanceApp(TEXT("{...}"))
>> {
>>  // if this is the 2nd instance, allow the 1st instance to come to fg
>>  if (!AllowSetForegroundWindow(ASFW_ANY))
>>    throw 1;
>> }
>>
>> CTrayApp theApp;
>>
>> BOOL
>> CTrayApp::InitInstance()
>> {
>>  if (!AmITheFirst()) {
>>    // wait just a bit so ASFW() in 2nd instance works
>>    // (don't exit before 2nd instance calls SFW())
>>    Sleep(500);
>>    return FALSE;
>>  }
>>
>>  CMainFrame *pMainFrame = new CMainFrame;
>>  m_pMainWnd = pMainFrame;
>>  if (!pMainFrame->Create(NULL, "foo"))
>>    return FALSE;
>>
>>  m_pMainWnd->ShowWindow(SW_HIDE);
>>  m_pMainWnd->UpdateWindow();
>>
>>  return TRUE;
>> }
>>
>> void CTrayApp::OnSecondInstance(UINT, LPARAM)
>> {
>>  m_pMainWnd->SetForegroundWindow(); // no effect (but main wnd was hidden)
>>  AfxMessageBox("hello world!", MB_OK|MB_SETFOREGROUND); // not in fg
>> }
>> ====
>
> OK, let's start from scratch:
>
> //////////////////////////////////////////////////////////////////////////
> // Shared global variables - visible to all instances of this .exe
>
> #pragma data_seg(".sdata")
>  HWND sh_hwndMainFrame = NULL;
> #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")
>
>
>  CTrayApp::CTrayApp()
>   : CSingleInstanceApp(TEXT("{...}"))
>  {
>  }
>
>  CTrayApp theApp;
>
>
>  BOOL
>  CTrayApp::InitInstance()
>  {
>   if (!AmITheFirst()) {
>     // this instance (the second instance) has the focus and must explicity 
> give it away
>     AllowSetForegroundWindow(ASFW_ANY);
>
>     // Request the first instance to bring its window to foreground
>     // Post message to CMainFrame of first instance
>     // Assume CMainFrame::OnSecondInstance() is called when it receives a 
> UWM_SECOND_INSTANCE message
>     ASSERT (sh_hwndMainFrame != NULL);
>     ::PostMessage ( sh_hwndMainFrame, UWM_SECOND_INSTANCE, 0, 0);
>     return FALSE;
>   }
>
>   // First instance - create mainframe window that is hidden
>   CMainFrame *pMainFrame = new CMainFrame;
>   m_pMainWnd = pMainFrame;
>   if (!pMainFrame->Create(NULL, "foo"))
>     return FALSE;
>
>   // No need to show or update the window, as it is hidden --- comment out
>   //m_pMainWnd->ShowWindow(SW_HIDE);
>   //m_pMainWnd->UpdateWindow();
>
>   // Save main window handle for use in second instance
>   sh_hwndMainFrame = m_pMainWnd->GetSafeHwnd();
>
>   return TRUE;
> }
>
>
> Does this make sense?

It makes sense, but seems to be the same as what I'm doing.

Using the CSingleInstanceApp class I found, AmITheFirst() sends the
notification to the 1st instance.  Therefore, I call ASFW() in my
constructor, so that I know it is called before the 1st instance tries
to call SFW().  In your example, AmITheFirst() would (apparently) just
return the value of (sh_hwndMainFrame == NULL).

CSingleInstanceApp creates a shared file mapping for the purpose of
sharing data between the 2 (or more?) instances.  The constructor
saves the thread id into the shared space if the shared mapping
doesn't already exist; if it did already exist, it posts a message to
the thread whose id was saved.  This seems to be a common technique.
It does work, as far as only allowing a single instance goes.

Why did you move ASFW() from the constructor to InitInstance()?  I
guess it's better that away since only the 2nd instance will allow
focus to be taken from it, but does it make any other difference?

-frank
0
fcusack (69)
7/6/2007 12:31:02 AM
"Frank Cusack" <fcusack@fcusack.com> wrote in message 
news:m2odiqgypl.fsf@sucksless.local...
> On Thu, 5 Jul 2007 16:43:26 -0700 "David Ching" 
> <dc@remove-this.dcsoft.com> wrote:
>> "Frank Cusack" <fcusack@fcusack.com> wrote in message
>> news:m2abuaig6h.fsf@sucksless.local...
>>> CTrayApp::CTrayApp()
>>>  : CSingleInstanceApp(TEXT("{...}"))
>>> {
>>>  // if this is the 2nd instance, allow the 1st instance to come to fg
>>>  if (!AllowSetForegroundWindow(ASFW_ANY))
>>>    throw 1;
>>> }
>>>
>>> CTrayApp theApp;
>>>
>>> BOOL
>>> CTrayApp::InitInstance()
>>> {
>>>  if (!AmITheFirst()) {
>>>    // wait just a bit so ASFW() in 2nd instance works
>>>    // (don't exit before 2nd instance calls SFW())
>>>    Sleep(500);
>>>    return FALSE;
>>>  }
>>>
>>>  CMainFrame *pMainFrame = new CMainFrame;
>>>  m_pMainWnd = pMainFrame;
>>>  if (!pMainFrame->Create(NULL, "foo"))
>>>    return FALSE;
>>>
>>>  m_pMainWnd->ShowWindow(SW_HIDE);
>>>  m_pMainWnd->UpdateWindow();
>>>
>>>  return TRUE;
>>> }
>>>
>>> void CTrayApp::OnSecondInstance(UINT, LPARAM)
>>> {
>>>  m_pMainWnd->SetForegroundWindow(); // no effect (but main wnd was 
>>> hidden)
>>>  AfxMessageBox("hello world!", MB_OK|MB_SETFOREGROUND); // not in fg
>>> }
>>> ====
>>
>> OK, let's start from scratch:
>>
>> //////////////////////////////////////////////////////////////////////////
>> // Shared global variables - visible to all instances of this .exe
>>
>> #pragma data_seg(".sdata")
>>  HWND sh_hwndMainFrame = NULL;
>> #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")
>>
>>
>>  CTrayApp::CTrayApp()
>>   : CSingleInstanceApp(TEXT("{...}"))
>>  {
>>  }
>>
>>  CTrayApp theApp;
>>
>>
>>  BOOL
>>  CTrayApp::InitInstance()
>>  {
>>   if (!AmITheFirst()) {
>>     // this instance (the second instance) has the focus and must 
>> explicity
>> give it away
>>     AllowSetForegroundWindow(ASFW_ANY);
>>
>>     // Request the first instance to bring its window to foreground
>>     // Post message to CMainFrame of first instance
>>     // Assume CMainFrame::OnSecondInstance() is called when it receives a
>> UWM_SECOND_INSTANCE message
>>     ASSERT (sh_hwndMainFrame != NULL);
>>     ::PostMessage ( sh_hwndMainFrame, UWM_SECOND_INSTANCE, 0, 0);
>>     return FALSE;
>>   }
>>
>>   // First instance - create mainframe window that is hidden
>>   CMainFrame *pMainFrame = new CMainFrame;
>>   m_pMainWnd = pMainFrame;
>>   if (!pMainFrame->Create(NULL, "foo"))
>>     return FALSE;
>>
>>   // No need to show or update the window, as it is hidden --- comment 
>> out
>>   //m_pMainWnd->ShowWindow(SW_HIDE);
>>   //m_pMainWnd->UpdateWindow();
>>
>>   // Save main window handle for use in second instance
>>   sh_hwndMainFrame = m_pMainWnd->GetSafeHwnd();
>>
>>   return TRUE;
>> }
>>
>>
>> Does this make sense?
>
> It makes sense, but seems to be the same as what I'm doing.
>
> Using the CSingleInstanceApp class I found, AmITheFirst() sends the
> notification to the 1st instance.  Therefore, I call ASFW() in my
> constructor, so that I know it is called before the 1st instance tries
> to call SFW().  In your example, AmITheFirst() would (apparently) just
> return the value of (sh_hwndMainFrame == NULL).
>
> CSingleInstanceApp creates a shared file mapping for the purpose of
> sharing data between the 2 (or more?) instances.  The constructor
> saves the thread id into the shared space if the shared mapping
> doesn't already exist; if it did already exist, it posts a message to
> the thread whose id was saved.  This seems to be a common technique.
> It does work, as far as only allowing a single instance goes.
>
> Why did you move ASFW() from the constructor to InitInstance()?  I
> guess it's better that away since only the 2nd instance will allow
> focus to be taken from it, but does it make any other difference?
>
> -frank

I didn't know CSingleInstanceApp did all that.  So you're right, your code 
and mine do similar.  I am still confused about your call to Sleep() and why 
you think you need to wait for the second instance there.  In any case, 
Sleep() causes many intermittent errors and you should find a way to get rid 
of it, since you just don't know how long to sleep for.  Whatever time 
period you pick is almost guaranteed not to work on some system, some of the 
time.

I have heard that you should not call PostThreadMessage() to a thread that 
has created windows, as it can cause the message to not be routed to the 
correct window.  There's a KnowledgeBase article on that.

Could you just debug the first instance and set a breakpoint at 
OnSecondInstance() to make sure it is being called when the second instance 
is started?  Note that in a debugger, the set foreground window should 
succeed since the debugger automatically sets Windows to allow foreground 
windows to be brought to top.

-- David 


0
dc2983 (3206)
7/6/2007 12:40:39 AM
On Thu, 05 Jul 2007 17:31:02 -0700 Frank Cusack <fcusack@fcusack.com> wrote:
> On Thu, 5 Jul 2007 16:43:26 -0700 "David Ching" <dc@remove-this.dcsoft.com> wrote:
>> "Frank Cusack" <fcusack@fcusack.com> wrote in message 
>> news:m2abuaig6h.fsf@sucksless.local...
>>> CTrayApp::CTrayApp()
>>>  : CSingleInstanceApp(TEXT("{...}"))
>>> {
>>>  // if this is the 2nd instance, allow the 1st instance to come to fg
>>>  if (!AllowSetForegroundWindow(ASFW_ANY))
>>>    throw 1;
>>> }
>>>
>>> CTrayApp theApp;
>>>
>>> BOOL
>>> CTrayApp::InitInstance()
>>> {
>>>  if (!AmITheFirst()) {
>>>    // wait just a bit so ASFW() in 2nd instance works
>>>    // (don't exit before 2nd instance calls SFW())
>>>    Sleep(500);
>>>    return FALSE;
>>>  }
....

vs

>>  CTrayApp::CTrayApp()
>>   : CSingleInstanceApp(TEXT("{...}"))
>>  {
>>  }
>>
>>  CTrayApp theApp;
>>
>>
>>  BOOL
>>  CTrayApp::InitInstance()
>>  {
>>   if (!AmITheFirst()) {
>>     // this instance (the second instance) has the focus and must explicity 
>> give it away
>>     AllowSetForegroundWindow(ASFW_ANY);
....

>> Does this make sense?
>
> It makes sense, but seems to be the same as what I'm doing.
>
> Using the CSingleInstanceApp class I found, AmITheFirst() sends the
> notification to the 1st instance.  Therefore, I call ASFW() in my
> constructor, so that I know it is called before the 1st instance tries
> to call SFW().  In your example, AmITheFirst() would (apparently) just
> return the value of (sh_hwndMainFrame == NULL).
>
> CSingleInstanceApp creates a shared file mapping for the purpose of
> sharing data between the 2 (or more?) instances.  The constructor
> saves the thread id into the shared space if the shared mapping
> doesn't already exist; if it did already exist, it posts a message to
> the thread whose id was saved.  This seems to be a common technique.
> It does work, as far as only allowing a single instance goes.
>
> Why did you move ASFW() from the constructor to InitInstance()?  I
> guess it's better that away since only the 2nd instance will allow
> focus to be taken from it, but does it make any other difference?

ah-ha.

It's not AmITheFirst() which posts the notification, it's the
CSingleInstanceApp ctor (which I initialize in the CTrayApp ctor).  So
in fact even though I called ASFW() in the CTrayApp ctor, it was
already too late as the CSingleInstanceApp ctor has already posted the
message, and the 1st instance had already put up the messagebox.

Moving ASFW() into the CSingleInstanceApp ctor (iff this is the
2nd instance) gets everything working.

Thanks so much for sticking with me on this one.

-frank
0
fcusack (69)
7/6/2007 12:50:15 AM
"Frank Cusack" <fcusack@fcusack.com> wrote in message 
news:m2r6nm73ug.fsf@sucksless.local...
> ah-ha.
>
> It's not AmITheFirst() which posts the notification, it's the
> CSingleInstanceApp ctor (which I initialize in the CTrayApp ctor).  So
> in fact even though I called ASFW() in the CTrayApp ctor, it was
> already too late as the CSingleInstanceApp ctor has already posted the
> message, and the 1st instance had already put up the messagebox.
>
> Moving ASFW() into the CSingleInstanceApp ctor (iff this is the
> 2nd instance) gets everything working.
>
> Thanks so much for sticking with me on this one.
>
> -frank

Glad it's working now!  :-)

-- David 


0
dc2983 (3206)
7/6/2007 1:38:54 AM
On Thu, 5 Jul 2007 17:40:39 -0700 "David Ching" <dc@remove-this.dcsoft.com> wrote:
> I have heard that you should not call PostThreadMessage() to a thread that 
> has created windows, as it can cause the message to not be routed to the 
> correct window.  There's a KnowledgeBase article on that.

Makes sense.  I'll do a GetSafeHwnd() thing instead, like your example.
-frank
0
fcusack (69)
7/6/2007 1:49:29 AM
On Thu, 5 Jul 2007 16:43:26 -0700 "David Ching" <dc@remove-this.dcsoft.com> wrote:
> //////////////////////////////////////////////////////////////////////////
> // Shared global variables - visible to all instances of this .exe
>
> #pragma data_seg(".sdata")
>  HWND sh_hwndMainFrame = NULL;
> #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")

How can I make sh_hwndMainFrame visible to other modules (files)?  I
added a header with

  extern HWND sh_hwndMainFrame;

and my trayapp.cpp is the only place where sh_hwndMainFrame is defined,
so I know "for sure" that there is just the one and only sh_hwndMainFrame.
But in my mainframe.cpp, the sh_hwndMainFrame that it accesses is not
the shared one.  Apparently.

Actually I don't care to share sh_hwndMainFrame, I am trying to share
a char buffer.  The 2nd instance saves the command line there, and the
1st instance retrieves it.  The code to retrieve the command line has
to live in mainframe.cpp because that's where window events are handled.

TIA
-frank
0
fcusack (69)
7/9/2007 5:04:06 PM
"Frank Cusack" <fcusack@fcusack.com> wrote in message 
news:m28x9ppkzd.fsf@sucksless.local...
> On Thu, 5 Jul 2007 16:43:26 -0700 "David Ching" 
> <dc@remove-this.dcsoft.com> wrote:
>> //////////////////////////////////////////////////////////////////////////
>> // Shared global variables - visible to all instances of this .exe
>>
>> #pragma data_seg(".sdata")
>>  HWND sh_hwndMainFrame = NULL;
>> #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")
>
> How can I make sh_hwndMainFrame visible to other modules (files)?  I
> added a header with
>
>  extern HWND sh_hwndMainFrame;
>
> and my trayapp.cpp is the only place where sh_hwndMainFrame is defined,
> so I know "for sure" that there is just the one and only sh_hwndMainFrame.
> But in my mainframe.cpp, the sh_hwndMainFrame that it accesses is not
> the shared one.  Apparently.
>
> Actually I don't care to share sh_hwndMainFrame, I am trying to share
> a char buffer.  The 2nd instance saves the command line there, and the
> 1st instance retrieves it.  The code to retrieve the command line has
> to live in mainframe.cpp because that's where window events are handled.
>
> TIA
> -frank

Frank, the memory turns out not to be shared between .exe instances if you 
don't initialize it.  So to share a char buffer you need to declare it 
something like this:

 #pragma data_seg(".sdata")
     TCHAR sh_szCommandLine[MAX_PATH] = {0};    // <-- init to all 0's
 #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")


-- David 


0
dc2983 (3206)
7/9/2007 5:26:14 PM
Reply:

Similar Artilces:

Single Instance Storage
I know that if a user sends an email with attachments to multiple people that only one copy of the attachment exists and everyone receives a pointer to those but what if the user embedded numerous pictures into the body of the email and then sent that to multiple people? Are pointers still used? On Wed, 24 Aug 2005 07:57:13 -0700, "David Mendes" <someone@here.com> wrote: >I know that if a user sends an email with attachments to multiple people >that only one copy of the attachment exists and everyone receives a pointer >to those but what if the user embedded ...

Single Instance Store and Deletions
Hi all, could someone please just confirm my understanding of Single Instance store: A mail is sent to 50 people on an Exchange Site. The mail is stored in one location in PRIV and the 50 mailboxes get a link to it. (When looking at the Mailbox Resources listing all Mailboxes on a server does the size of this message get added to that user's mailbox size? I've noticed in the past that when adding up the total mailbox sizes they are usually bigger than the size of the PRIV file.) When one user deletes the mail, no white space is freed up as the mail is still required by the other...

Multiuse (Single Instance) or Single Use (Multiple Instances)
Hi, Some of our VBA application that used createObject doesn't work . Then we found about the below points from Microsoft and made it to work using getObject. "COM servers can be classified as Multiuse (Single Instance) or Single Use (Multiple Instances), depending on the number of instances of that server that can run simultaneously on a single computer. " We haven't changed anything in the OS, except upgrading Excel 2003 to Excel 2007.Can you let me know what might have made the system to switch from Single Use (Multiple Instances) to Multiuse (Single ...

Multiple Charts from single instance of data
I am trying to produce multiple charts from one instance of data. The data is emailed to me in "raw form" - that is, imbedded as message text in the body of the message. The data is rather simple; consists of 3 fields per record as follows: Account# Actual Plan 1 75 100 2 100 100 3 1250 1000 etc. This data is sent to me once every month. Pretty simple in terms of data... Each account number has an actual (spend) and a planned (spend). In the example above, account 1 is "under plan", account 2 is "at plan...

single instance backup store
does the DP server implement this in disk and / or tape storage? (1 copy of nt.dll copied from 5 servers) Hi Marc, DPM doesn't single instance a file from different servers as of now (though, it does efficiently store the data of different recovery points of the same server/datasource). We are looking at doing this in the future versions of DPM. Thanks, Narendran [MSFT] This posting is provided “AS IS” with no warranties, and confers no rights "Marc Harbeson" <NospamTemp018@nospam.nospam> wrote in message news:715E8913-0EA1-4500-A67D-AAF91747D45B@micro...

Single Instance Store (SIS)
Is there a way to get statistics for Single Instance Store (SIS), user statistics, amount of data and other useful information? How? Exchange 2003/2007. SIS is not availible in Exchange 2010, want to do some investigation on this before migration to Exchange 2010. Jordan On Fri, 20 Nov 2009 19:06:04 +0100, Jordan wrote: >Is there a way to get statistics for Single Instance Store (SIS), user >statistics, amount of data and other useful information? How? >Exchange 2003/2007. PerfMon. MSExchangeIS Mailbox \ Single Instance Ratio. How useful that is depends on how mu...

Single Instance Ratio
When you move a mailbox from one server to another does it break the single instance ratio? Single instance ratio for *what*? SIS is implemented on a per-message/per-mailbox store basis. -- Ben Winzenz Exchange MVP MessageOne Read my blog! http://winzenz.blogspot.com http://feeds.feedburner.com/winzenz (RSS Feed) "Riccardo" <dskjfhadskjgaskjdhgf@ajhsgdfkjsahgfksajh.sdjhfgsakjhdgfsadjhg.s> wrote in message news:ejhFoCFpGHA.4268@TK2MSFTNGP04.phx.gbl... > When you move a mailbox from one server to another does it break the > single instance ratio? Hi Riccardo, ...

can't bring "single instance" tray app to foreground
I'm using the single instance class found at <http://www.codeproject.com/threads/simplesingleinstanceapp.asp>. When the first instance of my app receives the notification that another instance was launched, it shows a dialog displaying the args received. The problem is that this dialog does not become the frontmost/active window. I'm doing something like this: void CTrayApp::OnSecondInstance(UINT, LPARAM) { m_pMainWnd->SetForegroundWindow(); AfxMessageBox(GetSecondInstanceCmdLine(), IDOK); } which throws up the dialog but it's behind the active window (generally t...

Single Instance Messaging/Adding a new Server
Greetings All, I am adding a new exchnage server to one of our regional offices in order to ease a perceieved performance issue. Currently we have 1 storage group with 2 info stores, Users A-K and Users L-Z. Users L-Z will be moved to the new server.The edb for Users L-Z is approx 17GB in size with a single instance messaging ratio of approx 11-1 (we have alot of people using distribution lists here). Users L-Z is approx 400 people. My question - in moving users in the L-Z group to the new server, what can I expect (in real life terms) the expansion of the database to be... ie, what kind of ...

Single Instance Math Problem
If I had an Exchange 2003 server with 100 GB store and a single instance storage ratio of 5, would the size of the store jump to 500 GB without single instance? Reason for question: I plan to move old mail off the server, into pst files and on a Windows file server. I want to know how much space on the file server to allocate. On Fri, 12 Aug 2005 13:24:03 -0700, "Shawn" <Shawn@discussions.microsoft.com> wrote: >If I had an Exchange 2003 server with 100 GB store and a single instance >storage ratio of 5, would the size of the store jump to 500 GB without single &...

Child dialog's
Hello , I am able to limit the app to single instance. But the child dialog's (modeless) could not be limited to single instance. I mean I want to limit the child dialog's to be single instance. Also I could not bring the child dialogs to focus by using tab. Could you let me know how to do this ? Thanks in advance, Ravi I don't understand the problem. class CMyMainDialog : public CDialog { ..... private: CMyChildDlg m_ChildDlg; }; void CMyMainDialog::BringupTheChild() { if (m_ChildDialog.m_hWnd == NULL) { m_ChildDialog.Create(....); } m_ChildDialo...

Single Instance Store Question
How does SIS work within exchange? or If I send an email to 30 of my exchange users from the internet will that transact as one instance or 30 instances? (assuming one exch db) - JP Exchange uses Single Instance Storage - each message is stored once in each Store message recipients reside in. Understanding Single Instance Message Storage https://www.microsoft.com/technet/prodtechnol/exchange/guides/E2k3AdminGuide/8fa39b5c-855e-45b6-956a-8a35ef59437a.mspx -- Bharat Suneja MCSE, MCT www.zenprise.com blog: www.suneja.com/blog ----------------------------------------- "Jean Pierre&qu...

Single Instance Store in migration
I'm about to migrate users from NT4 and Exchange 5.5 to W2K3 and Exchange 2003. Also I will be changing the name of the exchange organization. I figured out how to migrate the mailboxes using exmerge. That works fine, but I loose my Single Instance Storage. Is there a way to migrate mailboxes from an Exchange 5.5 organisation (named A) to an Exchange organisation (named B) without loosing the Single Instance Store?? Jurgen Voogd MCSE Systems Engineer In order to do this you would have to be a part of the same Org/Site and use the move mailbox utility. There may be 3rd party solutions...

Restore a broken Single Instance Storage / Log files
I have adopted an Exchange 2003 / Server 2003 SP1 server that is quickly running out of drive space. The exchange environment was improperly migrated to 2003 and SIS was broken. Is there any way to enable SIS once it has been broken? Also, my log files are HUGE!! I have about 30GB of database and 70GB of log files.... anything seem wrong to you? Is there any maintenance tat I can put in place to clear these log files... if you mean transaction log files, that would be an indication that backups have not been run...do an online full backup immediately, before you do anything else...and wha...

single instance of Outlook 2000
Is there a way to only allow a single instance of Outlook 2000 to be running at the same time? Add the /recycle switch to the file path in the shortcut you use to open Outlook. -- Jocelyn Fiorello MVP - Outlook *** Messages sent to my e-mail address will NOT be answered -- please reply only to the newsgroup to preserve the message thread. *** In news:01d101c3d177$da852c60$a601280a@phx.gbl, Brett Breitwieser wrote: > Is there a way to only allow a single instance of Outlook > 2000 to be running at the same time? ...

single instance
hi, I got a problem with an app which i developed in MFC , the problem is "It is required that when ever that app runs........, only single instance of that app should run, that app runs as a tray icon. the link http://support.microsoft.com/kb/q243953 helped me but............. when i click on "RUN AS" option by clicking right button it can be runned in multiple instances. PLZ HELP, Parijat In this situation you will have to attach the debugger to each of the processes and see how this function in the KB behaves:- BOOL IsAnotherInstanceRunning() { return (ERROR_ALREADY...

single instance?
For my Windows application, can I just use: if( m_hPrevInstance != NULL ) return FALSE; in the InitInstance() to make sure only one instance run? Do I have to use the Mutex? Kathy, The m_hPrevInstance parameter is a holdover from Win16. It is no longer in use, so you do have to use some other means of telling if your program is already running. Rich "The m_hPrevInstance data member is always set to NULL in a Win32 application. To detect a previous instance of an application, test for the existence of a named mutex/event." There was a post sometime back here, where I had s...

single instance YET ...
Hi, I wish to have my MDI based MFC application to be single instance. Let's assume I use the unique class name method. When my application starts, I check to see if there's already an instance running. If so, I set focus to active instance and terminate. But now I wish this: When a second instance is started with command line parameters, I wish to terminate that instance, but pass the command line parameters to the first instance (a file name, so that it can be openend as another document inside my MDI application). How do I pass this info? Is it possible to pass this via a window...

Single Instance of Application
Hi, I have an interesting requirement. My application is launched by windows explorer, the command line argument for the application is the directory path that is selected from the windows explorer. Reqt: I launch my application from some directory say C:\Temp\xyz. I minimize the application and goto explorer and select another directory say C:\Temp\abc, I hv to show the same application for the selected directory. I have used MUTEX for single instance, but now I want to parse the command line for the second time. My first code was like this BOOL CDpoiApp::InitInstance() { if (g_SingleIn...

Single instance help
Hi, I have an SDI application that is also a server (that is - has objects that can be embedded in other applications say - MSWord). I would like to have this run as a single instance. I have followed the procedure described in an article by Joe Newcomer (very clear and easy to understand) - have included the 'exclusion.h', 'exclusion.cpp' files and have the CWinApp derived class check that it is not running already. This works fine when I am trying to run tha application as a stand-alone application - if it is already running, it does not run again the second time. However,...

Single Instance running under NTService
Hi, I have a server application running under Win2k server. I register it as a NTservice so it will still running after the user log off from the server. My server application can be hide under System Tray. There is one problem annoy me for quite sometimes. When the user log on to the server, the server application doesn't appear on system tray. If I need to see the dialog box, then I need to restart the service again. Currently I just adding in the code so that it only allow single instance running. http://www.developerfusion.com/show/1716/7/ It ...

Single Instance Broken after Move to 2003
is it possible to "mass migrate" users from 5.5 to 2003 (using the move wizard) and maintain single instance storage? Our pilot group migrated to 2003 resulted in a massive store , obviously we don't want to blow out of proportions when we migrate the next 3,000 mailboxes. Jerry. Yes. SIS will be maintained beween messages in the same store. Note that the increase you saw is not entirely atypical as many times the mailbox sizes your 5.5 server reported were not always correct. On Wed, 9 Jun 2004 09:58:27 +0800, "jerry cantrell" <undisclosed@earth.net&g...

Single Instance of Outlook 2002 Open
Is there a way to restrict how many instances of Outlook can be running simultaneously? I would like to allow only one instance of the program to be open. I didn't think you could open up more than one instance of OL2002. It sure won't let me open up more than one at a time. If I try to launch it again, it merely opens up the existing Outlook window. Larry Williams wrote: > Is there a way to restrict how many instances of Outlook > can be running simultaneously? I would like to allow only > one instance of the program to be open. ...

Edit a single instance of a recurring task?
Hi all - Just wondering if this is possible. If I have a recurring appointment in Outlook, I can make changes to a single instance of that appointment - change the date/time, delete it, change the reminder time, etc. Can I do the same with a recurring task? I'm fairly computer literate, but it seems like all I can do is skip an occurrence or edit the series. I work mostly from Outlook 2003, but would accept an answer for Outlook 2007. If there is not a way to do this, does anyone have a workaround? Thanks, tbgg :confused: -- tbgg http://forums.slipstick....

Move Mailboxes and Single Instance Store
Hi, Small question about single instace store, If I moved all mailboxes placed in one store, to a newly created store on the same SG. Will I lose the single instance store for e-mails by moving the mailboxes process?? Yes, if all recipients are moved to the same Store. Exchange single-instance storage and its effect on stores when moving mailboxes http://support.microsoft.com/kb/175481 -- Bharat Suneja MVP - Exchange www.zenprise.com NEW blog location: exchangepedia.com/blog ---------------------------------------------- "Feras Mustafa" <FerasMustafa@discussions.microsoft...