Replies: 2 comments
-
It appears that |
Beta Was this translation helpful? Give feedback.
0 replies
-
I didn't have enough time to understand dotnet/orleans#236, and I will not have enough time to make a PR for this. What worked on my end was to provide the path to my preferred version of // --------------------------------
// Program.cs, replace existing method with this
// --------------------------------
private static void ResolveDependentAssemblies(
IDictionary<string, string> inputsMap,
string inputDir)
{
AssemblyResolver resolver = new AssemblyResolver(
assemblies: inputsMap,
folder: inputDir,
logger: log);
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += resolver.Resolve;
}
//---------------------------------
// AssemblyResolver.cs, new file
//---------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace MakeSfxCa
{
/// <summary>
/// The assembly resolver.
/// </summary>
public class AssemblyResolver
{
/// <summary>
/// The application folder (where we first look for assemblies).
/// </summary>
public string Folder { get; private set; }
/// <summary>
/// Instantiate an instance.
/// </summary>
/// <param name="assemblies">[NotNull]</param>
/// <param name="folder">The folder where we should search for assemblies first (if paths were not explicitly
/// given already).</param>
/// <param name="logger">[NotNull]</param>
public AssemblyResolver(
IDictionary<string, string> assemblies,
string folder,
TextWriter logger)
{
this.Folder = folder;
this.logger = logger;
foreach (KeyValuePair<string, string> entry in assemblies)
{
if (entry.Key.EndsWith(".dll") || entry.Key.EndsWith(".exe"))
{
AssemblyStub stub = new AssemblyStub(
assembly: null,
file: entry.Value);
this.assemblyCache[entry.Key] = stub;
}
}
}
/// <summary>
/// This is a <<see cref="ResolveEventHandler"/> intended to be hooked into the
/// <see cref="AppDomain.ReflectionOnlyAssemblyResolve"/> event.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">[NotNull] The event args.</param>
/// <returns>[NotNull] The assembly.</returns>
public Assembly Resolve(object sender, ResolveEventArgs args)
{
AssemblyName assemblyName = new AssemblyName(args.Name);
AssemblyStub stub = null;
if ( this.assemblyCache.TryGetValue($"{assemblyName.Name}.dll", out stub)
|| this.assemblyCache.TryGetValue($"{assemblyName.Name}.exe", out stub))
{
stub.EnsureLoaded();
if (stub.LoadError != null)
{
this.logger.WriteLine($" {stub.LoadError}");
}
}
else
{
stub = this.TryLoadUncachedAssembly(args.Name);
if (stub != null)
{
// Add it into the cache.
string key = Path.GetFileNameWithoutExtension(stub.File);
this.assemblyCache[key] = stub;
}
}
return stub?.Assembly;
}
/// <summary>
/// This is the cache of given assemblies. When a value has no <see cref="AssemblyStub.Assembly"/> then
/// it is just a stub for an assembly that has not been loaded yet.
/// Key = filename without path (e.g. "System.ValueTuple.dll")
/// Value.File = absolute filename with "dll" extension (e.g. "C:/Path/System.ValueTuple.dll")
/// </summary>
private Dictionary<string, AssemblyStub> assemblyCache = new Dictionary<string, AssemblyStub>();
/// <summary>
/// Logs are written here.
/// </summary>
private TextWriter logger;
/// <summary>
/// Tries to load an uncached assembly. This will not add the stub into the cache.
/// </summary>
/// <param name="asmName">The assembly name, as given by <see cref="ResolveEventArgs.Name"/>.</param>
/// <returns>If null, an assembly could not be found; otherwise this is the stub of the located assembly.</returns>
private AssemblyStub TryLoadUncachedAssembly(
string asmName)
{
AssemblyStub output = null;
AssemblyName assemblyName = new AssemblyName(asmName);
string tryPath = Path.Combine(this.Folder, $"{assemblyName.Name}.dll");
if (File.Exists(tryPath))
{
output = new AssemblyStub(
assembly: null,
file: tryPath);
}
else
{
tryPath = Path.Combine(this.Folder, $"{assemblyName.Name}.exe");
if (File.Exists(tryPath))
{
output = new AssemblyStub(
assembly: null,
file: tryPath);
}
}
if (output != null)
{
output.EnsureLoaded();
}
if (output?.Assembly == null)
{
Assembly asm = null;
try
{
asm = Assembly.ReflectionOnlyLoad(asmName);
}
catch (FileNotFoundException)
{
}
if (asm != null)
{
output = new AssemblyStub(
assembly: asm,
file: asm.Location);
if (asm.GetName().ToString() == assemblyName.ToString())
{
this.logger.WriteLine($" Loaded dependent assembly: {asm.Location}");
}
else
{
this.logger.WriteLine($" WARNING Loaded mismatched dependent assembly: {asm.Location}");
this.logger.WriteLine($" Loaded assembly: {asm.GetName()}");
this.logger.WriteLine($" Mismatched assembly: {assemblyName}");
}
}
}
if (output?.Assembly == null)
{
this.logger.WriteLine($" ERROR Dependent assembly not supplied: {assemblyName}");
if (output?.LoadError != null)
{
this.logger.WriteLine($" {output.LoadError}");
}
}
if (output?.File == null)
{
// Ensure that there is no stub if we do not have a file.
output = null;
}
return output;
}
}
}
//---------------------------------
// AssemblyStub.cs, new file
//---------------------------------
using System;
using System.IO;
using System.Reflection;
using System.Security;
namespace MakeSfxCa
{
/// <summary>
/// A stub that represents an assembly which may or may not be loaded yet.
/// </summary>
public class AssemblyStub
{
/// <summary>
/// The assembly (if loaded). If null, then the assembly has not been loaded yet.
/// </summary>
public Assembly Assembly { get; private set; }
/// <summary>
/// The absolute path to the assembly file.
/// </summary>
public string File { get; private set; }
/// <summary>
/// If defined, this is the error that occurred while trying to load the assembly. If null, an error was
/// not observed.
/// </summary>
public string LoadError { get; private set; }
public AssemblyStub()
{
}
/// <summary>
/// Constructs an instance.
/// </summary>
/// <param name="assembly"><see cref="Assembly"/></param>
/// <param name="file"><see cref="File"/></param>
public AssemblyStub(
Assembly assembly,
string file)
{
this.Assembly = assembly;
this.File = file;
}
/// <summary>
/// Ensures the assembly is loaded. This has no effect if the assembly is already loaded, or if an assembly
/// loading error was already detected. The load is only attempted once.
/// </summary>
public void EnsureLoaded()
{
if (this.Assembly != null || this.LoadError != null)
{
return;
}
try
{
this.Assembly = Assembly.ReflectionOnlyLoadFrom(this.File);
}
catch (Exception ex)
{
this.LoadError = $"Error: Failed to load dependent assembly: {this.File}. {ex.Message}";
}
}
}
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I am having a problem with the
MakeSfxCA.exe
tool: In our version of WiX (3.11.3.439) the tool doesn't support binding redirection. I can see that the problem still exists in the currentdevelop
branch by inspecting MakeSfxCA.ResolveDependentAssemblies.The scenario is:
.config
file.At runtime, the binding redirect loads
4.0.3.0
(which is what I want). Unfortunately, when I try to generate an assembly withMakeSfxCA.exe
I get the following error.This looks like a bug to me, but I wonder if there is an easy workaround. If not I will just rewrite MakeSfxCA.ResolveDependentAssemblies. In my case, I am already providing the path to
System.ValueTuple.dll
in theinputsMap
, so I can just create logic to select a value frominputMap
before falling back toAssembly.ReflectionOnlyLoad("System.ValueTuple")
;Beta Was this translation helpful? Give feedback.
All reactions