Genman32 – A tool to generate Sxs manifest for managed assembly for Registration Free COM/.Net Interop


Attached to this article is GenMan32, a tool to generate sxs manifest for managed assembly to use in registration free COM/.Net Interop scenario.


(For more information about registration free COM/.Net interop, please read http://blogs.msdn.com/junfeng/archive/2006/05/17/595140.aspx.)


GenMan32 uses reflection API to enumerate all the types in the assembly. For each type, if it requires registration (as determined by System.Runtime.InteropServices.RegistrationServices.TypeRequiresRegistraton), depending on what kind of type it is, the tool generates either a clrClass element, or a clrSurrogate element.


For most basic scenarios, the sxs manifest generated by the tool is sufficient. For more complex scenarios, we may have to edit the generated manifest file before add the manifest to the assembly.


Here is the usage of the tool.


D:\tools>genman32


Microsoft (R) .NET Framework Win32 Manifest File Generation Utility 2.0.60120.0


Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.


 


Syntax: GenMan32 AssemblyName [Options]


Options:


    /add                     Add manifest file to the assembly as a resource.


                             If /manifest option is provided, use the filename a


s input.


                             Otherwise generate one from the assembly.


    /remove                  Remove an embedded manifest from the assembly.


    /replace                 Replace embedded manifest with new manifest.


                             New manifest is specified by /manifest option.


    /manifest:filename       Specify the manifest file to add or replace.


                             Used together with option /add or /replace.


    /typelib                 Generate typelib and record all the interfaces in


                             manifest. This option cannot be used with interop


                             assemblies.


    /reference:filename      Specify the dependency of the assembly. To specify


                             multiple dependencies, specify the /reference optio


n multiple time.


    /asmpath:directory       Look for assembly references here.


    /out:filename            Generate manifest. If filename is omitted, the


                             manifest is generated as AssemblyName.manifest.


    /nologo                  Prevents GenMan32 from displaying logo.


    /silent                  Silent mode. Success messages not displayed.


/? or /help              Display this usage message.


 


We can use the tool to generate a Sxs manifest for managed assembly.


 


D:\tools>more testlib.cs


using System;


using System.Runtime.InteropServices;


 


[ComVisible(true)]


public class TestClass


{


    public void TestAPI()


    {


    }


}


 


[ComVisible(true)]


public struct TestStruct


{


    int testField;


}


 


D:\tools>genman32 testlib.dll /out:1.man


Microsoft (R) .NET Framework Win32 Manifest File Generation Utility 2.0.60120.0


Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.


 


Win32 Manifest file D:\tools\1.man is created successfully


                   


Let’s look at the generated manifest.


 


D:\tools>more 1.man


<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>


<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>


    <assemblyIdentity


        name=”testlib”


        version=”0.0.0.0″


        processorArchitecture=”MSIL” />


    <clrClass


        clsid=”{ED653D53-DA9A-35A8-B16E-6C8704AC432D}”


        progid=”TestClass”


        threadingModel=”Both”


        name=”TestClass”


        runtimeVersion=”v2.0.50727″>


    </clrClass>


    <clrSurrogate


        clsid=”{D250790F-F50A-33FD-990F-FF5DC3E26E9B}”


        name=”TestStruct”>


    </clrSurrogate>


    <file name=”testlib.dll”>


    </file>


</assembly>


 


We can also use this tool to add the manifest to the managed assembly.


 


D:\tools>genman32 testlib.dll /add /manifest:1.man


Microsoft (R) .NET Framework Win32 Manifest File Generation Utility 2.0.60120.0


Copyright (C) Microsoft Corporation 1998-2004.  All rights reserved.


 


Win32 Manifest added to assembly ‘D:\tools\testlib.dll’ successfully


 


We can verify the manifest is indeed successfully embedded to the managed assembly.


 


D:\tools>dumpmanifest -f testlib.dll 1


<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>


<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>


    <assemblyIdentity


        name=”testlib”


        version=”0.0.0.0″


        processorArchitecture=”MSIL” />


    <clrClass


        clsid=”{ED653D53-DA9A-35A8-B16E-6C8704AC432D}”


        progid=”TestClass”


        threadingModel=”Both”


        name=”TestClass”


        runtimeVersion=”v2.0.50727″>


    </clrClass>


    <clrSurrogate


        clsid=”{D250790F-F50A-33FD-990F-FF5DC3E26E9B}”


        name=”TestStruct”>


    </clrSurrogate>


    <file name=”testlib.dll”>


    </file>


</assembly>


 


Let’s prove ourselves that this is indeed working.


 


CoCreate.exe simply calls CoCreateInstance. If it fails, CoCreate.exe prints an error message, else it prints success.


 


D:\tools>more cocreate.exe.manifest


<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>


<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>


<assemblyIdentity


    name=”CoCreate”


    version=”0.0.0.0″


    type=”win32″/>


</assembly>


 


D:\tools>cocreate {ED653D53-DA9A-35A8-B16E-6C8704AC432D}


Error: CoCreateInstance({ED653D53-DA9A-35A8-B16E-6C8704AC432D}) failed with hr=


0x80040154.


 


Let’s add TestLib to CoCreate.exe’s dependency.


 


D:\tools>more cocreate.exe.manifest


<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>


<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>


<assemblyIdentity


    name=”CoCreate”


    version=”0.0.0.0″


    type=”win32″/>


<dependency>


    <dependentAssembly>


    <assemblyIdentity


        name=”testlib”


        version=”0.0.0.0″


        processorArchitecture=”MSIL” />


    </dependentAssembly>


</dependency>


</assembly>


 


D:\tools>cocreate {ED653D53-DA9A-35A8-B16E-6C8704AC432D}


Success!


 


Good job!

GenMan32.zip

Comments (12)

  1. wpSlider says:

    Pardon my ignorance but is there such a tool for native (non .Net) COM servers?

  2. Sorry I don’t know.

  3. Patrick Wolf says:

    Hi,

    thanks very much for the tool. Would you be able to let me know where I could find CoCreate and DumpManifest?

    Thanks

    Patrick

  4. ppetree says:

    An OLD problem and I’m trying to find out how to isolate and kill it!

    Before you run off screaming! LOL I would appreciate any help you can give.

    First-chance exception at 0x7c943345 2090087237 in sasyserv.exe: 0xC0150010:3222601744 The activation context being deactivated is not active for the current thread of execution.

    I read your article SXS Activation Context which addresses this specific error BUT I am at a complete loss as to how to track down the source of the error.

    I have a main thread which works fine all on its own.  I have a seperate thread which reads/writes a named pipe.  Main thread uses WaitForSingleObject and I/O thread uses WaitForMultipleObjects and ResetEvents (thrice).  When the I/O thread completes one full read/write cycle the main thread (apparently) throws this error on a call to WaitForSingleObject()… and the handle passed is validated.

    Huh? I’m not sure how ActivateActCtx/DeactivateActCtx. and this tool fits into all this but I am certainly getting the error and you are apparently the only source of info! LOL

    Please throw me a little help!

    Thanks,

    Phil

  5. In my last article , I briefly discussed how COM, Sxs and CLR work together to make registration free

  6. lee yuan says:

    You did a good job! I have a dream —–working in the Microsoft company,but I can’t make it.junfeng zhang? have you come from xinyu city jiangxi province of China?

  7. J says:

    Hi, I came across your article entitled "When AssemblyResolve handler meets AssemblyResolve handler."  I wasn’t sure how else to contact you except in this comment section.  I am currently having that problem that you described in that article, where Assembly::Load is getting called over and over until eventually, I get a stack overflow exception.  I guess my question is how do I correctly load an assembly needed by the application?  I have 2 applications (client and server) and I am trying to serialize an object in one application and deserialize the object in the other.  The trouble is in deserializing; hence, I am subscribing to the ResolveEventHandler and it is causing me to have the afforementioned problem.  Any help or advice is greatly appreciated.  I am using .NET 2.0 and programming in C++.  Thanks!  

  8. tcassisi says:

    Assume this setup:

    1. F1/Managed.DLL

    Expose the minimum COM class then:

    Run the utility on this, then use it or MT.EXE to embed the manifest.

    2. F1/Native.DLL

    Consume the "Managed.DLL":

    Inside this manifest, refer to "Managed" as the assembly identity et al.

    3. F2/NativeHost.EXE

    This has NO manifest nor can it be changed (think any Microsoft Office component here).

    It consumes a native COM class within "F1/Native.DLL".

    Now during the DllMain of the Native.DLL, you record the ACTCTX, then activate it within the COM class that is about to try to instantiate the COM class in the Managed.DLL.

    At this point, CLSIDFromProgID() works fine when subsequently requesting the "F1/Managed.DLL" COM Class and the NT Registry is indeed not touched.

    However, CoCreateInstance() will fail with "File not found".

    Tracing shows that:

    a) the manifests are all parsed correctly by the native SxS

    b) the CLR is correctly loaded

    c) the CLR tries to load "F2/Managed.DLL" instead of "F1/Managed.DLL".

    Is it intentional that the CLR Loader ignores the current ACTCTX when setting the Probing root folder?

    This is an inconsistency since SxS *does* correctly handle chaining (including explicit ACTCTX switching) in the 100% Native case, and is doing it’s job here.

    It is the CLR that seems to be unaware of the ACTCTX and just uses the Host process path (F2/) as the root.

    Are there any addition attributes within the manifest that could be added to make the CLR use the correct ACTCTX?

    Or any SxS or CLR calls that might correct this?

  9. tcassisi,

    Yes, CLR uses the process default ACTCTX instead of the current ACTCTX.

  10. tcassisi@tovica.com says:

    Is the CLR explicitly requesting the ACTCTX using SxS and is there one process-wide default, or is it technically associated with each thread on creation, or a combination of the two?

    That is, can I either override it, or can I add/change it prior to my CoCreateInstance() call?

    When you get a moment, it would be great if you could add to your blog to explain why this is the case (is it a bug, or…?).

    Also, any hints as to what the undocumented attributes in the manifest do would be great (e.g. the loadFrom).

    And perhaps make clear that the .NET manifest your tool for produces for a DLL must be embedded in the DLL (if the trick of moving the details to the EXE manifest is not used) or it will not work when consumed by native SxS – (I believe this is due to a design flaw in the .NET loader that conflicts with the rules of the native SxS loader regarding the naming of the manifest file vs the name of the CLR binary assembly file?)

    Any ways around this would be great, for example, does the .NET loader allow the name of the assembly to be specified separately?

  11. tcassisi,

    When you call CreateActCtx, you may use the flag ACTCTX_FLAG_SET_PROCESS_DEFAULT to set your activation context to be the process default.

    It does not work when the process has already a process default activation context. But otherwise it should be good.