插件加载到 appDomain 的 mySQL 错误

Posted

技术标签:

【中文标题】插件加载到 appDomain 的 mySQL 错误【英文标题】:mySQL error with plugin loaded into appDomain 【发布时间】:2011-06-17 16:14:12 【问题描述】:

我正在努力使用我的插件进行动态加载。我正在将插件加载到 appdomain 中,但是当我的插件尝试执行任何 mysql 代码时出现以下异常:

MySql.Data.MySqlClient.MySqlException 未处理 消息=拒绝访问 对于用户''@'localhost'(使用 密码:否)

这是 Plugins.cs 上的代码:

public class Plugins 

private static List<PluginContainer> PluginList;
public static bool PluginsAreLoaded 
get 
if(PluginList==null) 
return false;

else 
return true;




public static void LoadAllPlugins(Form host) 
//add assemblies in OD folder to appDomain
Assembly[] list = AppDomain.CurrentDomain.GetAssemblies();
AppDomain appDomainAnesthesia AppDomain.CreateDomain("appDomainAnesthesia");
for(int i=0;i<ProgramC.Listt.Count;i++) 
string dllPathWithVersion = String.Empty;
if(!ProgramC.Listt[i].Enabled) 
continue;

if(ProgramC.Listt[i].PluginDllName=="") 
continue;

string dllPath=ODFileUtils.CombinePaths(Application.StartupPath,ProgramC.Listt[i].PluginDllName);
if(dllPath.Contains("[VersionMajMin]")) 
Version vers=new Version(Application.ProductVersion);
dllPathWithVersion=dllPath.Replace("[VersionMajMin]",vers.Major.ToString()+"."+vers.Minor.ToString());
dllPath=dllPath.Replace("[VersionMajMin]","");//now stripped clean
if(File.Exists(dllPathWithVersion))
File.Copy(dllPathWithVersion,dllPath,true);


if(!File.Exists(dllPath)) 
continue;

//add our plugin to the appDomain
try                        
string typeName = Path.GetFileNameWithoutExtension(dllPath) + ".Plugin";
PluginBase plugin = (PluginBase)appDomainAnesthesia.CreateInstanceAndUnwrap(Path.GetFileNameWithoutExtension(dllPathWithVersion), typeName);
appDomainAnesthesia.Load(Path.GetFileNameWithoutExtension(dllPathWithVersion));
plugin.Host=host;

catch(Exception ex) 
MessageBox.Show(ex.Message);
continue;//don't add it to plugin list.
       
PluginContainer container=new PluginContainer();
container.Plugin=plugin;
container.ProgramNum=ProgramC.Listt[i].ProgramNum;
PluginList.Add(container);



这里是插件库:

public abstract class PluginBase : MarshalByRefObject 
private Form host;
///<summary>This will be a refrence to the main FormOpenDental so that it can be used by    the plugin if needed.  It is set once on startup, so it's a good place to put startup code.</summary>
public virtual Form Host  
get  
return host; 

set 
host=value; 



///<summary>These types of hooks are designed to completely replace the existing functionality of specific methods.  They always belong at the top of a method.</summary>
public virtual bool HookMethod(object sender,string methodName,params object[] parameters) 
return false;//by default, no hooks are implemented.

///<summary>These types of hooks allow adding extra code in at some point without disturbing the existing code.</summary>
public virtual bool HookAddCode(object sender,string hookName,params object[] parameters) 
return false;

public virtual void LaunchToolbarButton(long patNum) 

插件容器:

class PluginContainer 
public PluginBase Plugin;
public long ProgramNum;

最后,插件:

public class Plugin : PluginBase  
private Form host;
public AnestheticData AnesthDataCur;
public AnestheticRecord AnestheticRecordCur;
public Patient PatCur;
public string SourceDirectory;
public string DestDirectory;
public System.ComponentModel.IContainer components;
public long patNum;
public static Procedure procCur;
public static List<Procedure> ProcList;
public static ODtextBox textNotes;
public override Form Host 
get  
return host; 

set 
host=value;
ConvertAnesthDatabase.Begin();//if this crashes, it will bubble up and result in the plugin not loading.                                                                                                 

它轰炸了

plugin.Host=host; 

Plugins.cs 上的行来自 ConverAnesthDatabase.Begin() 方法,因为那里有多个 mySQL 语句。

我可以访问 mySQL 数据库,所以这不是问题。

如何解决此错误?

【问题讨论】:

当您将ConvertAnesthDatabase.Begin(); 直接放在应用程序中而不是动态加载它时,它是否工作? 是的。如果我从 PluginBazse 中删除 :MarshalByRefObject 没有任何问题。 我只是在这里猜测,因为我在您的示例中找不到任何 mysql 代码,但可能是您在一个 AppDomain 的静态字段中设置用户名和密码,然后尝试在其他AppDomain中使用它们? 【参考方案1】:

尽量不要“扩展”您的 PluginBase 而是使用接口:

public interface IPlugin

    Form Host get; set; 
    bool HookMethod(object sender,string methodName,params object[] parameters);
    bool HookAddCode(object sender,string hookName,params object[] parameters);
    void LaunchToolbarButton(long patNum);

然后

public class Plugin : IPlugin

    ...

【讨论】:

进行了更改,但是当我尝试构建时,我得到:错误 3 'OpenDentBusiness.Iface.HookAddCode(object, string, params object[])': interface members cannot have a definition C:\用户\wjs\Desktop\ODVersions\opendental11.0b\opendental11.0\OpenDentBusiness\Plugins\PluginBase.cs 24 8 OpenDentBusiness 你的界面是什么样子的?有没有在接口中实现HookAddCode-方法,因为接口不能实现,需要在Plugin本身实现? Jan-Peter - 它们没有在 Current.Domain 中设置为静态字段,但它们被传递给表单的静态实例。 chrfin - 感谢您的帮助 - 不幸的是,我无法控制插件界面,因为我的插件用于另一个开源程序。

以上是关于插件加载到 appDomain 的 mySQL 错误的主要内容,如果未能解决你的问题,请参考以下文章

防止代码被加载到另一个 AppDomain

将 DLL 加载到具有已知唯一公共接口的单独 AppDomain 中

受限 AppDomain 中的加载项应如何访问升级服务

消息泵和 AppDomain

一个appdomain可以限制在一个目录吗?

AppDomain 中的对象被垃圾收集