none
.net interface to COM server fails with 0x80008005 (cross post) RRS feed

  • Question

  • Sorry about cross posting...but after posting this question in another forum I realized that this is probably the correct place to pose the question:

     

    I have a native c++ COM server that exposes COM interfaces. I can successfully use a native c++ client application to get and use the exposed interfaces from the server.

    When I use a .net client with a reference to the server, I get the following error when I try to create an instance of the server:

    Retrieving the COM class factory for component with CLSID {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

    ...even though the COM server starts and runs successfully (and only takes about 1 or 2 seconds to startup).

    Each time the .net client tries to create an instance of the server, a new instance starts - any existing instances are ignored.

    BUT I get the above error only when the server is registered as a local server. If I register the server as a windows service, the .net client can successfully get and use the interfaces just fine. It doesn't matter if the service is in the 'local system' account or my login account, the client/server interaction works when the COM server is registered as a service.

     

    I'm doing all this as an admin on Windows 7 64-bit. The client and server are both 32-bit apps. The COM server is on the local machine.

    I've had this working with vs2005 (targeting .net framework 2.). I recently updated to vs2010 and am now running into this issue. I've tried building the .net client targeting frameworks 2.0, 3.5, and 4.0 with the same results.

    Spent two days on this one so far...what could be the problem?

     

    Thanks

    Saturday, May 21, 2011 7:19 PM

Answers

  • I have the answer...the server lock handling was the cause.

    My server, as part of the configuration loading, creates COM objects (using CComObject<>::CreateInstance) and later releases them. The creation of the COM objects incremented the server's lock count, and the release of the COM objects decremented the server's lock count. By the time the server was completely loaded, the lock count had dropped to zero - which began the suspend/revoke logic for the server's interfaces. This happened immediately after the PreMessageLoop() over-ride, so after the startup finished the revoke began and the client application received the CO_E_SERVER_EXEC_FAILURE error.

    When I commented out part of the configuration load, it worked because the COM objects for that part of the configuration were created but not destroyed.

    When I ran the server as a service it worked because services are stopped by the SCM, not by the lock count going to zero.

    The interesting thing here is that the behavior is different between the VS2005 and VS2010 builds. The ATL code has changed between the two versions so the shutdown logic must be triggered differently (I didn't go that far into it, but maybe a default delay period has changed?).

    To fix the problem, I increment the server's lock count by one before loading the configuration and keep that lock until all other locks have been released.

    • Marked as answer by kalprin Sunday, July 24, 2011 6:02 PM
    Sunday, July 24, 2011 6:02 PM

All replies

  • Thank you for your question, we're doing research on this case, it might take some time before we get back to you.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, May 23, 2011 2:11 AM
  • Hello kalprin,

     

    1. Concerning the CO_E_SERVER_EXEC_FAILURE Error.

    1.1 This error occurs when a client (any client, be it written in C++ or in a .NET language), is not able to retrieve the class factory of a COM class. The class factory is the COM object that instantiates a COM class. All COM objects have an associated class factory object.

     

    1.2 In the case of a COM EXE server (service exe or plain exe), this can happen if the class factory is not successfully registered (via API RegisterClassObjects()). The following are possibilities :

    1.2.1 The call to the RegisterClassObjects() API failed.

    1.2.2 The call to RegisterClassObjects() was made with the REGCLS_SUSPENDED flag and the CoResumeClassObjects() API was never called or that it was called but failed.

     

    1.3 The curious thing is that the error occurred only when the COM server is a plain (non-service) local server and the client is a .NET-based application.

    1.3.1 Now, the problem is not with locating the COM EXE server nor with launching it. It is launched fine. The problem is with the failure of the class factory registration process. 

    1.3.2 With such a failure, the next time a request is made by any client to obtain the class factory, another instance of the COM EXE server is started up because the previous instance did not supply the required class factory. This is why you mentioned :

    "Each time the .net client tries to create an instance of the server, a new instance starts - any existing instances are ignored."

     

    1.4 The fact that both the C++ native client app and the .NET client app succeed in using a service-based COM server makes me suspect that the success is due to the fact that the class factory registration process has already been carried out successfully by the time the client apps attempt to instantiate the COM classes. This is assuming that the service has been set up to start up automatically.

    1.4.1 Based on this premise, I suggest some tests which are outlined in the sections below.

     

    2. Test Suggestion 1.

    Assuming that you have created your COM server using ATL, I suggest performing the following test :

    2.1 Start to debug the COM server without running any client code.

    2.2 Put a breakpoint in the _tWinMain() function and start to step from there.

    2.3 Pay careful attention to the following ATL source codes location :

    CAtlExeModuleT<T>::PreMessageLoop(int) (<Visual Studio Folder>\VC\atlmfc\include\atlbase.h).

    This is where the RegisterClassObjects() API is called. Now because you will be performing debugging, the COM server will be started up without being invoked by the COM-subsystem and hence I believe the call to RegisterClassObjects() API will succeed.

    2.4 Once you can confirm that the RegisterClassObjects() API has succeeded, simply let the program run without stepping any further.

    2.5 Now execure your .NET client app. See if it succeeds this time.

    2.6 The logic of the test is that, with the COM class properly registered, the .NET client should be able to create an instance using the currently running COM server.

     

    3. Test Suggestion 2.

    3.1 Another way you can test the COM server is by starting up the C++ client app. This should start up the COM server.

    3.2 Then ensure that the C++ app remains running.

    3.3 At this time, start up the .NET client app. See if it succeeds this time.

    3.4 The logic of the test is similar to the one in section 2 : i.e., with the COM class properly registered, the .NET client should be able to create an instance.

     

    Please give the tests a try and let us know how things turn out.

    Best of luck, kalprin,

    Bio.

     


    Monday, May 23, 2011 11:33 AM
  • Bio,

     

    Thanks for the suggestions. These are the kinds of tests I've been running, but I ran through your tests again. The results are below.

     

    Test suggestion 1

    I started the COM server in a debugger. I could see that CoRegisterClassObjects(), called with REGCLS_SUSPENDED, succeeded. I could then see that CoResumeClassObjects() succeeded. I then let the COM server continue to run. When I started the .net client (in another debug session), it started a second instance of the COM server and received the 0x80080005 error.

     

    Test suggestion 2

    I started the native c++ client application in a debugger and let it start and connect to the COM server. I then just let it run. I then started the .net client application in a debugger. It's connection attempt started a second instance of the COM server and it received the 0x80080005 error.

     

    I've run these tests using a primary interop assembly built for the COM server (and referenced by the .net client), and also run the tests without a primary interop assembly - referencing the COM server directly in the client. The results are the same - error 0x80080005.

     

    Thanks for any other suggestions...

     

    Monday, May 23, 2011 2:52 PM
  • Hello kalprin,

     

    1. Thanks very much for running the tests and sharing with us the results.

    2. So it seems that the .NET client app will always launch a new instance of the COM EXE server even if the class factory of the COM class has obviously been registered successfully. This is of course assuming that CoRegisterClassObject() was called with the REGCLS_MULTIPLEUSE flag.

    3. Currently, I have some questions to ask you :

    3.1 Assuming that you have used the ATL wizard to generate your code, is your COM server project first created as a service-based EXE ?

    3.2 Thereafter, is it the same service-based COM server that is used as a plain local server ? After being de-registered as a service of course.

    3.3 How does the C++ client instantiate the COM class ? Did you #import the TLB and then use a _com_ptr_t ? Or did you use CoCreateInstance() or CoGetClassObject() ? Some sample code would be useful.

    3.4 How does the C# client instantiate the COM class ? Is it coded like the following :

    KalprinClass kalprin = new KalprinClass() ?

    or more like :

    Type type = Type.GetTypeFromProgId("kalprin.kalprin");
    Activator.CreateInstance(type);

    Some sample code would be useful.

    4. Additionally, I now suspect that even when it was launched for the very first time, the COM server probably succeeded in registering the class factory. However, the .NET client somehow always fails to connect to this class factory. To ascertain this, it would be great if you could perform another test which is outlined below :

    4.1 In the _tWinMain() function of your COM server source codes, add a call to the DebugBreak() API right at the beginning :

    extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/,
                                    LPTSTR /*lpCmdLine*/, int nShowCmd)
    {
        DebugBreak();
        return _AtlModule.WinMain(nShowCmd);

    Compile the codes. During the compilation process, when the IDE attempts to register the server, an exception occurred message box will appear. This is directly related to the DebugBreak() call above. Ignore this message for now. Do not click on the "Debug" button on this message box.

    4.2 Make sure that the COM EXE server is not running.

    4.3 Launch your .NET client app. When the client code attempts to instantiate the COM class, the COM server will be launched.

    4.4 The DebugBreak() API will cause a breakpoint exception to occur which prompts the system to display the unhandled breakpoint exception message box (that we met before). The message box will contain the "Debug" button. This time, do click on the "Debug" button.

    4.5 The Visual Studio IDE will be launched and you will be brought to the exact location of the call to DebugBreak() in your COM server code.

    4.6 Now step through as quickly as possible to the code location where CoRegisterClassObject() and CoResumeClassObjects() are called and see if they succeed.

    4.7 I mentioed quickly because too long a stepping process will also cause the .NET client to raise the 0x80080005 error.

    4.8 If the calls to CoRegisterClassObject() and CoResumeClassObjects() went through successfully, we know that the registered class object somehow could not be used by the .NET client.

     

     Thanks,

    - Bio.

     

    Tuesday, May 24, 2011 9:39 AM
  • Thanks again Bio for the suggestions.

     

    I'll provide the results once I can get a test to work.  When I add the DebugBreak() line to WinMain() the server doesn't break. I'm not sure why...when I run it in the debugger and step over that line it breaks.  When it is started by a client it does not break. I've verified that the server is indeed starting (and it is the correct .exe file on my machine). I don't believe it gets past the DebugBreak() statement because I don't see the usual logging output - but the process doesn't show a message or trigger the debugger to start, the process just exits. Any ideas on why this might be? I've got Just In Time debugging enabled for all types listed.

     

    Some answers to your questions:

    The server does use the REGCLS_MULTIPLEUSE flag.

    The ATL Wizard was indeed used, so the server can be registered as a service or a local server...otherwise it is the same code.

    The native c++ client imports the server's .tlb file and instantiates the server like this:

    asi::IasiServerPtr pServer;

    HRESULT hr = pServer.CreateInstance(asi::CLSID_asiServer);

    if ( NOERROR == hr )

    {

    // use server

    }
    The C# client instantiates the client like one of these...I've tried them all and they all fail:
    When using a PIA:
    asiDATA.asiServerClass asi = new asiDATA.asiServerClass();
    When directly referencing the .tlb file:
    asiDATA.asiServer asi = new asiDATA.asiServer();
    Another method using the ProdID:
    Type tt = Type.GetTypeFromProgID("asiDATA.asiServer");
    asiDATA.asiServer asi = Activator.CreateInstance(tt) as asiDATA.asiServer;
    Again, thanks for the help...you've spent a great deal of time with this issue.

    Tuesday, May 24, 2011 1:14 PM
  • Bio,

     

    I'm not sure why my DebugBreak() doesn't work, but I added some extra logging to my server. I can see the the ATL code 'PreMessageLoop()' returns 0x00000000 so the CoRegisterClassObjects() and CoResumeClassObjects() must be completing successfully.

     

    Also, reading back through the list of suggestions I saw your in your first response, the comment that the class factory registration may be successful under the assumption that the service starts automatically. It may be obvious by now that the class factory is correctly registered...but I wanted to be clear that the service is not configured to start automatically. In all cases during my tests, whether the exe is a service or local server, it is always started by the client request.

     

    Thanks


    Tuesday, May 24, 2011 2:24 PM
  • Trying to bump this issue as I've spent a week on it now and still have no solution.

     

    I started over with my testing.

    • I copied my working vs2005 project to a new location.
    • I opened it in vs2010, which performed the project update.
    • I built the project in vs2010 which resulted in one error - I had been using a manifest file (for UAC recognition) to merge with the generated manifest file. I removed the merge manifest file and left the rest of the options and settings in place (UAC options which weren't in vs2005 are set to:

    Enable User Account Control (UAC): "Yes (/MANIFESTUAC:)".

    UAC Execution Level: "asInvoker (/level='asInvoker')"

    UAC Bypass UI Protection: "No (/uiAccess='false')"

    • I built the project again in vs2010 with no errors.
    • .net clients fail to connect to the server's COM interface when the server runs as a local server. HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE).
    • .net clients can connect to the server's COM interface when the server runs as a service. I've tested this with the service running under the local system account and under my login account (which is admin). .net clients can connect in both cases.
    • native COM clients can connect to the server in both scenarios (as a local server and as a service).

     

    Based on logging output from the server I know that the CoRegisterClassObjects() and CoResumeClassObjects() succeed.

    I've tried many different project settings variations to no avail.

    I've created other simple COM server projects in vs2005 and updated them to vs2010 - they work correctly.

     

    Does anyone have any ideas?

    Thursday, May 26, 2011 1:33 PM
  • Hello kalprin,

     

    1. Thanks for Running the Tests.

    1.1 Sincere apologies for my late reply. Sorry to have kep you waiting. Thankyou for running the tests (esp using DebugBreak()).

    1.2 I also noted that the REGCLS_MULTIPLEUSE was used and that the clients instantiated the COM class in the usual ways.

    1.3 I also noted that the service-based COM server was not configured to run automatically. 

     

    2. Concerning the DebugBreak() statement.

    2.1 I am using Windows XP for testing. What OS are you using ? I think it might be Windows 7 which may be the source of the problem.

    2.2 Albeit I am not familiar with any restrictions on Windows 7 with regards to DebugBreak().

    2.3 Let me do some research on this.

     

    3. Recommendations.

    3.1 I read through the history of your project as listed in your last post. I concur that the class factory regiatration likely succeeded but the .NET client is somehow not able to connect with it. The problem appears to be related to security albeit I am not able to comment further on this.

    3.2 There are other ways of instantiating objects that you may like to try, see "Instance Creation Helper Functions" : http://msdn.microsoft.com/en-us/library/ms678507(v=vs.85).aspx

    But some of the techniques may require you to make changes to the COM server source codes.

    3.3 One hard alternative is to re-start the VS2010 project from scratch and ensuring success with each incremental step as you manually port over the code from VS2005.

    3.4 If time does not permit this, an laternative is to write a thin wrapper (in C++ ATL) for the COM class exposed by the original COM EXE server. The wrapper internally instantiates the actual COM class from the original server.

    3.5 Very sorry that I can't be of greater help at this time, kalprin.

     

    Best of luck,

    - Bio.

     

    Friday, May 27, 2011 5:55 AM
  • Hello kalprin,

     

    Concerning the DebugBreak() Statement Problem.

    1. I did some googling and discovered the following potential solution in case you are using Windows 7 :

    "DebugBreak not breaking"

    http://stackoverflow.com/questions/1044103/debugbreak-not-breaking

    2. It's basically a settings issue connected with the "Action Centre" in the Control Panel.

     

    - Bio.

     

    Friday, May 27, 2011 12:02 PM
  • Bio,

    Thanks for the DebuBreak() link. I googled around but never found that one. Following those steps allowed me to get my vs2010 to break into a debug session correctly...which helped tremendously!

    I can now see that the real issue seems to be one related to timing. I'm not sure why things are different when my server runs as a service vs. a local server - it executes the same startup code. If I comment out much of the configuration loading, which speeds up the time between the server starting and when it calls CoRegisterClassObjects() and CoResumeClassObjects(), the client can connect successfully. If I leave the configuration loading in place, the client gets the 0x80080005 error.

    As a test, I commented out the configuration loading and put in a 2 minute delay instead (at the same place in the code where it would have loaded the configuration). This caused the client to fail to connect with the same error. I did this for two reasons:

    1) I wanted to remove my configuration loading code to make sure nothing was causing an error during that logic;

    2) To force a long wait.

    While my configuration load doesn't normally take 2 minutes, it can take about 30 to 40 seconds when all components are built in debug.

    What might be the next steps here? Is there a way to specify a wait time for the COM interop? Is there anything I can do on the server side that I can use to signal to the client or COM subsystem that I'm still working and not to indicate any failure?

    Thanks again for your help.

     

    Friday, May 27, 2011 3:20 PM
  • More information.

    This may or may not be a timing issue. I still don't have a good handle on exactly what the cause is since I can get things to work or fail trying different scenarios. There are cases where I can get it to fail after a fairly short load; and times when the load takes longer than normal and it still works. Continuing to debug....

     

    Thanks.

    Friday, May 27, 2011 9:02 PM
  • Hello kalprin,

     

    1. On DebugBreak().

    1.1 Congratulations on being able to use DebugBreak() finally, and getting good findings :-)

     

    2. On Server Startup.

    2.1 I also did some further searching and found this blog :

    "When CoCreateInstance returns 0x80080005 (CO_E_SERVER_EXEC_FAILURE)"

    http://blogs.msdn.com/b/adioltean/archive/2005/06/24/432519.aspx

    2.2 According to the above-mentioned blog, the maximum time allowed between server startup and the server calling CoRegisterClassObject() is 120 seconds (2 minutes).

    2.3 The blog did not mention any way to configure this timeout value. I'll do some research on this.

    2.4 Here is another good read :

    "COM CoCreateInstance Timeout Error?"

    http://social.msdn.microsoft.com/Forums/en/vcmfcatl/thread/5d67686f-f84c-4032-9225-edfd11fa251d

    2.5 One other thing, kalprin : we must still pay heed to the results of the tests (see posts dated May 23 and May 24) in which we saw that even if the server has already been started up successfully (either by being run on its own or by being started up by another client), the .NET client still was not able to connect with the class factory when it ought to (after all, the server has been registered with REGCLS_MULTIPLEUSE).

     

    - Bio.

     


    Saturday, May 28, 2011 9:14 AM
  • Bio,

    Thanks again for your response.

    I've tried a few more tests and am now wondering if this is a memory corruption of some kind. When I enable a specific configuration load that allows the server to run and the client to connect, the client can connect multiple times to the same instance of the server...so that's good. I still haven't figured out what the difference is between the version of the components that I've built with vs2005 and the ones I've built with vs2010. They are the same projects, just upgraded by vs2010, so they *should* produce the same results. I will continue to investigate.

    Thanks again for your help.

    Monday, May 30, 2011 6:45 PM
  • More information.

    I built all components of my application with vs2010. I then built the main executable (which the clients connect to) with vs2005. The same clients that I've been using, which have problems connecting to the vs2010 built version, connected without problem to the vs2005 built version of the .exe. Could this be a build option that is not handled differently between vs2005 and vs2010...or a new setting in vs2010 that might be negatively affecting the resultant .exe?

    Thanks

    Monday, May 30, 2011 7:25 PM
  • Still haven't resolved this. Here's where I stand:

     

    VS2005:

    Project and all components work correctly.

     

    VS2010:

    When registered as a service:

    Project and all components work correctly...that is:

    Project and all components work with native (unmanaged) client.

    Project and all components work with managed client.

     

    When registered as a local server:

    Project and all components work with native (unmanaged) client.

    Managed clients receive the error  0x80080005 (CO_E_SERVER_EXEC_FAILURE) when trying to connect.

     

    I recently created a new VS2010 project (instead of upgrading from the VS2005 project) and moved all files to the new project. I get the same results as with previous attempts - managed clients receive error 0x80080005 when trying to connect.

     

    I've managed to get the server to partially work. When I disable part of its configuration, it will run and all clients can connect. So obviously, I began reviewing the code that loads and uses that configuration data. I found no problems, so my next step was to re-enable that configuration load and disable a different part of the configuration. That worked too! I continued to enable and disable different parts of the configuration load. Virtually everything I tried allowed the server to run and managed clients to connect as long as the full configuration was not loaded. It seems that there is no specific configuration that causes the server not to work...but when all configuration is loaded, managed clients can't connect. Overall timing is not an issue (as I had once thought) because the server starts and loads its full configuration in about 15-20 seconds. 

    Does anyone have any ideas where to go from here?

    Monday, June 13, 2011 8:20 PM
  • One possible area to think about the issue is marshaling between the COM client and server application. It seems to me that the error 0x80080005 (CO_E_SERVER_EXEC_FAILURE) is due to the marshaling of the data between managed client and server.  I think in case of unmanaged clients the data types used in client and server will be same but in case of unmanaged clients the data type may change in terms of objects like if I use Int in managed code it will be an object and allocated in heap compared to stack allocation in C++ unmanaged code.  In case of running the server as service, probably SCM may take care of proper marshaling.

     

    We'd like to see your unmanaged and managed client code to analyze in terms of marshaling between client and server calls in COM applications.

     

    To cross check this we can try exposing a couple of methods without any arguments and calling them from managed code.  


    --Trevor H.
    Send files to Hotmail.com: "MS_TREVORH"
    Monday, June 20, 2011 8:16 PM
    Moderator
  • Trevor,

    Thanks for responding.

     

    I'll be happy to send whatever you think might help. Remember though, the problem happens during the connection (or instance creation) between client and server when no method calls are being made. For example, this statement causes the exception:

     

    asiDATA.asiServer asi = new asiDATA.asiServer();

     

    (where asiDATA.asiServer is defined in the referenced type library).

     

    Also remember that this statement can succeed if the server is not fully enabled to load its entire configuration.

     

    Do you still want to see the two client projects?

     


    Monday, June 20, 2011 9:04 PM
  • -          Please collect the event viewer data (application, security and  System) if any significant events are logged when you reproduce the exception CO_E_SERVER_EXEC_FAILURE

    -          If possible please provide us the COM server dll/exe and we will try to reproduce by our own client to make sure the server component code is fine, even though the environment changes may not reproduce the same you are having. We will give a try.

    -          For your information, usually the following actions will be performed during the COM server startup

    -Checks if EXE is started as a COM server

    -Initialize COM and create class factory

    -Register class objects using CoRegisterClassObject


    --Trevor H.
    Send files to Hotmail.com: "MS_TREVORH"
    Wednesday, June 22, 2011 6:21 PM
    Moderator
  • Hello All,

    I have the same problem. I know it has worked in the past, even with a C# 'DCOM Server' but it now all fails.

    (On Windows 2003 R2 32-bit edition, however, it works!)

     

    I have a DCOM server in ATL, in the hope that the .NET Dcom server was the problem, but even the ATL DCOM Server fails.

    More info, a VBA client, or a managed client all have the same problem!

    It looks as if CoRegisterClassObject does not work at all. All clients that use either CreateObject or Activator.CreateInstance bump into launching the EXE. the exe is registered as a Windows Service!

    [2376] Ctor of CdcomModule
    [2376] WinMain
    [2376] DCOM so returnexit WinMain with 0

    this is the trace for the server being started up. It ALL works well, no errors, no HR fails

    [4068] WinMain
    [4068] starting Service Dispatches
    [4068] ServiceMain
    [4068] PreMessageLoop
    [4068] InitializeSecurity
    [4068] CoInitializeSecurity 0
    [4068] RegisterClassObjects 0

    This is running on Win64. In Win32 mode, it also fails.

    MS: I also had to use FireFox 5.0 (insterad of IE 9) to post this posting. MS what are you doing?


    Saturday, July 16, 2011 11:17 AM
  • I found the circumstance when this does not work.

     

    If you implement CAtlServiceModuleT<> and register your exe as a service with command line /Service, and you start it, Win7 and Win2008 do not really register the classobject (CoRegisterClassObject). It just launches a NEW instance of your DCOM .exe which is really forbidden if your exe is registered as a windows service.

    In Win2003 and XP it does work but on Win7 and Win2008 this functionality is broken. It ALWAYS will return with CO_E_SERVER_EXEC_FAILURE (HRESULT  0x80080005), no matter how you define security or how you correcty configure Win7 with the correct settings.

    The only workaroud is to NOT register your exe as a Service and let Windows launch the exe. Since CAtlServiceModuleT can delay the shutdown (which is good for performance instead of letting the exe kill itself if all DCOM Clients have dereffed) and also uses security (it implements CoInitializeSecurity) your 'service' is back again. The second time a call to your DCOM classs is done using a DCOM context, CoRegisterClassObject indeed redirects the call to the ClassFactory of your DCOM implementation.

     


    Sunday, July 17, 2011 8:05 PM
  • This is not the same issue.

    The problem that I have is that VS2005 and VS2010 produce different results. When using VS2005, a service built (which implements CAtlServiceModuleT<>) correctly registers and runs as a service on Windows 7. The same service built with VS2010 works correctly on Windows 7 only when used with a native (unmanaged client). When the VS2010 service on Windows 7 is used with a managed client, the client's attempt to connect to the server results in CO_E_SERVER_EXEC_FAILURE (whether the service is already running or not).

     

    Monday, July 18, 2011 2:33 PM
  • I found something interesting.

    With the VS2010 build, the server lock count never increases...it is always zero. My service is derived from CAtlServiceModuleT. There are multiple interfaces with similar implementations. One the interfaces it exposes are derived from these (plus more):

    public CComObjectRootEx<CComObjectThreadModel>,

    public CComCoClass<CasiServer, &CLSID_asiServer>, // my class

    In my stdafx.h header, I have:
    #define _ATL_FREE_THREADED
    Why would the lock count on the service module not increment when clients query interfaces?
    Thanks

    Thursday, July 21, 2011 5:27 PM
  • More interesting information:

     

    The VS2005 build uses Lock() and Unlock() methods in atlbase.h that differ from the Lock() and Unlock() methods in the VS2010 build.

    For example, the VS2005 Lock() method calls CComGlobalsThreadModel::Increment(&m_nLockCount). This keeps the m_nLockCount member up-to-date.

    The VS2010 Lock() method calls CoAddRefServerProcess(). This does not use the m_nLockCount member and so the lock count is always zero.

    Furthermore, the VS2005 ATL::_ATL_MODULE70 member called 'm_bComInitialized' is true by the time the first Lock() is called. The VS2010 ATL::_ATL_MODULE70 member 'm_bComInitialized' is never set to true.

     

    I now suspect that at least part of the client connection problems I've seen are due to either the lock count or the 'm_bComInitialized = false' problem (or some issue related to this). I'm guessing that when a client connected and the lock count stayed zero, CoSuspendClassObjects may have been called by base ATL logic which caused an error. This jives with the fact the clients could connect when the server is running as a service. The lock count going to zero doesn't suspend com objects in a service.

     

    There are still unresolved issues and things that don't fully make sense. For example, why do clients connect successfully if not all of the configuration is loaded.

    Also, the lock count that I now see (after over-riding the Lock() and Unlock() methods) isn't right. I see it increment, but the value doesn't appear to really be in the range it should be. And I don't see it decrement.

     

    If this extra information rings any bells for anyone, please let me know.

    Thanks

     

    Thursday, July 21, 2011 8:53 PM
  • I have the answer...the server lock handling was the cause.

    My server, as part of the configuration loading, creates COM objects (using CComObject<>::CreateInstance) and later releases them. The creation of the COM objects incremented the server's lock count, and the release of the COM objects decremented the server's lock count. By the time the server was completely loaded, the lock count had dropped to zero - which began the suspend/revoke logic for the server's interfaces. This happened immediately after the PreMessageLoop() over-ride, so after the startup finished the revoke began and the client application received the CO_E_SERVER_EXEC_FAILURE error.

    When I commented out part of the configuration load, it worked because the COM objects for that part of the configuration were created but not destroyed.

    When I ran the server as a service it worked because services are stopped by the SCM, not by the lock count going to zero.

    The interesting thing here is that the behavior is different between the VS2005 and VS2010 builds. The ATL code has changed between the two versions so the shutdown logic must be triggered differently (I didn't go that far into it, but maybe a default delay period has changed?).

    To fix the problem, I increment the server's lock count by one before loading the configuration and keep that lock until all other locks have been released.

    • Marked as answer by kalprin Sunday, July 24, 2011 6:02 PM
    Sunday, July 24, 2011 6:02 PM