I am having a problem where my user control does not find a specific referenced assembly at runtime.
I am extracting the referenced assemblies at run time from embedded resources, but this is the only assembly that somehow the user control is looking for before it can be extracted, so it cannot find it.
Why is it that the application does not wait for the instance of the assembly to be created to look for it ?
I am trying to understand.
Why does this assembly fall into the “pre-bind” category ?
Fusion Log below
*** Assembly Binder Log Entry (8/15/2012 @ 8:55:28 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\Temp\gn\WPFDemo\bin\Debug\WPFDemo.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = xxxx
LOG: DisplayName = AVX.NET, Version=1.2.0.1551, Culture=neutral, PublicKeyToken=4300bc540bfb680e
(Fully-specified)
LOG: Appbase = file:///C:/Temp/gn/WPFDemo/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = WPFDemo.exe
Calling assembly : Test, Version=1.0.6.39680, Culture=neutral, PublicKeyToken=4300bc540bfb680e.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Temp\gn\WPFDemo\bin\Debug\WPFDemo.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: AVX.NET, Version=1.2.0.1551, Culture=neutral, PublicKeyToken=4300bc540bfb680e
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET.DLL.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET/AVX.NET.DLL.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET.EXE.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET/AVX.NET.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (8/15/2012 @ 8:55:28 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\Temp\gn\WPFDemo\bin\Debug\WPFDemo.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = xxxx
LOG: DisplayName = AVX.NET, Version=1.2.0.1551, Culture=neutral, PublicKeyToken=4300bc540bfb680e
(Fully-specified)
LOG: Appbase = file:///C:/Temp/gn/WPFDemo/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = WPFDemo.exe
Calling assembly : Test, Version=1.0.6.39680, Culture=neutral, PublicKeyToken=4300bc540bfb680e.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Temp\gn\WPFDemo\bin\Debug\WPFDemo.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: AVX.NET, Version=1.2.0.1551, Culture=neutral, PublicKeyToken=4300bc540bfb680e
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET.DLL.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET/AVX.NET.DLL.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET.EXE.
LOG: Attempting download of new URL file:///C:/Temp/gn/WPFDemo/bin/Debug/AVX.NET/AVX.NET.EXE.
LOG: All probing URLs attempted and failed.
There are a couple of triggers for the CLR to load an assembly. Beyond explicit Assembly.LoadXxx() calls, by far the most common one is the just-in-time compiler. Which needs the assembly to properly generate code for a method, before that method executes.
So if you have any code that uses a type from such an assembly and that code is “close” to the code you have that extracts the DLL then it is likely you’ll get this outcome. The jitter may well need the assembly before your extraction code can run.
You must particularly watch out for the inlining optimization performed by the jitter optimizer, enabled in the Release build without a debugger attached. Now “close” extends past the method body. To prevent this from happening, any method that is called from the method that performs the DLL extraction code must be decorated with [MethodImpl(MethodImplOptions.Noinlining)].
You’ll possibly be heading for another problem with this approach. It doesn’t look like you’ve written a custom AppDomain.AssemblyResolve event handler. Or it possibly didn’t get registered yet. You cannot extract DLLs to the same directory as the EXE on recent versions of Windows, UAC stops this. Extracting to a writable directory is required. Say the TEMP directory. Which then requires a custom assembly resolve handler. Virus scanners get nervous when executable files appear from nowhere, another highly random and utterly undiagnosable possible failure mode.
Do avoid these kind of problems with the most common way to deploy a single executable. One called setup.exe and created by, say, a Setup project. Easy to do in VS.