AppDomain dependencies across directories - c#

I am creating a plugin system and I am creating one AppDomain per plugin. Each plugin has its own directory with its main assemblies and references. The main assemblies will be loaded by my plugin loader, in addition to my interface assemblies (so the plugin can interact with the application).
Creating the AppDomain:
this.appDomain = AppDomain.CreateDomain("AppDomain", null, new AppDomainSetup {
ApplicationBase = pluginPath,
PrivateBinPath = pluginPath,
});
Loading the assemblies:
this.appDomain.Load(myInterfaceAssembly.GetName(true));
var assemblies = new List<Assembly>();
foreach (var assemblyName in this.assemblyNames) {
assemblies.Add(this.appDomain.Load(assemblyName));
}
The format of assemblyName is the assembly's filename without ".dll".
The problem is that AppDomain.Load(assemblyName) throws an exception:
Could not load file or assembly '[[assemblyName]], Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
All of the dependencies of [[assemblyName]] are:
Inside the directory pluginPath,
The myInterfaceAssembly which is already loaded, or
In the GAC (e.g. mscorelib).
Clearly I'm not doing something right. I have tried:
Creating an object using this.appDomain.CreateInstanceAndUnwrap inheriting from MarshalByRefObject with a LoadAssembly method to load the assembly. I get an exception saying that the current assembly (containing the proxy class) could not be loaded (file not found, as above), even if I manually call this.appDomain.Load(Assembly.GetExecutingAssembly().GetName(true)).
Attaching an AssemblyResolve handler to this.appDomain. I'm met with the same exception as in (1), and manually loading doesn't help.
Recursively loading assemblies by loading their dependencies into this.appDomain first. This doesn't work, but I doubt my code is correct:
private static void LoadAssemblyInto(AssemblyName assemblyName, AppDomain appDomain) {
var assembly = Assembly.Load(assemblyName);
foreach (var referenceName in assembly.GetReferencedAssemblies()) {
if (!referenceName.FullName.StartsWith("MyProject")) {
continue;
}
var loadedAssemblies = appDomain.GetAssemblies();
if (loadedAssemblies.Any((asm) => asm.FullName == referenceName.FullName)) {
continue;
}
LoadAssemblyInto(referenceName, appDomain);
}
appDomain.Load(assembly.GetName(true));
}
How can I load my plugin assembly with its dependencies in that plugin's directory while also loading some assemblies in the current directory?
Note: The assemblies a plugin may (probably will) reference are already loaded in the current domain. This can be shared across domains (performance benefit? simplicity?) if required.
Fusion log:
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: Where-ref bind. Location = C:/MyProject/bin/Debug/MyProject.Library.DLL
LOG: Appbase = file:///C:/PluginDir
LOG: Initial PrivatePath = C:\PluginDir
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.Library.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\MyProject.Library.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: MyProject.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Re-apply policy for where-ref bind.
LOG: Where-ref bind Codebase does not match what is found in default context. Keep the result in LoadFrom context.
LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\MyProject.Library.dll.
LOG: Assembly is loaded in LoadFrom load context.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: Where-ref bind. Location = C:\MyProject\bin\Debug\MyProject.exe
LOG: Appbase = file:///C:/MyProject/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.exe.
LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\MyProject.exe
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: Re-apply policy for where-ref bind.
LOG: Where-ref bind Codebase matches what is found in default context. Keep the result in default context.
LOG: The post-policy assembly reference requires probing again.
LOG: Switch from LoadFrom context to default context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\MyProject.exe.
LOG: Assembly is loaded in default load context.
LOG: Where-ref bind Codebase matches what is found in default context. Keep the result in default context.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
(Fully-specified)
LOG: Appbase = file:///C:/MyProject/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Binding succeeds. Returns assembly from C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll.
LOG: Assembly is loaded in default load context.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 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:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = MyProject.resources, Version=1.0.0.0, Culture=en-US, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/MyProject/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources/MyProject.resources.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources.EXE.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en-US/MyProject.resources/MyProject.resources.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 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:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = MyProject.resources, Version=1.0.0.0, Culture=en, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/MyProject/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources/MyProject.resources.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources.EXE.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/en/MyProject.resources/MyProject.resources.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 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:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = MyProject.Library, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL
(Fully-specified)
LOG: Appbase = file:///C:/PluginDir
LOG: Initial PrivatePath = C:\PluginDir
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library.DLL.
LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library/MyProject.Library.DLL.
LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library.EXE.
LOG: Attempting download of new URL file:///C:/PluginDir/MyProject.Library/MyProject.Library.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:28 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = MyProject
(Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: MyProject | Domain ID: 1
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/MyProject/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject/MyProject.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyProject.EXE.
LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\MyProject.exe
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: A partially-specified assembly bind succeeded from the application directory. Need to re-apply policy.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\MyProject.exe.
LOG: Assembly is loaded in default load context.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = MyPlugin
(Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: MyPlugin | Domain ID: 2
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/PluginDir
LOG: Initial PrivatePath = C:\PluginDir
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/PluginDir/MyPlugin.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\PluginDir\MyPlugin.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
LOG: A partially-specified assembly bind succeeded from the application directory. Need to re-apply policy.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Binding succeeds. Returns assembly from C:\PluginDir\MyPlugin.dll.
LOG: Assembly is loaded in default load context.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 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:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = MyPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/MyProject/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin/MyPlugin.DLL.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin.EXE.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/MyPlugin/MyPlugin.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL
(Fully-specified)
LOG: Appbase = file:///C:/PluginDir
LOG: Initial PrivatePath = C:\PluginDir
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Download of application configuration file was attempted from file:///C:/MyProject/bin/Debug/MyProject.vshost.exe.Config.
LOG: Found application configuration file (C:\MyProject\bin\Debug\MyProject.vshost.exe.Config).
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Microsoft.VisualStudio.HostingProcess.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL
LOG: Found assembly by looking in the GAC.
LOG: Binding succeeds. Returns assembly from C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities\10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.dll.
LOG: Assembly is loaded in default load context.
*** Assembly Binder Log Entry (12/24/2010 # 11:03:29 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\MyProject\bin\Debug\MyProject.vshost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = Null-Laptop-PC\Null-Laptop
LOG: DisplayName = Ionic.Zip.Reduced, Version=1.9.1.5, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c
(Fully-specified)
LOG: Appbase = file:///C:/MyProject/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyProject.vshost.exe
Calling assembly : MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\MyProject\bin\Debug\MyProject.vshost.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: Ionic.Zip.Reduced, Version=1.9.1.5, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/MyProject/bin/Debug/Ionic.Zip.Reduced.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\MyProject\bin\Debug\Ionic.Zip.Reduced.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Ionic.Zip.Reduced, Version=1.9.1.5, Culture=neutral, PublicKeyToken=edbe51ad942a3f5c
LOG: Binding succeeds. Returns assembly from C:\MyProject\bin\Debug\Ionic.Zip.Reduced.dll.
LOG: Assembly is loaded in default load context.

I tried one of my attempted solutions again:
Creating an object using this.appDomain.CreateInstanceAndUnwrap inheriting from MarshalByRefObject with a LoadAssembly method to load the assembly. I get an exception saying that the current assembly (containing the proxy class) could not be loaded (file not found, as above), even if I manually call this.appDomain.Load(Assembly.GetExecutingAssembly().GetName(true)).
I found out that CreateInstanceFromAndUnwrap can accept the path to an assembly file, which makes things easy:
private T CreateOnAppDomain<T>() {
var type = typeof(T);
return (T) this.appDomain.CreateInstanceFromAndUnwrap(
type.Assembly.Location,
type.FullName
);
}
public void LoadAssemblies() {
var assemblyLoader = CreateOnAppDomain<AssemblyLoader>();
assemblyLoader.LoadAssembly(myInterfaceAssembly.GetName(true));
foreach (var assemblyName in this.assemblyNames) {
assemblyLoader.LoadAssembly(new AssemblyName(assemblyName));
}
}
class AssemblyLoader : MarshalByRefObject {
public void LoadAssembly(AssemblyName name) {
Assembly.Load(name);
}
}
This solves my AppDomain creation problems. (Now to get everything else working!)
Thanks for everyone's help; I really appreciate your inputs.

I believe that the exception is occurring when it tries to load the assembly into the main AppDomain and not the domain you created explicitly. This is a side effect of using AppDomain.Load which leads to the assembly being loaded into the current domain and the domain you created. Since the assembly is only in the bin path (plugin directory) of the domain you created you get the exception.
From MSDN related to AppDomain.Load:
The assembly is loaded into both
domains because Assembly does not
derive from MarshalByRefObject, and
therefore the return value of the Load
method cannot be marshaled. Instead,
the common language runtime tries to
load the assembly into the calling
application domain.

I had a similar issue. You need to customize the method used to find the assemblies. The Console.Debug statements might need to be modified to compile but here is the general gist:
private static void SetupResolvingAdditionalThirdPartyDlls()
{
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssemblies;
}
private static Assembly ResolveAssemblies(object sender, ResolveEventArgs args)
{
Assembly assembly = null;
bool foundAssembly = false;
Console.DebugFormat("Received request for the following dll {0}", args.Name);
int idx = args.Name.IndexOf(',');
if (idx > 0)
{
string partialName = args.Name.Substring(0, idx);
string dllName = partialName + ".dll";
string exeName = partialName + ".exe";
string searchDirectory = "locationOfDirectoryToSearch";
// Add other directories that you want to search here
List<string> directorySearch = new List<string>
{
CombinePath(searchDirectory, dllName),
CombinePath(searchDirectory, exeName),
// Include the other directories here to this list adding both the dll and exe.
};
foreach (string fileName in directorySearch)
{
if (File.Exists(fileName))
{
Console.DebugFormat("Found dll {0} at {1}", args.Name, fileName);
foundAssembly = true;
assembly = Assembly.LoadFrom(fileName);
break;
}
}
if (assembly == null)
{
if (!foundAssembly)
{
foreach (string fileName in directorySearch)
{
Console.DebugFormat("Could not find dll {0} in any search path used {1}", args.Name, fileName);
}
}
else
{
Console.DebugFormat("Could not load dll {0}", args.Name);
}
}
}
return assembly;
}

Related

Assembly.LoadFrom is not loading DLL from folder

I built an app that needs access to three DLL's for an optional feature.
Since it's optional, I don't ship those 3 DLL's and let the user select if he wants or not to have it.
But since I'm actually using the DLL in code, I need to reference them (via nuget).
The problem is that if those 3 DLL's are stored in a folder different than where the main executable is located, the app fails to access them.
SharpDX.Direct3D11.dll
SharpDX.dll
SharpDX.DXGI.dll
I already tried to manually call Assembly.LoadFrom(path) without success.
The strange part is that the app fails to load one of them:
*** Assembly Binder Log Entry (27/02/2020 # 10:51:36) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Program Files (x86)\MyApp\MyApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
(Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/MyApp/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyApp.exe
Calling assembly : MyApp, Version=2.21.1.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (27/02/2020 # 10:51:36) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Program Files (x86)\MyApp\MyApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
(Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/MyApp/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MyApp.exe
Calling assembly : MyApp, Version=2.21.1.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: SharpDX.DXGI, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyApp/SharpDX.DXGI/SharpDX.DXGI.EXE.
LOG: All probing URLs attempted and failed.
The code that tried to load the three DLL's is this and it runs right before any call or reference to the SharpDX library appears, I debugged and it executes those lines normally:
public static void LoadSharpDx()
{
var realPath = UserSettings.All.SharpDxLocationFolder ?? "";
//In order to get the correct location, I need to combine the current base directory with the relative path.
if (!string.IsNullOrWhiteSpace(UserSettings.All.SharpDxLocationFolder) && !Path.IsPathRooted(UserSettings.All.SharpDxLocationFolder))
realPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, UserSettings.All.SharpDxLocationFolder.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
if (string.IsNullOrEmpty(realPath) || realPath == ".")
return;
//The realPath is C:\Users\nicke\Desktop\Dll
//So, it's correct.
Assembly.LoadFrom(Path.Combine(realPath, "SharpDX.dll"));
Assembly.LoadFrom(Path.Combine(realPath, "SharpDX.Direct3D11.dll"));
Assembly.LoadFrom(Path.Combine(realPath, "SharpDX.DXGI.dll"));
//Throws a different error.
//Assembly.Load(Path.Combine(realPath, "SharpDX.dll"));
//Assembly.Load(Path.Combine(realPath, "SharpDX.Direct3D11.dll"));
//Assembly.Load(Path.Combine(realPath, "SharpDX.DXGI.dll"));
}
When analyzing ProcMon, I can see that the app is able to find and load the DLL inside the folder.
So, what's going on?
Why can't it load the SharpDX.DXGI library?
So, I interpreted wrong what Assembly.LoadFrom() was doing.
In the end, I just had to use the CurrentDomain.AssemblyResolve event:
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
var assemblyName = args.Name.Split(',').First();
if (!assemblyName.StartsWith("SharpDX"))
return null;
//Simply converts relative paths to full paths in order to
//prevent getting the wrong path when the app is loaded from a
//link or "Open with..." commands.
var path = Other.AdjustPath(UserSettings.All.SharpDxLocationFolder ?? "");
return Assembly.LoadFrom(System.IO.Path.Combine(path, $"{assemblyName}.dll"));
}
catch (Exception e)
{
LogWriter.Log(e, "Error loading assemblies");
return null;
}
}

Why does a library generated by Costura.Fody require DLL it has included inside?

We are using Costura.Fody to pack all our binaries into a single DLL. It has a VS solution with a single project and we pack all its dependencies to it. As long as this project was single within the solution, it was working. But recently we moved some features into another project. Since then, the library fails to load with System.Reflection.Assembly.LoadFrom, throwing the following error:
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
=== LOADER EXCEPTIONS ===
System.IO.FileNotFoundException:
---
System.IO.FileNotFoundException: Could not load file or assembly 'OurCompany.OurProject.TheLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'OurCompany.OurProject.TheLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
=== Pre-bind state information ===
LOG: DisplayName = OurCompany.OurProject.TheLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/Work/Test/LibraryExplorer.Cli/bin/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : OurCompany.OurProject, Version=1.0.62.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\Work\Test\LibraryExplorer.Cli\bin\Debug\LibraryExplorer.Cli.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: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Work/Test/LibraryExplorer.Cli/bin/Debug/OurCompany.OurProject.TheLibrary.DLL.
LOG: Attempting download of new URL file:///C:/Work/Test/LibraryExplorer.Cli/bin/Debug/OurCompany.OurProject.TheLibrary/OurCompany.OurProject.TheLibrary.DLL.
LOG: Attempting download of new URL file:///C:/Work/Test/LibraryExplorer.Cli/bin/Debug/OurCompany.OurProject.TheLibrary.EXE.
LOG: Attempting download of new URL file:///C:/Work/Test/LibraryExplorer.Cli/bin/Debug/OurCompany.OurProject.TheLibrary/OurCompany.OurProject.TheLibrary.EXE.
LOG: Attempting download of new URL file:///C:/Users/dominik.janata/AppData/Local/Temp/ProjectClock/OurCompany.OurProject.TheLibrary.DLL.
LOG: Attempting download of new URL file:///C:/Users/dominik.janata/AppData/Local/Temp/ProjectClock/OurCompany.OurProject.TheLibrary/OurCompany.OurProject.TheLibrary.DLL.
LOG: Attempting download of new URL file:///C:/Users/dominik.janata/AppData/Local/Temp/ProjectClock/OurCompany.OurProject.TheLibrary.EXE.
LOG: Attempting download of new URL file:///C:/Users/dominik.janata/AppData/Local/Temp/ProjectClock/OurCompany.OurProject.TheLibrary/OurCompany.OurProject.TheLibrary.EXE.
To address an obvious suggestion, OurCompany.OurProject.TheLibrary.DLL is packed among the resources of OurCompany.OurProject.DLL

Assembly Binding Issue in asp.net web application, Enabled Fusion Log

I am working on legacy web application and I am getting run time assembly binding error (FileNotFoundException)
I looked into application base directory and can confirm that required DLL with correct version and public token is available under bin/ directory.
I enabled Fusion Log on server to capture details and realized that CLR is probing for assembly in GAC first (I think this is by design for signed assemblies) Below is log for quick reference :
I am able to make it work by installing assembly in GAC - but question and curiosity still remains open why CLR did not picked it from application base directory after it is not found in GAC ?
Also from below log it appears that after GAC, search is performed under directory C:Windows/System32 vs my application directory. I think it's because also logs says it's Running under executable C:\Windows\system32\dllhost.exe
Any help/comment appreciated !!
*** Assembly Binder Log Entry (6/28/2018 # 4:18:02 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Windows\system32\dllhost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.19.3.10102, Culture=neutral, PublicKeyToken=31bf3856ad364e35
(Fully-specified)
LOG: Appbase = file:///C:/Windows/system32/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = dllhost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory.DLL.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory/Microsoft.IdentityModel.Clients.ActiveDirectory.DLL.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory.EXE.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory/Microsoft.IdentityModel.Clients.ActiveDirectory.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (6/28/2018 # 4:18:02 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Windows\system32\dllhost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.19.3.10102, Culture=neutral, PublicKeyToken=31bf3856ad364e35
(Fully-specified)
LOG: Appbase = file:///C:/Windows/system32/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = dllhost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory.DLL.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory/Microsoft.IdentityModel.Clients.ActiveDirectory.DLL.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory.EXE.
LOG: Attempting download of new URL file:///C:/Windows/system32/Microsoft.IdentityModel.Clients.ActiveDirectory/Microsoft.IdentityModel.Clients.ActiveDirectory.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (6/28/2018 # 4:18:03 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Windows\system32\dllhost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.19.3.10102, Culture=neutral, PublicKeyToken=31bf3856ad364e35
(Fully-specified)
LOG: Appbase = file:///C:/Windows/system32/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = dllhost.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: The same bind was seen before, and was failed with hr = 0x80070002.
ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002).
*** Assembly Binder Log Entry (6/28/2018 # 4:18:03 AM) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Windows\system32\dllhost.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.19.3.10102, Culture=neutral, PublicKeyToken=31bf3856ad364e35
(Fully-specified)
LOG: Appbase = file:///C:/Windows/system32/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = dllhost.exe
Calling assembly : MS.UST.EC.Oem.ServiceProxy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0753af11def5a5f8.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: The same bind was seen before, and was failed with hr = 0x80070002.
ERR: Unrecoverable error occurred during pre-download check (hr = 0x80070002).
The EXE image C:\Windows\system32\dllhost.exe is known as the "COM Surrogate" host. When you want to activate a COM+ component service, and not load it in your own process (for security or stability), dllhost.exe will be invoked to load the component and expose it as an "out of process" activation, then communicate back to your process via some transparent proxy channel, allowing the calling program to pretend that the component is loaded locally.
What this means is that you likely have some code which is being accessed via a COM+ interface and getting launched out-of-process. This code in turn is trying to load the Microsoft.IdentityModel.Clients.ActiveDirectory assembly. The problem is, it's not in your process anymore, and won't participate in any binding policy you've setup (private bin path, binding redirects, etc). This is why you see it trying the GAC first and then failing to find your dll - it's not your process.
Look for any component you might be loading which is a COM component: are you using some COM TypeLib, or a Runtime Callable Wrapper to some COM dll, or do you have any code which inherits System.EnterpriseServices.ServicedComponent?
If you can find where the out-of-process COM component is being launched, you may be able to refactor it to bring the logic in-process and fix your loading issues this way. Otherwise you'll have to put the assemblies in the GAC.

Windows Service Installation Error: Error 1001, Unable to get installer types assembly in the C:\Program Files\..\..\xxx.dll assembly.

We're pushing a legacy Windows Service that was originally written for Windows 2003 to a Windows 2012 R2 Server for testing, however when we attempt to run the installer .msi, we are receiving the following error:
Error 1001, Unable to get installer types assembly in the C:\Program Files\..\..\xxx.dll assembly. -> . Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
It appears that it may be an issue with an Oracle.DataAccess DLL:
The Log Viewer provided this information:
*** Assembly Binder Log Entry (7/22/2016 # 1:54:54 PM) ***
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:\Windows\syswow64\MsiExec.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
(Fully-specified)
LOG: Appbase = file:///C:/Windows/syswow64/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MsiExec.exe
Calling assembly : CTMSRenewalOutboundService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: No application configuration file found.
LOG: Using host configuration file: C:\Temp\CFG4155.tmp
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Program Files\PPD\CTMSOutboundService\Oracle.DataAccess.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
ERR: Invalid assembly platform or ContentType in file (hr = 0x8007000b).
ERR: Run-from-source setup phase failed with hr = 0x8007000b.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (7/22/2016 # 1:54:54 PM) ***
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:\Windows\syswow64\MsiExec.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
(Fully-specified)
LOG: Appbase = file:///C:/Windows/syswow64/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MsiExec.exe
Calling assembly : CTMSRenewalOutboundService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: No application configuration file found.
LOG: Using host configuration file: C:\Temp\CFG4155.tmp
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Program Files\PPD\CTMSOutboundService\Oracle.DataAccess.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
ERR: Invalid assembly platform or ContentType in file (hr = 0x8007000b).
ERR: Run-from-source setup phase failed with hr = 0x8007000b.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (7/22/2016 # 4:01:10 PM) ***
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:\Windows\syswow64\MsiExec.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
(Fully-specified)
LOG: Appbase = file:///C:/Windows/syswow64/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MsiExec.exe
Calling assembly : CTMSRenewalOutboundService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: No application configuration file found.
LOG: Using host configuration file: C:\Temp\CFGDA59.tmp
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Program Files\PPD\CTMSOutboundService\Oracle.DataAccess.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
ERR: Invalid assembly platform or ContentType in file (hr = 0x8007000b).
ERR: Run-from-source setup phase failed with hr = 0x8007000b.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: All probing URLs attempted and failed.
*** Assembly Binder Log Entry (7/22/2016 # 4:01:10 PM) ***
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:\Windows\syswow64\MsiExec.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
(Fully-specified)
LOG: Appbase = file:///C:/Windows/syswow64/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = MsiExec.exe
Calling assembly : CTMSRenewalOutboundService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: No application configuration file found.
LOG: Using host configuration file: C:\Temp\CFGDA59.tmp
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Windows/syswow64/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Program Files\PPD\CTMSOutboundService\Oracle.DataAccess.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Oracle.DataAccess, Version=4.112.4.0, Culture=neutral, PublicKeyToken=89b483f429c47342
ERR: Invalid assembly platform or ContentType in file (hr = 0x8007000b).
ERR: Run-from-source setup phase failed with hr = 0x8007000b.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/PPD/CTMSOutboundService/Oracle.DataAccess/Oracle.DataAccess.EXE.
LOG: All probing URLs attempted and failed.
I made sure to try both:
Copying a local copy of Oracle.DataAccess.DLL
Using a reference to the GAC for Oracle.DataAccess.DLL
However neither seemed to work.
We have deployed several other Windows Services that refer to this DLL, and had no issues.
Thanks.
It'll very likely be a bitness issue as those links imply. I'm going to add some extra info here.
The installer class in the installer assembly is not called directly. There is a C++ Dll that your MSI calls first, and this loads a version of the NET Runtime and then instantiates your custom action installer class methods through reflection (which is why you don't see your assembly load in FusionViewer). Copy Local won't matter during the install - it will load GAC assemblies. Apart from being instantiated via reflection, your CA assembly is being called from an msiexec.exe process and won't load any config or settings files you have, or otherwise care where it's running from (for examplr there is no working directory of the assembly's location).
The chain of bitness gets complicated - your setup may be x86 or x64, your custom action Dll may be x86, x64 or AnyCpu. It will try to load dependencies which may not match. If it's an x86 install, build your installer class for x86 and make sure anything it calls is built for x86. Same idea if it's x64. So a possible explanation is that Server 2012 is 64-bit and your CA assembly is running native and looking for 32-bit Oracle assemblies.
Our workaround to this issue after speaking with Microsoft Support was to use Orca to override the InstallUtilLib.dll being referenced in the 32 bit .Net framework directory.
By using Orca, we were able to point the msi to the c:\Windows\Microsoft.Net\Framework64 directory.
Open the resulting .msi in Orca from the Windows Installer SDK
Select the Binary table
Double click the cell [Binary Data] for the record InstallUtil
Make sure “Read binary from filename” is selected and click the Browse button
Browse to %WINDIR%Microsoft.NET\Framework64\v4.0.30319
Select InstallUtilLib.dll
Click the Open button
Click the OK button
As soon as we followed these steps, we were able to install the Windows Service.
We had several other Windows Services that we built and upgraded to Windows 2012R2 without any issues. For some reason this was the only service that required this workaround.
Hope this helps someone.
Thanks.

Why won't my program look in the GAC for an assembly?

I have a service that loads a bunch of assemblies as plugins. Each of these plugins reference a common assembly that is installed in the GAC. For some reason, some of the plugins are able to successfully load the assembly from the GAC, but others fail. I can't seem to figure out why this would be happening. Here is the Fusion log for one that works and on that doesn't:
*** Assembly Binder Log Entry (12/3/2011 # 10:54:47 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\Windows\Microsoft.NET\Framework\v4.0.30319\AddInProcess.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\SYSTEM
LOG: DisplayName = OSAE.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f47a6446f36f79f7
(Fully-specified)
LOG: Appbase = file:///C:/Program Files/OSA/AddIns/ZWave
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = NULL
Calling assembly : OSAE.Zwave, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
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: OSAE.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f47a6446f36f79f7
LOG: Found assembly by looking in the GAC.
LOG: Binding succeeds. Returns assembly from C:\Windows\Microsoft.Net\assembly\GAC_MSIL\OSAE.API\v4.0_1.0.0.0__f47a6446f36f79f7\OSAE.API.dll.
LOG: Assembly is loaded in default load context.
Failed:
*** Assembly Binder Log Entry (12/3/2011 # 10:54:46 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:\Windows\Microsoft.NET\Framework\v4.0.30319\AddInProcess.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\SYSTEM
LOG: DisplayName = OSAE.API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/Program Files/OSA/AddIns/Web Server
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = NULL
Calling assembly : OSAE.WebServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Program Files/OSA/AddIns/Web Server/OSAE.API.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/OSA/AddIns/Web Server/OSAE.API/OSAE.API.DLL.
LOG: Attempting download of new URL file:///C:/Program Files/OSA/AddIns/Web Server/OSAE.API.EXE.
LOG: Attempting download of new URL file:///C:/Program Files/OSA/AddIns/Web Server/OSAE.API/OSAE.API.EXE.
LOG: All probing URLs attempted and failed.
Failed assembly is not strongly signed (PublicKey=null). I don't know why the assembly is not signed, but there is no need for loader to look in the GAC for such assembly as only strongly signed assemblies can go into the GAC.

Categories

Resources