AppDomain.CurrentDomain.AssemblyResolve要求 .resources程序集?
使用代码如何将附属程序集嵌入到 csharptest.net提供的EXE文件中 ,我创建了一个自定义程序集解析程序并在我的资源中嵌入了我的程序集。
我可以成功解析我使用的程序集,但不知怎的,AppDomain.CurrentDomain.AssemblyResolve请求一个名为’AppName.resources’的程序集,特别是“MyProgram.resources,Version = 0.15.3992.31638,Culture = en-US,PublicKeyToken = null”不知道如何解决?
我试图禁用从资源加载我的自定义程序集(将所有程序集dll放在程序目录中)并启用AppDomain.CurrentDomain.AssemblyResolve,但它仍然要求它。
我对此有点困惑,如果你可以帮助我,我将非常感激。
这是我感兴趣的代码;
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; }
自己回答;
将此行添加到AssemblyInfo.cs可以解决它,并且不再需要解析器来获取资源。
[assembly: NeutralResourcesLanguageAttribute("en-US", UltimateResourceFallbackLocation.MainAssembly)]
虽然这是一种解决方案,但应该仔细考虑多语言应用。
更多信息:
- https://connect.microsoft.com/VisualStudio/feedback/details/526836/wpf-appdomain-assemblyresolve-being-called-when-it-shouldnt
- http://blogs.msdn.com/b/kimhamil/archive/2008/11/11/what-does-the-neutralresourceslanguageattribute-do.aspx
- http://forums.devshed.com/net-development-87/c-wpf-appdomain-assemblyresolve-being-called-when-it-shouldn-t-669567.html
- http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx
对于具有非en-US文化的机器,这种方法失败了。 更好的方法是忽略assembly解析器上的资源;
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 */ ... } }
我的情况有点复杂,上述解决方案对我不起作用。 (那是改变AssemblyInfo.cs文件)
我已将所有表单和图像资源移动到单独的dll中,并且在使用任何图像时,抛出“filenotfoundexception”exception。
重要信息如下:
从.NET Framework 4开始,将为所有程序集(包括资源程序集)引发ResolveEventHandler事件。 请参阅以下参考
https://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve(v=vs.110).aspx
解决方案结果非常简单。 如果以“dllname.resources.dll”forms请求资源文件,则始终返回null;
这是我从其他样本中找到的事件代码。 (我已经评论了调试行 – 如果您在使用代码时遇到问题,请取消注释。
在您的课程中添加此行。 它用于防止多次加载dll
readonly static Dictionary _libs = new Dictionary();
这是事件方法。
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; }