Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reg free COM interop with C#, possible?

Is it possible to use registration free COM with Dotnet interop and C#? If so how does one add a reference to the COM object in the C# project?

I have a reg free ATL COM server dll with an embedded manifest and two test clients, one cpp the other c#. The cpp client correctly references the COM object using an import statement and either

#pragma comment(linker, "\"/manifestdependency:type='win32' name='TestComSvr2' version='1.0.0.0'\"")

or setting 'Additional Manifest Dependencies' to "type='win32' name='TestComSvr1' version='1.0.0.0'" under Linker->Manifest File options, after which the cpp client will run correctly just so long as the COM component is in the same directory.

The c# client though refuses to play at all.

Attempting to add a file reference to either the unregistered COM component dll or unregistered tlb results in the error:

"A reference to 'blah blah' could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component".

Registering just the type library with 'regtlib TestComSvr' and then creating either a file or COM reference to that results in the c# project failing to build with:

"Error loading type library/Dll. (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY))".

Registering the COM component and creating a reference normally in the c# project, setting the reference to Isolated, building the c# project then unregistering the component and running the c# project results in this exception:

Retrieving the COM class factory for component with CLSID {B1D0A80F-0050-4856-BACD-87D664E58CBE} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

Note: Even if this worked it wouldn't be a useful case anyway, since ultimately it still requires registration of the component, I just tested it for thoroughness.

So far the only way I've been able to reference the COM object from C# at all is by registering the COM object itself, which of course utterly defeats the point since then it isn't reg-free at all.

Anyone got any ideas?

(This is on WinXP with VS2010 sp1).

like image 458
Neutrino Avatar asked Mar 06 '12 14:03

Neutrino


1 Answers

You need to:

  • add the registration free COM entries to your assembly manifest xml file, and
  • build that manifest into your C# executable.

  1. You need to come up with your registration-free COM assembly manifest, where you state your dependancy on Neutrino.TestComSvr2 assembly:

    <?xml version="1.0" encoding="utf-8"?>
    <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" 
                xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" 
                xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    
       <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
    
       <!-- We depend on our COM object -->
       <dependency>
          <dependentAssembly>
              <assemblyIdentity type="win32" name="Neutrino.TestComSvr2" version="1.0.0.0" />
          </dependentAssembly>
       </dependency>
    
    
       <!-- 
           Everything else in this sample manifest is not relavent to this answer, 
           but every developer should be doing their job and writing correct 
           Windows programs 
       -->
    
       <!-- Disable file and registry virtualization. -->
       <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
          <security>
             <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="false" />
             </requestedPrivileges>
          </security>
       </trustInfo>
    
       <!-- We are high-dpi aware on Windows Vista -->
       <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
          <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
             <dpiAware>true</dpiAware>
          </asmv3:windowsSettings>
       </asmv3:application>
    
       <!-- Declare that we were designed and tested on Windows 7-->
       <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
          <application>
              <!--The ID below indicates application support for Windows 7 -->
              <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
              <!--The ID below indicates application support for Windows Vista -->
              <!-- supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/ -->
          </application>
       </compatibility>
    
       <!-- We depend on Common Controls version 6 (i.e. "enable themes") -->
       <dependency>
          <dependentAssembly>
             <assemblyIdentity
                   type="win32"
                   name="Microsoft.Windows.Common-Controls"
                   version="6.0.0.0"
                   processorArchitecture="*"
                   publicKeyToken="6595b64144ccf1df"
                   language="*"
             />
          </dependentAssembly>
       </dependency>
    

    Note: i had a similar manifest in my question Registration-Free COM from ASP.NET?

  2. Then you need to include this application manifest in your C# exe:

    1. Right-click on the project in the Solution Explorer.
    2. Click "Add New Item".
    3. Select "Application Manifest File".

These steps are similar to what can be found on MSDN for adding a manifest to a managed application.

You also need to ensure that your Neutrino.TestComSvr2 assembly contains it's registration-free COM entries:

Neutrino.TestComSvr2.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

   <assemblyIdentity type="win32" name="Neutrino.TestComSvr2" version="1.0.0.0" />

   <file name = "ContosoFrobber.dll">

      <comClass
            progid="Frobber.Gizmo"
            clsid="{00028C00-0000-0000-0000-000000000046}"
            description="Gizmo Frobber by Contoso"
            threadingModel = "Apartment" />

      <typelib 
            tlbid="{00028C01-0000-0000-0000-000000000046}"
            version="1.0" 
            helpdir=""/>
   </file>
</assembly>

And blingo blango, you should be working.

like image 55
Ian Boyd Avatar answered Oct 04 '22 16:10

Ian Boyd