c# assemblies assembly-resolution

c# - AppDomain.CurrentDomain.AssemblyResolve solicitando un ensamblado<AppName>.resources?



assemblies assembly-resolution (2)

Mi situación era un poco más compleja y la solución anterior no funcionó para mí. (Eso es cambiar el archivo AssemblyInfo.cs)

He movido todos mis recursos de forma e imagen a una dll separada y en el momento en que se usa cualquiera de las imágenes, se lanza la excepción ''filenotfoundexception''

La información importante es la siguiente:
A partir de .NET Framework 4, el evento ResolveEventHandler se genera para todos los ensamblajes, incluidos los ensamblados de recursos. Vea la siguiente referencia

https://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve(v=vs.110).aspx

La solución resultó ser muy simple. Si se solicita un archivo de recursos con el formato ''dllname.resources.dll'', siempre se devuelve nulo;

Aquí está el código del evento que he adaptado de otras muestras encontradas. (He comentado las líneas de depuración: anule el comentario si tiene un problema con el código.

Añade esta línea en tu clase. Se utiliza para evitar cargar una dll más de una vez.

readonly static Dictionary<string, Assembly> _libs = new Dictionary<string, Assembly>();

Este es el método del evento.

private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) { Assembly assembly = null; string keyName = new AssemblyName(args.Name).Name; if (keyName.Contains(".resources")) { return null; // This line is what fixed the problem } if (_libs.ContainsKey(keyName)) { assembly = _libs[keyName]; // If DLL is loaded then don''t load it again just return return assembly; } string dllName = DllResourceName(keyName); //string[] names = Assembly.GetExecutingAssembly().GetManifestResourceNames(); // Uncomment this line to debug the possible values for dllName using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(dllName)) { if (stream == null) { Debug.Print("Error! Unable to find ''" + dllName + "''"); // Uncomment the next lines to show message the moment an assembly is not found. (This will also stop for .Net assemblies //MessageBox.Show("Error! Unable to find ''" + dllName + "''! Application will terminate."); //Environment.Exit(0); return null; } byte[] buffer = new BinaryReader(stream).ReadBytes((int) stream.Length); assembly = Assembly.Load(buffer); _libs[keyName] = assembly; return assembly; } } private static string DllResourceName(string ddlName) { if (ddlName.Contains(".dll") == false) ddlName += ".dll"; foreach (string name in Assembly.GetExecutingAssembly().GetManifestResourceNames()) { if (name.EndsWith(ddlName)) return name; } return ddlName; }

usando el código Cómo incrustar un conjunto satélite en el archivo EXE proporcionado por csharptest.net, he creado un solucionador de conjuntos personalizado e incrusté mis conjuntos en mis recursos.

Puedo resolver con éxito mis ensamblajes utilizados en pero de alguna manera, AppDomain.CurrentDomain.AssemblyResolve solicita un ensamblaje llamado ''AppName.resources'' específicamente "MyProgram.resources, Version = 0.15.3992.31638, Culture = en-US, Public KeyToken = null", que No sabes como resolver?

He intentado deshabilitar la carga de mis ensamblajes personalizados desde los recursos (puse todos los archivos DLL de mi ensamblaje en el directorio del programa) y solo habilité el dominio de aplicación.Dominio actual.Resolución de ensamblaje, pero aún así lo pedía.

Estoy un poco confundido acerca de esto, apreciaré mucho si puedes ayudarme en esto.

Aquí está mi código para los interesados;

static Assembly ResolveAssemblies(object sender, ResolveEventArgs args) { Assembly assembly = null; string name = args.Name.Substring(0, args.Name.IndexOf('','')); if (name == "MyProgram.resources") return null; else name = string.Format("MyProgram.Resources.Assemblies.{0}.dll", name); lock (_loadedAssemblies) { if (!_loadedAssemblies.TryGetValue(name, out assembly)) { using (Stream io = Assembly.GetExecutingAssembly().GetManifestResourceStream(name)) { if (io == null) { MessageBox.Show("MyProgram can not load one of it''s dependencies. Please re-install the program", string.Format("Missing Assembly: {0}", name), MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(-1); } using (BinaryReader binaryReader = new BinaryReader(io)) { assembly = Assembly.Load(binaryReader.ReadBytes((int)io.Length)); _loadedAssemblies.Add(name, assembly); } } } } return assembly; }


Respondiendo por mi cuenta;

La adición de esta línea a AssemblyInfo.cs lo resuelve y la resolución no volverá a pedir recursos.

[assembly: NeutralResourcesLanguageAttribute("en-US", UltimateResourceFallbackLocation.MainAssembly)]

Aunque se trata de una solución alternativa, deben considerarse cuidadosamente las aplicaciones en varios idiomas.

Más información:

Este enfoque falla para máquinas con culturas no en-EE. UU. Un mejor enfoque es ignorar los recursos en la resolución de ensamblajes;

public Assembly Resolver(object sender, ResolveEventArgs args) { lock (this) { Assembly assembly; AssemblyName askedAssembly = new AssemblyName(args.Name); string[] fields = args.Name.Split('',''); string name = fields[0]; string culture = fields[2]; // failing to ignore queries for satellite resource assemblies or using [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.MainAssembly)] // in AssemblyInfo.cs will crash the program on non en-US based system cultures. if (name.EndsWith(".resources") && !culture.EndsWith("neutral")) return null; /* the actual assembly resolver */ ... } }