AppDomain拒绝加载程序集

编程入门 行业动态 更新时间:2024-10-18 18:15:46
本文介绍了AppDomain拒绝加载程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试创建一个小的插件框架,并且在AppDomain代码中四处走动,运气不佳. 对我来说最重要的是,我希望在同一类的不同版本之间没有冲突(例如,一个插件可能要使用其自己的Common.dll v 1.0库,而我可能有2.0),这与其他问题类似. 所以我在下面写了这个小应用.

静态 void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault( false ); Console.WriteLine(Utility.GetVersion()); var ads = 新 AppDomainSetup(); 字符串 appBase = @" ../../ExtensionLib /ExtensionLib/bin/Debug"; ads.ApplicationBase = appBase; // ads.PrivateBinPath = appBase; // ads.ConfigurationFile ="ExtensionLib.dll.config"; // ads.PrivateBinPathProbe =."; var ad = AppDomain.CreateDomain(" 扩展应用" ,空,广告); // var ah = new AssemblyHelper(); // ad.AssemblyResolve + = ah.MyResolveEventHandler; // ad.AssemblyLoad + = ah.AssemblyLoadedHandler; // MessageBox.Show(ad.BaseDirectory); 组装a = ad.Load(" ExtensionLib" ); ILib l =(ILib)a.CreateInstance(" LibImpl" ); l.DoSomething(); Console.WriteLine(Utility.GetVersion()); } }

Common.dll包含实用程序类,但是我们拥有该类的不同版本.插件和主机应用程序都使用相同的ILib(在同一个dll中定义). 主机应用程序设置

c:\....\123 Common.dll (v 2.0) IntegInterface.dll (where ILib is defined, v1.0) LoadCommon.exe (the host)

插件应用程序设置

c:\ .... \ 456 Common.dll(v 1.0) IntegInterface.dll(其中定义了ILib,v1.0) ExtensionLib.dll(插件)

当应用运行时,在ad.Load()时出现异常

System.IO.FileNotFoundException was unhandled Message="Could not load file or assembly ''ExtensionLib'' or one of its dependencies. The system cannot find the file specified." Source="mscorlib" FileName="ExtensionLib" FusionLog="Assembly manager loaded from: C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\mscorwks.dll Running under executable C:\\Users\\Roberto\\Documents\\Visual Studio 2008\\Projects\\LoadCommon\\LoadCommon\\bin\\Debug\\LoadCommon.vshost.exe --- A detailed error log follows. \n === Pre-bind state information === LOG: User = Roberto-PC\\Roberto LOG: DisplayName = ExtensionLib\n (Partial) LOG: Appbase = file:///C:/Users/Roberto/Documents/Visual Studio 2008/Projects/LoadCommon/LoadCommon/ExtensionLib/ExtensionLib/bin/Debug LOG: Initial PrivatePath = NULL Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\\Users\\Roberto\\Documents\\Visual Studio 2008\\Projects\\LoadCommon\\LoadCommon\\ExtensionLib\\ExtensionLib\\bin\\Debug\\ExtensionLib.dll.config LOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\config\\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). " StackTrace: at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.AppDomain.Load(String assemblyString) at System.AppDomain.Load(String assemblyString) at LoadCommon.Program.Main() in C:\Users\Roberto\Documents\Visual Studio 2008\Projects\LoadCommon\LoadCommon\Program.cs:line 36 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

我还尝试设置一个assemblyresolve委托,以查看是否可以提供帮助,但是运气不好,尽管我将AssemblyHelper标记为可序列化,但还是遇到了序列化错误. 在某些时候,我还将使IntegInterface具有不同的版本,并确保我最终会遇到很多问题. 有人可以在这里说些什么吗?非常感谢. 感谢

解决方案

这是关于加载程序集的常见混淆.是否要按其主要可执行模块的文件名加载Assembly? 使用System.Reflection.Assembly.LoadFrom(string fileName).有关其他区别,请参见所有其他System.Reflection.Assembly.Load...方法和帮助页面.该调用应在新创建的Application Domain上下文中完成,而不是在流程的默认(初始)Application Domain中完成.如果我对您的插件组合的假设是错误的,请自由纠正我,我将为您提供一些不同的方法.

System.AppDomain广告= AppDomain.CreateDomain(" 扩展应用" , 空,广告); ad.DoCallBack(()= > { // ... System.Reflection.Assembly.LoadFrom(myPluginFileName); // ... });

如果您的插件程序集具有入口点(EXE文件),则可以使用System.AppDomain.ExecuteAssembly.我怀疑您是通过这种方式设计插件的(您提到了ILib接口;如果这是您的插件支持的接口,那么,恭喜!这是最好的方法.请参阅下面的参考资料,其中使用特殊的装配属性来选择实现插件接口& mdas;的类,对鲁棒性和性能非常好. 因此,即使我认为您的设计不是基于EXE入口点,但让我展示一下以防万一:

System.AppDomain广告= AppDomain.CreateDomain(" 扩展应用" , 空,广告); ad.ExecuteAssembly(myExeFileName);

很高兴您了解在单独的Application Domain中动态加载插件的重要性,但这仅在以后要卸载它们时才需要.如果您只需要加载一次所有插件,则可以在一个域(默认域)中工作,而不必创建额外的应用程序域. 您可以实现我有关插件程序集和使用Application Domain的各种设计的所有答案: 创建使用可重载插件的WPF应用程序... [ ^ ] 另请参见: 使用CodeDom生成代码 [ ^ ]. 在.NET计算器中使用CodeDOM编译器的重要示例: 创建使用可重载插件的WPF应用程序... [ ^ ].

—SA

尝试使用版本,区域性和PublicKeyToken加载程序集

Assembly.Load (" SampleAssembly,版本= 2.0.0000.0,Culture = neutral,PublicKeyToken = 12312320f8da049e3" );

我需要做的只是打电话,所以尽管SAK的解决方案很有意义(谢谢!),但我还是决定只使用

ILib l = (ILib)ad.CreateInstanceAndUnwrap("ExtensionLib", "ExtensionLib.LibImpl");

做到这一点就好了.此外,我可以更改不同域上的接口,并且它们仍然以某种方式兼容.我确定透明代理会进行一些时髦的跳舞. 谢谢大家!

I''m trying to create a small plugin framework, and have been going around and around the AppDomain code with not much luck. The most important thing for me is that I want to have no conflicts between different versions of the same class (for example a plugin may want to use its own Common.dll v 1.0 library whereas I may have 2.0), similar to other issues. So I wrote the small app below.

static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Console.WriteLine(Utility.GetVersion()); var ads = new AppDomainSetup(); string appBase = @"../../ExtensionLib/ExtensionLib/bin/Debug"; ads.ApplicationBase = appBase; //ads.PrivateBinPath = appBase; //ads.ConfigurationFile = "ExtensionLib.dll.config"; //ads.PrivateBinPathProbe = "."; var ad = AppDomain.CreateDomain("Extension App", null, ads); // var ah = new AssemblyHelper(); // ad.AssemblyResolve += ah.MyResolveEventHandler; // ad.AssemblyLoad += ah.AssemblyLoadedHandler; //MessageBox.Show(ad.BaseDirectory); Assembly a = ad.Load("ExtensionLib"); ILib l = (ILib) a.CreateInstance("LibImpl"); l.DoSomething(); Console.WriteLine(Utility.GetVersion()); } }

Common.dll contains the Utility class, but we have different versions of that class. Both the plugin and the host application use the same ILib (defined on the same dll). Host Application Setup

c:\....\123 Common.dll (v 2.0) IntegInterface.dll (where ILib is defined, v1.0) LoadCommon.exe (the host)

Plugin Application Setup

c:\....\456 Common.dll (v 1.0) IntegInterface.dll (where ILib is defined, v1.0) ExtensionLib.dll (the plugin)

When the app runs, I get an exception at the moment of ad.Load()

System.IO.FileNotFoundException was unhandled Message="Could not load file or assembly ''ExtensionLib'' or one of its dependencies. The system cannot find the file specified." Source="mscorlib" FileName="ExtensionLib" FusionLog="Assembly manager loaded from: C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\mscorwks.dll Running under executable C:\\Users\\Roberto\\Documents\\Visual Studio 2008\\Projects\\LoadCommon\\LoadCommon\\bin\\Debug\\LoadCommon.vshost.exe --- A detailed error log follows. \n === Pre-bind state information === LOG: User = Roberto-PC\\Roberto LOG: DisplayName = ExtensionLib\n (Partial) LOG: Appbase = file:///C:/Users/Roberto/Documents/Visual Studio 2008/Projects/LoadCommon/LoadCommon/ExtensionLib/ExtensionLib/bin/Debug LOG: Initial PrivatePath = NULL Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Using application configuration file: C:\\Users\\Roberto\\Documents\\Visual Studio 2008\\Projects\\LoadCommon\\LoadCommon\\ExtensionLib\\ExtensionLib\\bin\\Debug\\ExtensionLib.dll.config LOG: Using machine configuration file from C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\config\\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). " StackTrace: at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.AppDomain.Load(String assemblyString) at System.AppDomain.Load(String assemblyString) at LoadCommon.Program.Main() in C:\Users\Roberto\Documents\Visual Studio 2008\Projects\LoadCommon\LoadCommon\Program.cs:line 36 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

I also tried to setup an the assemblyresolve delegate to see if I could help, no luck however, I ended up with Serialization errors even though I did tag AssemblyHelper as serializable. At some point I will also have the IntegInterface have different versions, and am sure I will end up with a whole slew of issues. Can someone shed some light here? Very much appreciated. Thanks

解决方案

This is the usual confusion about loading assembly. Do you want to load Assembly by the file name of its main executable module? Use System.Reflection.Assembly.LoadFrom(string fileName). See all other System.Reflection.Assembly.Load... methods and help pages on their differences. This call should be done in the newly created Application Domain context, not in your default (initial) Application Domain of your process. If my assumption about your plug-in assembly was wrong, please free to correct me, I''ll give you a bit different approach.

System.AppDomain ad = AppDomain.CreateDomain("Extension App", null, ads); ad.DoCallBack(() => { //... System.Reflection.Assembly.LoadFrom(myPluginFileName); //... });

If your plug-in Assembly has an entry point (EXE file) you can use System.AppDomain.ExecuteAssembly. I doubt you design you plug-ins this way (you mentioned ILib interface; if this is the interface supported by your plug-in — congratulations! This is the best approach. See be reference below on using a special assembly attribute to select a class implementing plug-in interface &mdas; very good for robustness and performance). So, even though I don''t think your design is not bases on EXE entry point, let me show this just in case:

System.AppDomain ad = AppDomain.CreateDomain("Extension App", null, ads); ad.ExecuteAssembly(myExeFileName);

This is great that you understand importance of loading plug-ins dynamically in the separate Application Domain, but this is only needed if you want to unload them later. In you need to load all plug-ins only once, work in one domain, your default one, do not create an extra Application Domain. You can real all my Answers about plug-in Assemblies and using Application Domain, a variety of designs: Create WPF Application that uses Reloadable Plugins...[^] See also: code generating using CodeDom[^]. Important example of use with CodeDOM compiler for use in .NET calculator: Create WPF Application that uses Reloadable Plugins...[^].

—SA

Try to load the assembly with the version, culture and PublicKeyToken

Assembly.Load ("SampleAssembly, Version=2.0.0000.0, Culture=neutral, PublicKeyToken=12312320f8da049e3");

All I needed to do was make a call, so although SAK''s solution makes sense (thanks!), I decided to just use

ILib l = (ILib)ad.CreateInstanceAndUnwrap("ExtensionLib", "ExtensionLib.LibImpl");

which does the trick just fine. Furthermore, I can change the interface on the different domains and they are still somehow compatible. The transparent proxy does some funky dancing i''m sure. Thanks all!

更多推荐

AppDomain拒绝加载程序集

本文发布于:2023-11-06 13:57:45,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1563887.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:加载   程序   AppDomain

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!