Re: MultiUse ActiveX Exe creates multiple instances (Round 2)

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Niall Quiggin (niall.quiggin_at_puzuma.xtek.xray.com)
Date: 03/08/04


Date: Mon, 8 Mar 2004 23:03:17 -0000

Thanks for the reply and to Tian Min Huang. I know that the problem is not a
race condition when registering the classes. I have confirmed this by mking
the change.

I have changed the DCOM configuration to be the interactive user and made
the changes as suggested. Go the code in the InitInstance method now reads
as follows.

if ( !mFirstInstance )
{
    // Signal to existing intance to show GUI and then exit.
}
else
{
    // Register class factories via CoRegisterClassObject().
    if (FAILED(_AtlModule.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE)))
        return FALSE;
    // Handle various start up cases
    // Createdialog
    // Show dialog in modal manner.
    // ...
}
return FALSE;

Now the way I test if this working OK is that I run up an instance to the
application from Explorer. When it is running, I then run the test harness
application that is written in VB and I debug it using VS.NET 2003 IDE. When
I try to use GetObject() to connect to the code, I get an exception ("Cannot
create ActiveX component at Microsoft.VisualBasic.Interaction.GetObject"). I
have also tried just making a new object of the required type. When I do
this, there is a long time lag of some 10 or so seconds and then I get an
exception ("System.Runtime.InteropServices.COMException (0x80080005). Server
execution failed.").

So as you can see, I still cannot connect to an existing instance which is
vital to me. What am I doing wrong?

Best regards,
Niall Quiggin.

"Alexander Nickolov" <agnickolov@mvps.org> wrote in message
news:eDbnpIUBEHA.3256@TK2MSFTNGP09.phx.gbl...
First comment is, you must use the interactive user for your
server's identity. That's because you want manual startup from
the interactive user.

Second comment is, you must check if an instance of your server
is already running if started by the interactive user (e.g. no
/Embedding command-line argument). If your server is already
running, instead of registering your class objects and proceeding,
you have to signal the other instance to show its GUI, and then
exit the new instance. Of course, you also need to implement the
code that accepts such signals and shows the GUI so this executes
in the hidden running server. Note, you may even have the server
showing GUI and the interactive user starting another instance
(or trying at least). In that case, simply use SetForegroundWindow
to bring the other process' main window to the foreground, then
exit.

-- 
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
"Niall Quiggin" <niall.quiggin@puzuma.xtek.xray.com> wrote in message
news:FmH2c.1602$7g5.908@newsfe3-win.server.ntli.net...
> I made a post about this on 13 February and got a very helpful reply. I
> thought that I had the answer that I needed, but I never tested it as I
had
> other things more pressing to do. To re-iterate the problem:
>
> I have created an ActiveX server written in C++. This is an MFC based
> executable that has a number of COM interfaces. I am using VS.NET 2003 to
> build this application and testing with a test harness written in VB.NET
> (original it was to be C#). I need this server application to run as a
local
> server, and to be manually run up (this is simple as the application can
be
> run when the user logs on). Periodically the VB code will be executed and
it
> will connect to the COM server using GetObject(), does some work and then
> disconnects. The server is to stay running.
>
> To create the COM server in C++, I made a new MFC executable application
> with automation selected. I then added ATL objects for the separate COM
> interfaces (which automatically added ATL support). In the InitInstance
> method of the application class there is the following code:
>
> // Register class factories via CoRegisterClassObject().
> if (FAILED(_AtlModule.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
> REGCLS_MULTIPLEUSE)))
>     return FALSE;
>
> It would seem that this is all that is required to make the server only
have
> one instance. But it is not. I found out in the reply to the last post
that
> I needed to configure DCOM so that it ran up the server application as a
> specific user (interactive or specified user and *not* the launching user
> which is the default). I have tried both settings and neither work for me
as
> the multiple instances of the server are run up.
>
> I am wondering if the problem is that I manually run up the initial
instance
> of the server application, i.e. run it directly from Explorer before
running
> the VB code.
> How do I achieve just one instance of the server for all?
>
> Best regards,
> Niall Quiggin
>
>
>
>


Relevant Pages