Page 1 of 1

mySQL exception loading plugin into appDomain

Posted: Tue Jun 14, 2011 10:25 am
by wjstarck
Here is a slightly modified LoadAllPlugins method from OpentBusiness.Plugins:

Code: Select all

public static void LoadAllPlugins(Form host) {
	//add assemblies in OD folder to appDomain
	AppDomain appDomainAnesthesia = null;
	Assembly[] list = AppDomain.CurrentDomain.GetAssemblies();
	appDomainAnesthesia = AppDomain.CreateDomain("appDomainAnesthesia");
	foreach (Assembly a in list) {
		string path = a.Location;
		Assembly ass = Assembly.LoadFile(path);
		try {
			PluginBase plugin = (PluginBase)appDomainAnesthesia.CreateInstanceAndUnwrap(Path.GetFileNameWithoutExtension(path), a.FullName.ToString());
		} catch { }
	}
	list = appDomainAnesthesia.GetAssemblies();

	//No need to check RemotingRole; no call to db.
	PluginList=new List<PluginContainer>();
	if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
		return;//no plugins will load.  So from now on, we can assume a direct connection.
	}
			
	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

		PluginBase plugin=null;
		try {						
			Assembly ass=Assembly.LoadFile(dllPath);
			typeName=Path.GetFileNameWithoutExtension(dllPath)+".Plugin";
			//Type type=ass.GetType(typeName); 	//<---Current OD code
			//plugin=(PluginBase)Activator.CreateInstance(type); //<---Current OD code
			plugin = (PluginBase)appDomainAnesthesia.CreateInstanceAndUnwrap(Path.GetFileNameWithoutExtension(dllPathWithVersion), typeName);
			list = appDomainAnesthesia.GetAssemblies();
			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);
		//Active=true;
	}

}
The objective is to load the OD assemblies and the plugin into an appDomain so that the plugin can be dynamically loaded/unloaded by unloading the appDomain without quitting OD. I have PluginBase class inheriting from MarshalByRefObject, otherwise everything else is unmodified.

Everything loads fine into the appDomain, but I get an exception right after plugin.Host = host. The exception is "Access denied for user ''@'localhost' (using password: NO)". Here is the stack trace:

Code: Select all

MySql.Data.MySqlClient.MySqlException was caught
  Message=Access denied for user ''@'localhost' (using password: NO)
  Source=MySql.Data
  ErrorCode=-2147467259
  Number=0
  StackTrace:
       at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
       at MySql.Data.MySqlClient.NativeDriver.AuthenticateNew()
       at MySql.Data.MySqlClient.NativeDriver.Authenticate()
       at MySql.Data.MySqlClient.NativeDriver.Open()
       at MySql.Data.MySqlClient.Driver.Open()
       at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings)
       at MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection()
       at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection()
       at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver()
       at MySql.Data.MySqlClient.MySqlPool.GetConnection()
       at MySql.Data.MySqlClient.MySqlConnection.Open()
       at OpenDentBusiness.DataConnection.NonQ(String commands, Boolean getInsertID, OdSqlParameter[] parameters) in C:\Users\wjs\Desktop\ODVersions\opendental11.0b\opendental11.0\OpenDentBusiness\Db\DataConnection.cs:line 464
       at OpenDentBusiness.DataCore.NonQ(String command, Boolean getInsertID, OdSqlParameter[] parameters) in C:\Users\wjs\Desktop\ODVersions\opendental11.0b\opendental11.0\OpenDentBusiness\Db\DataCore.cs:line 34
       at OpenDentBusiness.DataCore.NonQ(String command, OdSqlParameter[] parameters) in C:\Users\wjs\Desktop\ODVersions\opendental11.0b\opendental11.0\OpenDentBusiness\Db\DataCore.cs:line 44
       at Anesthesia.ConvertAnesthDatabase.To7_1_0()
       at Anesthesia.ConvertAnesthDatabase.Begin()
       at Anesthesia.Plugin.set_Host(Form value)
       at OpenDentBusiness.PluginBase.set_Host(Form value)
       at OpenDentBusiness.Plugins.LoadAllPlugins(Form host) in C:\Users\wjs\Desktop\ODVersions\opendental11.0b\opendental11.0\OpenDentBusiness\Plugins\Plugins.cs:line 80
  InnerException: 
Any ideas?

Re: mySQL exception loading plugin into appDomain

Posted: Thu Jun 16, 2011 1:02 pm
by jordansparks
You're making my brain hurt. Why are you asking me these difficult questions that I don't know the answer to?

Re: mySQL exception loading plugin into appDomain

Posted: Thu Jun 16, 2011 1:05 pm
by wjstarck
You think your brain hurts..... :shock:

Re: mySQL exception loading plugin into appDomain

Posted: Thu Jun 16, 2011 5:31 pm
by jordansparks
I think this line in the stack trace is the key:
Anesthesia.ConvertAnesthDatabase.To7_1_0()

I also notice that the exception says ''@'localhost' . I would have expected it to say 'root'@'localhost'.

So I think your plugin is trying to send db commands before the db variables are initialized. Are you sure LoadAllPlugins is being called from the usual place? I haven't looked at that part of the code for a while. I can't remember where it usually happens. It needs to happen after the db variables are initialized.

Re: mySQL exception loading plugin into appDomain

Posted: Fri Jun 17, 2011 6:11 am
by wjstarck
jordansparks wrote: Are you sure LoadAllPlugins is being called from the usual place?
It seems to be. FormOpenDental.cs line 1431. Looks to me like that's after all the db stuff, which is 1383-1482