Using an absolute path in probing privatePath
according to MSDN:
You can use the element only in machine configuration or publisher policy files that also redirect the assembly version. ... If you are supplying a code base hint for an assembly that is not strong-named, the hint must point to the application base or a subdirectory of the application base directory.
You probably tried to apply in in app.config
?
and
The directories specified in privatePath must be subdirectories of the application base directory.
Use an AssemblyResolver instead in this situation.
Here's some code I cribbed partly from another question and modified for our own use. Unlike the linked code, this one resolves the application execution folder, which was something I haven't seen in many other examples. Feel free to excise that and stick in your own absolute path if necessary.
One advantage of the assembly resolver is that if you have mixed versions of your dlls, and want to load the dll from the target folder, not the one that happens to be with the app, then this works whereas the config file method doesn't.
I have that problem because our app ships with a small utility that is an app upgrader, and it often needs to reference newer versions of the dlls than the original app. (The upgrader gets updated, then the upgrader updates the main app. If they both look at the same dlls, bad things can happen.)
public static class AssemblyResolver
{
internal static void Hook(params string[] folders)
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
// Check if the requested assembly is part of the loaded assemblies
var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name);
if (loadedAssembly != null)
return loadedAssembly;
// This resolver is called when a loaded control tries to load a generated XmlSerializer - We need to discard it.
// http://connect.microsoft.com/VisualStudio/feedback/details/88566/bindingfailure-an-assembly-failed-to-load-while-using-xmlserialization
var n = new AssemblyName(args.Name);
if (n.Name.EndsWith(".xmlserializers", StringComparison.OrdinalIgnoreCase))
return null;
// http://stackoverflow.com/questions/4368201/appdomain-currentdomain-assemblyresolve-asking-for-a-appname-resources-assembl
if (n.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
return null;
string assy = null;
// Get execution folder to use as base folder
var rootFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)??"";
// Find the corresponding assembly file
foreach (var dir in folders)
{
assy = new[] { "*.dll", "*.exe" }.SelectMany(g => Directory.EnumerateFiles(Path.Combine(rootFolder,dir), g)).FirstOrDefault(f =>
{
try
{
return n.Name.Equals(AssemblyName.GetAssemblyName(f).Name,
StringComparison.OrdinalIgnoreCase);
}
catch (BadImageFormatException)
{
return false; /* Bypass assembly is not a .net exe */
}
catch (Exception ex)
{
// Logging etc here
throw;
}
});
if (assy != null)
return Assembly.LoadFrom(assy);
}
// More logging for failure here
return null;
};
}
}
Invoke this early on providing a list of paths to use for assembly resolving
AssemblyResolver.Hook("upglib","myOtherFolder");