Registry-free COM
Traditionally, the COM should be registered into registry, by building process or explicitly by execute regsvr32 com.dll command. However, Microsoft has another convenient mechanism to call COM: registry-free COM. Briefly, it uses *.manifest to declare the information which were stored in the registry. You can get more detailed information on msdn:
http://msdn.microsoft.com/en-us/library/ms973913.aspx
I tried to play with it, here is what I got:
If we want to transform registry based COM to registry-free COM, firstly we should make sure that registry based COM works well, then use regsvr32 �Cu com.dll to unregister from the registry, and the client code should not work without registry support. And then write some manifest file to specify the application/assembly dependency. Actually, most of them, we don’t need to write the manifest file from scratch. The building can generate manifest for us, we just need to some of them.
A.
If it’s the COM vcproj, we just need to go to: vcproj property dialog->Manifest Tool->Isolated COM to specify the Type Library File and Component File Name (actually it’s dll name) which are generated after compiling. Then it will generate COM interface, class and type library related information to the manifest file. We can use the manifest file, then do further modification in Step C in future. (Usually, we just need to add the AssemblyIdentity to the beginning of the manifest file). This way, we can avoid manually write most of the COM dll manifest, copy/paste the interface/class/typelib guild.
Note, it seems that we can’t just specify one of these 2 settings. We should specify both of them.
B.
If it’s the client project, a default manifest is generated after building. Then use that manifest, and rename it from Client.exe.embed.manifest to Client.exe.manifest, copy it to the directory where the exe resides. Then do further modification: Add the COM dll dependency, just like below:
<
dependency
>
<
dependentAssembly
>
<
assemblyIdentity
type
=
"win32" name="SimonATLSample.X" version="1.0.0.0" />
</
dependentAssembly
>
</
dependency
>
Here, SimonATLSample.X is the dependency COM Dll identity, from my understanding, we can name it anything we want. Here, I just append the X to it.
Client.exe.manifest is the application manifest.
C.
Copy the COM dll manifest to the same directory, rename it to the assemblyIdentity in Step B.(SimonATLSample.X). Add edit the SimonATLSample.X.manifest
We just add assemblyIdentity element to the beginning of the manifest file.
<assemblyIdentity
type = "win32"
name = "SimonATLSample.X"
version = "1.0.0.0" />
And note, there is the file element. We can specify the dll path for the COM dll. It means that we can place the COM Dll anywhere we want, we just specify the path here. Here, I put the SimonATLSample to ComDll sub-directory.
SimonATLSample.X.manifest is the assembly manifest.
<
file
name
=
"ComDll\SimonATLSample.dll" hashalg="SHA1">
<
comClass
clsid
=
"{75AD0D34-2D47-4B5A-B21E-49BBADC98E69}" tlbid="{587A0882-5469-4D50-BF8D-F6F4384426A2}" description="SimonMathUtil Class" />
<
typelib
tlbid
=
"{587A0882-5469-4D50-BF8D-F6F4384426A2}" version="1.0" helpdir="" flags="HASDISKIMAGE" />
</
file
>
D.
Then start the client exe, it should work fine, just like registry based COM.
E.
And I did a further test, if A.exe calls B.dll, in B.dll, it tries to call the registry-free COM, we can’t just use B.dll.manifest to do that, we still need A.exe.manifest. If we don’t really want A.exe.manifest, the separate file, we can also embed the manifest into the exe file by the VS setting(Manifest Tool->Input and Output->Additional Manifest File)
F.
And if we want to use the manifest more dynamically, we can use the Context Activation API, just like below:
HANDLE hActCtx;
ULONG_PTR ulpCookie;
ACTCTX ActCtxToCreate;
// This is very important to set all other members to zero!!!
memset((void*)&ActCtxToCreate, 0, sizeof(ACTCTX));
ActCtxToCreate.cbSize = sizeof(ACTCTX);
ActCtxToCreate.lpSource = _T("D:\\Code\\SimonATLSampleTest\\debug\\Rename_SimonATLSampleTest__.exe.manifest");
hActCtx = CreateActCtx(&ActCtxToCreate);
if(ActivateActCtx(hActCtx, &ulpCookie))
{
TestCOM();
DeactivateActCtx(0, ulpCookie);
}
ReleaseActCtx(hActCtx);