0

I am struggling to get dynamic loading working with my plugin. I'm loading the plugin into an appdomain but I get the following exception when my plugin tries to execute any mySQL code:

MySql.Data.MySqlClient.MySqlException was unhandled
Message=Access denied for user ''@'localhost' (using password: NO)

Here is the code on 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);
}

}

Here is PluginBase:

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) {
}

}

PluginContainer:

class PluginContainer {
public PluginBase Plugin;
public long ProgramNum;

and finally, Plugin:

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.                                                                                                 }
}

It bombs at the

plugin.Host=host; 

line on Plugins.cs which comes from the ConverAnesthDatabase.Begin() method as there are multiple mySQL statements there.

I have access to the mySQL database, so that is not the issue.

How do I resolve this error?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Does the `ConvertAnesthDatabase.Begin();` work, when you place it directly inside your application and not load it dynamicaly? – Christoph Fink Jun 17 '11 at 16:20
  • Yes. I don't have any problems if I remove the :MarshalByRefObject from PluginBazse. – William J. Starck Jun 17 '11 at 19:33
  • I'm just guessing here as i can't find any `mysql` code in your examples, but could it be that you are setting username and password in static fields in one `AppDomain` and then try to use them in the other `AppDomain`? – Jan-Peter Vos Jun 17 '11 at 21:09

1 Answers1

0

Try not to "extend" your PluginBase and use an Interface instead:

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);
}

and then

public class Plugin : IPlugin
{
    ...
}
Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
  • Made that change, but when I try to build I get:Error 3 'OpenDentBusiness.Iface.HookAddCode(object, string, params object[])': interface members cannot have a definition C:\Users\wjs\Desktop\ODVersions\opendental11.0b\opendental11.0\OpenDentBusiness\Plugins\PluginBase.cs 24 8 OpenDentBusiness – William J. Starck Jun 17 '11 at 19:55
  • How does you interface look like? Did you implement the `HookAddCode`-method in the interface, because you can't do that with interfaces, you need to implement it in the Plugin itself? – Christoph Fink Jun 18 '11 at 07:03
  • Jan-Peter - they're not set as static fields in the Current.Domain, but they are passed in to a static instance of a form. chrfin - Thanks for your help - Unfortunately, I don't have any control over the plugin interface, as my plugin is for another open source program. – William J. Starck Jun 19 '11 at 01:11