New assembly search behaviour
Topic Using .Net (CLR Managed) Classes in Win32 Applications described the default .Net assembly search order. This description is based on the official Microsoft documentation Assembly Searching Sequence on MSDN and actual experiments in Windows and Windows Server. However Windows 7 seems to have changed this behaviour. There is no mention of it on the Microsoft web site but now Windows continues looking for the manifest even after it finds the DLL with no manifest. Here is example Process Monitor log (some lines removed for readability):
csrss.exe QueryBasicInformationFile D:\Sandbox\NestedCalls\_Debug\DotNetProgram.exe.manifest SUCCESS csrss.exe QueryOpen D:\Sandbox\NestedCalls\_Debug\ComServerDll.dll SUCCESS csrss.exe CreateFile D:\Sandbox\NestedCalls\_Debug\ComServerDll.dll SUCCESS csrss.exe CreateFileMapping D:\Sandbox\NestedCalls\_Debug\ComServerDll.dll SUCCESS csrss.exe CloseFile D:\Sandbox\NestedCalls\_Debug\ComServerDll.dll SUCCESS csrss.exe QueryOpen D:\Sandbox\NestedCalls\_Debug\ComServerDll.manifest SUCCESS csrss.exe CreateFile D:\Sandbox\NestedCalls\_Debug\ComServerDll.manifest SUCCESS csrss.exe ReadFile D:\Sandbox\NestedCalls\_Debug\ComServerDll.manifest SUCCESS csrss.exe CloseFile D:\Sandbox\NestedCalls\_Debug\ComServerDll.manifest SUCCESS
Notice that Windows finds the DLL, maps the DLL to memory then drops the DLL and opens the manifest file. This is further illustrated by the corresponding log from sxstrace.exe:
================= Begin Activation Context Generation. Input Parameter: Flags = 0 ProcessorArchitecture = AMD64 CultureFallBacks = en-US;en ManifestPath = D:\Sandbox\NestedCalls\_Debug\DotNetProgram.exe.Manifest AssemblyDirectory = D:\Sandbox\NestedCalls\_Debug\ Application Config File = ----------------- INFO: Parsing Manifest File D:\Sandbox\NestedCalls\_Debug\DotNetProgram.exe.Manifest. INFO: Manifest Definition Identity is DotNetProgram.exe,processorArchitecture="x86",type="win32",version="188.8.131.52". INFO: Reference: ComServerDll,processorArchitecture="x86",type="win32",version="184.108.40.206" INFO: Reference: DotNetClassLibrary,type="win32",version="220.127.116.11" INFO: Resolving reference ComServerDll,processorArchitecture="x86",type="win32",version="18.104.22.168". INFO: Resolving reference for ProcessorArchitecture x86. INFO: Resolving reference for culture Neutral. INFO: Applying Binding Policy. INFO: No binding policy redirect found. INFO: Begin assembly probing. INFO: Did not find the assembly in WinSxS. INFO: Attempt to probe manifest at D:\Sandbox\NestedCalls\_Debug\ComServerDll.DLL. INFO: Attempt to probe manifest at D:\Sandbox\NestedCalls\_Debug\ComServerDll.MANIFEST. INFO: Manifest found at D:\Sandbox\NestedCalls\_Debug\ComServerDll.MANIFEST. INFO: End assembly probing.
The same behaviour applies to the search for a COM manifest in a COM DLL and to the search for a CLR manifest in a .Net DLL.
Make sure to not confuse CLR win32 manifest with .Net assembly manifest. The same .Net DLL may have both manifests: one used in unmanaged COM access and the other by managed assembly loader (Fusion loader).
Recommendation for Manifest Maker users
Microsoft still recommends embedding the manifest as a #1 resource in the corresponding DLL. In some cases, like corporate deployment scenarios, this is not a convenient or, sometimes not even a viable, solution. For most cases developers are faced with, this will work and will get the desired results.
Manifest Maker now has new command line options that make embedded manifests considerably simpler; the new /com, /clr, /dll and /exe options simplify common scenarios.
See Command Line Manifest Builder for the complete list of command line options and Using Manifest Maker with Visual Studio and MSBuild for more on using Manifest Maker with Visual Studio.