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 https://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!
Comments
Anonymous
April 14, 2007
Pardon my ignorance but is there such a tool for native (non .Net) COM servers?Anonymous
April 14, 2007
Sorry I don't know.Anonymous
April 15, 2007
Hi, thanks very much for the tool. Would you be able to let me know where I could find CoCreate and DumpManifest? Thanks PatrickAnonymous
April 30, 2007
The comment has been removedAnonymous
May 01, 2007
In my last article , I briefly discussed how COM, Sxs and CLR work together to make registration freeAnonymous
May 03, 2007
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?Anonymous
May 12, 2007
MSN I NIIPET <a href="http://msn.com">MSN</a>Anonymous
May 22, 2007
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!Anonymous
June 22, 2007
The comment has been removedAnonymous
June 22, 2007
tcassisi, Yes, CLR uses the process default ACTCTX instead of the current ACTCTX.Anonymous
June 26, 2007
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?Anonymous
June 26, 2007
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.