SxS Managed COM With Manifest Resource (WinXP and Win2K3)


This article is now superseded by the “Registration-Free Activation of .NET-Based Components: A Walkthrough” MSDN article. Please see the MSDNography links section.

Comments (15)

  1. jason buxton says:

    Steve – thanks so much for putting this out! But my environment is almost exclusively VB6 apps that need to interop with .NET assemblies. I’m prepared to forge ahead and hack out a VB client, but do you have any tips before I start?

  2. Steve White says:

    Like the steps above show, I’d recommend you first get your interop working in the normal case where your typelibrary is registered. In step 4 create a VB6 app, reference the .tlb generated when you registered your .NET assembly for COM Interop and use it as normal. If you can get to step 5 (and this is nothing to do with SxS yet) then the remaining steps will apply to a VB6 app, which is of course native, just as they do to the console app. The only difference between your VB6 client and my console app is how they initialise COM. My console app is MTA, your VB6 app will be STA. With SxS if client/server aren’t in compatible apartments then you have to put an extra section in your assembly manifest:

    <comInterfaceExternalProxyStub

    name="ISxSCPPSTABlue"

    iid="{4992BDCD-18E3-4907-89C8-5A6F57787820}"

    proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"

    numMethods="1"

    baseInterface="{00000000-0000-0000-C000-000000000046}"

    tlbid = "{E04C5ACA-356B-4D47-9A02-532D92BEAAE5}"

    />

    The above defines IDispatch so is appropriate for VB6. Just change the name and IID attributes above.

    Alternatively, make sure your .NET assembly runs in an STA with an STAThreadAttribute. When I get chance I’ll cover these situations in docs.

  3. jason buxton says:

    Okay, I’m sheepish but not too proud to ask: from where do I derive the ‘name’ and ‘iid’ attributes in my case?

  4. Steve White says:

    I’d say first try the route of building your .NET assembly as STA first. If that won’t fly then come back here. 🙂

    So, the reason you need the comInterfaceExternalProxyStub element is the same reason you need the manifest file – i.e. to supply the COM runtime with the information it would otherwise get from the registry. In this case the information is how to marshall interfaces between the client’s apartment and the server’s apartment. If these are compatible then you don’t need this element whic is why I suggest building the .NET app as STA.

    The ‘name’ attribute is the name of the interface(s) which you wish to use on your .NET class. The ‘iid’ attribute is the IID of this interface. I forgot to say that you’ll also need to set the ‘tlbid’ attribute which is the LIBID of the .tlb which describes your .NET classes. How do you find these values? I’d say the best thing is to use Guid attributes in your .NET classes so you know up front what the IID and LIBID will be. Failing that, there’s the OLE/COM Object Viewer. The object viewer in VB6 may also give this info, but if not then search for the OLE/COM Object Viewer.

    Hope that helps.

  5. jason buxton says:

    Well…. I truly can’t travel the path of making my .NET assembly single-threaded, so I aimed straight at the next option, and I’m pretty sure I missed.

    Ever heard of the law of leaky abstractions (http://www.joelonsoftware.com/articles/LeakyAbstractions.html)? You’re dealing with an individual who’s unfamiliar with the lower-level operations of the code I write. So that’s why I keep giving you the blog equivalent of a blank stare when you try to help me – sorry!

    Would it be inappropriate for me to paste the contents of OLEViewer into these comments, so you could see specifically what I’m working with? That’s about the only way I see for us to get on the same page…

  6. Steve White says:

    Sure, go for it.

  7. Steve White says:

    It looks like .NET assemblies registered for COM are Both-threaded which means no marshalling takes place whether the object is called from an MTA or an STA. So your VB client, calling from an STA, will be fine with the assembly manifest as I first showed it, i.e. no need for the extra comInterfaceExternalProxyStub element.

    I’d say go ahead with my original set of steps and just build a VB6 client instead of a C++ one. For reference, I rebuilt my C++ client but made it STA (as VB is) and it worked without changing the manifest.

    Cheers,

    Steve

  8. jason buxton says:

    Steve –

    It’s not working…. I’ve followed the steps you outlined and the best I can get is what I had before. I run the VB6 executable, and get a messagebox that says this:

    "This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem."

    That’s about all I can get. Would it be worthwhile for you to see the three objects (EXE, Manifest and DLL)?

  9. Steve White says:

    There are multiple possible points of failure in getting SxS to work, most resulting in the error message you quote. For example if you omit #include <windows.h> in step 10, you’ll see it.

    What I suggest is two things. First, do your experiments on Win2K3 and check the System event log. Win2K3 gives better messages than XP’s which are unhelpful. Second, I really urge you to get a functioning frame of reference for SxS by following the steps given in this article. Get some practice in what does and doesn’t work before we ‘move the goalposts’ by moving to VB6. You see, I only have the proofs published here, I have no proofs involving VB6. I do plan to do that work in due course, but I’m maxed out right now. Another option for you is to raise a case with MS Product Support.

    I do sympathise with your frustration – getting this far has been a struggle for me. But I will get round to VB6 in time and I intend to cover it in the eventual MSDN article.

  10. jason buxton says:

    Thanks for your patience and diligence, Steve. I’m going to have to wait for the MSDN article; I’m rather busy as well, which is why I’ve been asking you to fit a square peg in a round hole, rather than buck up and learn rudimentary C++.

    For the record, though – the #include <windows.h> isn’t relevant to a VB project anyway, right? I see other #includes in the file itself, which would mean those files would have to be there in order for the build.cmd file to execute successfully…

    Thanks again, and good luck on the article.

  11. Steve White says:

    > the #include <windows.h> isn’t relevant to a VB project anyway, right?

    So, you said initially "my environment is almost exclusively VB6 apps that need to interop with .NET assemblies." The only step in this article which is potentially relevant to VB6 is step 4. To make VB6 relevant you’d create a VB6 app instead of a C++ app in step 4, reference the .tlb generated when you registered your .NET assembly for COM Interop and use it as normal.

    All the other steps *have to be done as written*. The build.cmd file is to build your .NET assembly. So although #include <windows.h> isn’t relevant to VB6, it is relevant to this article and it’s not one of the bits which are replaced by replacing the C++ client with a VB6 client.

    I mentioned the #include <windows.h> as an example of something which, if forgotten, will prevent the experiment from working.

    As I said before, If you can get to step 5 (and this is nothing to do with SxS yet) then the remaining steps will apply to a VB6 app.

  12. jason buxton says:

    Sorry to produce a red herring with my comment regarding relevance.

    I’ll see what I can do about locating all the files necessary to support the #include, and will run the experiment again. I’ll keep you posted on how it goes. Thanks for sticking with me.

  13. Steve White says:

    This article is now superseded by the "Registration-Free Activation of .NET-Based Components: A Walkthrough" article. That article answers the questions raised in the comments.