Side-by-Side Manifest Contents - Complete Example | quick guide | home |
Windows Side-by-Side allows a manifest to reference any number of other manifests. One major restriction is that definitions inside these manifests must not conflict. Once all manifests are collected together and loaded into memory, Windows verifies that there are no duplicate definitions of files, COM classes, type libraries, progid's and other. There may be many references to any particular name, but there must be only one definition.
This approach allows us to organize our Side-by-Side project. By default, when you build an 'automatic' project, Manifest Maker puts all DLLs in a subdirectory and creates an accompanying manifest. These DLLs with this manifest make a Win32 Side-by-Side assembly. The assembly is put in a subdirectory named after the assembly. This name must not be changed or Windows will not find the assembly.
Subsequently, Manifest Maker creates a manifest for each executable in the project. These manifests must be located in the same folder as the corresponding executables. Each of these manifests contains a reference to the shared assembly created for this project.
If you did not read Step-by-Step - Inside a Manifest you may wish to read it now.
As Windows loads the application manifest and all manifests referenced by the application manifest (and, recursively all manifests referenced from these manifests...), it builds a list of all items described by these manifests. This is called the Activation Context. As soon as reading of the manifests is finished, we stop talking about manifests and start talking about the Activation Context. So, for example, XML well-formedness (this is actual W3C terminology) of manifest files is checked on a manifest but uniqueness of file names is checked on Activation Context.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="program.exe"
version="1.0.0.0"
type="win32"
processorArchitecture="x86"/>
<dependency>
<dependentAssembly>
<assemblyIdentity name="My.Example.Project" version="1.0.0.0" type="win32" processorArchitecture="x86"/>
</dependentAssembly>
</dependency>
</assembly>
As you can see this manifest, in addition to the manifest identity, contains a reference to assembly My.Example.Project. As you look at other application manifests, you will notice that they are almost exactly the same. Only the program name and, possibly, version are different.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="My.Example.Project"
version="1.0.0.0"
type="win32"
processorArchitecture="x86"/>
<file name="sampleDLL.dll"/>
<file name="sampleDLL-2.dll">
<comClass clsid="{4D880EAB-BF35-423A-A859-B1D9F2AC4CC1}"
description="CsxsSampleControl Object"
tlbid="{4EAA16D5-3C31-441D-B58D-E11037452ADF}"
threadingModel="apartment"
progid="sampleDLL.sxsSampleControl.1">
<progid>sampleDLL.sxsSampleControl</progid>
</comClass>
<typelib tlbid="{4EAA16D5-3C31-441D-B58D-E11037452ADF}"
version="1.0"
helpdir=""
flags="hasdiskimage"/>
</file>
<comInterfaceExternalProxyStub iid="{8EFCBB0D-5736-4EB4-BF65-013DC6A4D0BD}"
name="IsxsSampleControl"
tlbid="{4EAA16D5-3C31-441D-B58D-E11037452ADF}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/>
</assembly>
The first line, <?xml ...?> is a standard XML way of introducing an XML file.
The next line, <assembly ...> is the root tag in the manifest. It describes the namespace and version of this manifest.
The <assemblyIdentity> tag contains the name of the
assembly.
You can find more information in Step-by-Step - Inside
a Manifest.
The <file> tag describes a file. In addition to the name of the file it contains the description of COM objects implemented in this file:
| Name | Identifier | Contents |
|---|---|---|
| <file> | name= | name of the file, no path |
| <comClass> | clsid= | list of all COM classes |
| progid= | n/a | version independent ProgID |
| <progid> | tag text | list of all version dependent and other ProgID's |
| <typelib> | tlbid= | type libraries defined in this DLL |
| <comInterfaceExternalProxyStub> | iid= | COM interfaces - IIDs, type libraries and proxies |
There can be any number of the above elements in the manifest and in the
activation context as long as there are no conflicts. Conflicts are normally
caused by duplicate element identifiers.
This is important to understand: there can be multiple
references to identifiers but identifier definitions must be unique.
In short: definitions must be unique,
references need not be.
The above table names element identifier definitions. Note that the <progid> element is identified by the text inside the <progid></progid> pair of tags. Because of that, the name must not include any surrounding white space and both tags and the text must all be in the same line.
To make things more complicated, ProgID's are defined in both the <progid> element and in the progid= attribute of the <comClass> tag. Consequently there must be no duplicate progids in all instances of the two above places.
The first file above, sampleDLL.dll, has nothing defined inside the <file> tag. This may look like a superfluous definition, but it is not. While this file will not be used by COM (there are no COM objects defined in it) it will still be used by the LoadLibrary API call. Note that all LoadLibrary-related APIs eventually call LoadLibraryExW - this is where the side-by-side logic is implemented.
It is important to remember that Windows has a strict rule regarding loading DLLs: if the DLL name passed to any of the LoadLibrary* APIs contains a path, even a partial path, Windows will not search for the DLL. It will try the path as requested and quit. If the DLL name contains no path, Windows will try the activation context first then the standard Windows places (application directory, system directories, path etc.)