Problems with MDI plugins using AppDomain
-
28 aprilie 2012 16:47
Hi all!
I'm making a plugin system for my MDI application.
First I used a way without using AppDomain's and it worked but their were some problems, "could not unload the dll etc.."
So I looked on google how to make it unloadable and found out that I had to use AppDomain's so I did.
They use Interfaces to cast types.
This is the code where it loads:
void appmenu_Click(object sender, EventArgs e) { appMenuToolStripItem instance = (appMenuToolStripItem)sender; //try //{ AppDomain domain = AppDomain.CreateDomain(instance.Program.ID.ToString()); Object obj = domain.CreateInstanceFrom(instance.Program.Path, instance.Program.Type); StartApp(obj, domain); //} //catch (Exception ex) //{ // this.SendError(ex, instance.Program.Name); //} } private void StartApp(object obj, AppDomain domain) { IProgram program = (IProgram)obj; // InvalidCastException occures here. AsuraBarItem item = new AsuraBarItem(program.Name, program.icon); AsuraForm programfrm = program.GetForm; item.Program = program; item.ID = program.id; program.domain = domain; program.host = this; programfrm.MdiParent = this; this.AppBar.Items.Add(item); program.Show(); }I commented where the exception occures,
The exceptions tells me this:
System.InvalidCastException was unhandled
Message=Cannot convert transparentproxy totype AsuraOS.ProgramHelper.IProgram.If you need more info, just ask so I know wich part I need to add.
Thank you!Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's"- Mutat de CoolDadTxMVP 9 mai 2012 17:12 Winforms related (From:Visual C# General)
Toate mesajele
-
28 aprilie 2012 19:19
According to Documentation, try this: IProgram program = (IProgram)obj.Unwrap().
-
28 aprilie 2012 19:54
The method doesn't exist for a object,
'Error 1 'object' does not contain a definition for 'Unwrap' and no extension method 'Unwrap' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)'
EDIT
I had to use 'System.Runtime.Remoting' and then use ObjectHandle instead of Object.
So now is that problem fixed but now I get a new error.Should I make a new thread about it or continue it in this thread?
System.Runtime.Serialization.SerializationException was unhandled
Message=Type System.Windows.Forms.MdiClient+ControlCollection in assembly System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is not marked as serializable.
Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's"
- Editat de Matthias Beerens 28 aprilie 2012 20:19 New error
-
29 aprilie 2012 04:56
Hi,
Change the line to,
Object obj = domain.CreateInstanceAndUnwrap(instance.Program.Path
, instance.Program.Type);
If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".
- Editat de Kris444 29 aprilie 2012 04:56
-
29 aprilie 2012 06:56
I'm still getting the SerializationException
at this line:
/* The error: The type System.Windows.Forms.MdiClient+ControlCollection in assembly System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is not marked as serializable. */ private void StartApp(Object obj, AppDomain domain) { IProgram program = (IProgram)obj; AsuraBarItem item = new AsuraBarItem(program.Name, program.icon); AsuraForm programfrm = program.GetForm; item.Program = program; item.ID = program.id; program.domain = domain; program.host = this; programfrm.MdiParent = this; // Exception occures here this.AppBar.Items.Add(item); program.Show(); }Thanks alot already!
Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's" -
29 aprilie 2012 08:57
Try deriving your base plug-in class from MarshalByRefObject and do not make it serializable, since ControlCollection cannot be serialized.
-
29 aprilie 2012 10:04
I tried it but still getting the same error.
Let me show u what is inside my class that I'm trying to make a instance of.using System; using System.Drawing; using AsuraOS.ProgramHelper; namespace Super { /// <summary> /// The notepad controller /// </summary> public class Notepad : MarshalByRefObject, IProgram { frmNotepad frm; public Notepad() { frm = new frmNotepad(this._host, this); } Image IProgram.icon { get { ImageConverter conv = new ImageConverter(); return (Image)conv.ConvertFrom(frm.Icon); } } AppDomain _domain; AppDomain IProgram.domain { get { return _domain; } set { _domain = value; } } Guid _id = Guid.NewGuid(); Guid IProgram.id { get { return _id; } } IHost _host; IHost IProgram.host { get { return _host; } set { _host = value; } } void IProgram.Close() { frm.Close(); } void IProgram.Show() { frm.Show(); } void IProgram.PreviousSize() { frm.PreviousSize(); } string IProgram.Name { get { return frm.Text; } } AsuraForm IProgram.GetForm { get { return frm; } } } }And as I yet have to learn how to serialize a class etc.. I don't think I serialized anything.
So if u need more info just let me know.Thanks alot!
Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's" -
2 mai 2012 06:02
Hi,
I would recommend you double check whether the obj object being created is the target object you want. For this line of codes,
Object obj = domain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, "Super.Notepad");
Please make sure you passed the correct assembly path and the target type's Full Name, especially the Notepad's namespace. Only the type which inherits the IProgram can be used here.
Otherwise, if the problem still exists, could you please create a demo for us to do further investigation? You can ping me directly at misun@microsoft.com
Good day!
Thanks
Michael Sun [MSFT]
MSDN Community Support | Feedback to us
-
2 mai 2012 12:30Hey,
I've double checked, maybe their is some little thing I've missed or did something wrong.
So here is the demo, well it is more the full project.
http://www.mediafire.com/?2ctq3ry7x3d3dny
Thank you
Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's"
- Editat de Matthias Beerens 2 mai 2012 12:31 added link
-
2 mai 2012 15:53
Hi Matthias,
Thanks for sharing the demo! I have tested it and I found the exception is thrown at this line of the codes (in bold):
private void StartApp(Object obj, AppDomain domain) { IProgram program = (IProgram)obj; AsuraBarItem item = new AsuraBarItem(program.Name, program.icon); AsuraForm programfrm = program.GetForm; item.Program = program; item.ID = program.id; program.domain = domain; program.host = this; programfrm.MdiParent = this; this.AppBar.Items.Add(item); program.Show(); }The exception is SerializationException: "Type 'System.Windows.Forms.MdiClient+ControlCollection' in assembly 'System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable."
I remember that you used AppDomain since you want to unload certain assembly, right? However, in your codes, the MDI relationship are set between two forms and these two forms are at two different AppDomains. If it works, the Notepad MDI child form asembly should be loaded into the main form's AppDomain as well because the main form needs a reference to the MDI child form. So it seems the assembly is loaded in the memory twice. I don't think that's what you want, right?
I'd like to clarify why do you want to unload the assembly?
Good day!
Thanks
Michael Sun [MSFT]
MSDN Community Support | Feedback to us
-
2 mai 2012 16:57So my friend is making a 'fake os', alot of people seem to be doing it on youtube.
And as I already knew how to make plugins, I told him it would be great to make it so that you can make the app's in the 'os' as plugins. But we encountered some problems, for example if the app maker doesn't put a working code for closing the form when the IProgram.Close is called then the whole app would have to shutdown before it would work. So I searched for a way to force it to close and found out about appdomains, and now I'm focusing on learning about appdomains this way :)
I hope this explains it.
ThanksHope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's" -
3 mai 2012 12:20
But we encountered some problems, for example if the app maker doesn't put a working code for closing the form when the IProgram.Close is called then the whole app would have to shutdown before it would work.
Hi Matthias,
Thanks for the update! I just cannot quite understand the sentence I quoted. If we don't use another AppDomain, we can still set the MDI relationship and use the IProgram.Close method. I think AppDomain is for isolation purpose, however, if we set the MDI relationship between the form in two different AppDomain, we break the isolation.
Good day!
Thanks
Michael Sun [MSFT]
MSDN Community Support | Feedback to us
-
3 mai 2012 16:56Ow okay, I'll try to explain it better now :)
So, we are making forms (as plugins) to show into the MDI form. But to communicate with them I made a Interface 'IProgram' that has a method called 'Close' (IProgram.Close), so when the application has to close for example through the custom applicationbar I made then it will call the Close method from the interface. But if the maker of the pluginable application did not put a working code inside the Close method from the interface for example 'someform.close();', then the form would never close until the application restarts.
I hope you understand it now.
Thanks alot!Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's" -
4 mai 2012 01:59
Hi Matthias,
Yes, I understand it. But I don't think AppDomain can help here. the plugin forms can be in your main AppDomain as well. Could you please explain what's the problem if you use the main AppDomain to load the forms?
Have a nice weekend!
Thanks
Michael Sun [MSFT]
MSDN Community Support | Feedback to us
-
4 mai 2012 14:48Hi Michael,
Well if the form is 'malicious' like if they do not add a working code in the Close method from the interface and make it so the form can't close for example putting this code in the form closing event 'e.cancel = true;'
Then the form would be unable to close by clicking the [X] button in the form control box and the custom appbar. So thats why I wanted to use AppDomain's to unload it. Or wouldn't that work? Or is there a better way to do it.
Thanks alot! And u too have a nice weekend!Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's" -
5 mai 2012 07:56
Hi Matthias,
I think you may consider creating another process for each form and call the API SetParent, http://www.pinvoke.net/default.aspx/user32.setparent However, it's a little tricky, http://stackoverflow.com/questions/3459874/good-or-evil-setparent-win32-api-between-different-processes. But if it's another process, you can kill the process to let it exit.
Good day!
Thanks
Michael Sun [MSFT]
MSDN Community Support | Feedback to us
-
5 mai 2012 10:02Hi Michael,
I've already tried that some time ago,
But I didn't really like it. And I want to use plugins.
ThanksHope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's" -
6 mai 2012 05:52
Hi Matthias,
I will try to involve some senior engineers into this case. Thanks for your patience!
Have a nice weekend!
Thanks
Michael Sun [MSFT]
MSDN Community Support | Feedback to us
-
9 mai 2012 15:06Hi Michael,
Thank you for trying to involve some senior engineers to help me.
Have a nice day.Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's" -
18 mai 2012 08:55
You receive SerializationException exception in below code because you're trying to assign an object of frmMain (public partial class frmMain : Form, IHost ...) to a proxy object (which represent a Notepad object in a different appdomain), the 'this' object need to be marshaled to a different appdomain, however, some fields of frmMain class cannot be marshaled (neither serializable nor inherit from MarshalByRefObject).
private void StartApp(Object obj, AppDomain domain)
{
IProgram program = (IProgram)obj;
AsuraBarItem item = new AsuraBarItem(program.Name, program.icon);
AsuraForm programfrm = program.GetForm;
item.Program = program;
item.ID = program.id;
program.domain = domain;
program.host = this;
programfrm.MdiParent = this;
this.AppBar.Items.Add(item);
program.Show();
}Anyway, this falls into the paid support category which requires a more in-depth level of support. Please visit the below link to see the various paid support options that are available to better meet your needs.
http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone
Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
Regards,
Eric Yang
Microsoft Online Community Support -
7 iunie 2012 01:31
Did you ever find a good solution for this? I'm in exactly the same boat.
I'm in the process of developing a test platform. The platform will gather the data, and various tests (dll's) can be developed and loaded into the platform separately and dynamically.
I've been able to successfully load the assemblies into the main application domain, but if there is a problem with the test and it needs to be reloaded you are forced to shut the whole platform application down, recompile the test, restart the platform application, and reload your test. I really need a way to dynamically unload dll assemblies so I don't have to shut down the application. Additionally the test DLL's create an MDI child form that runs in the main testing platform application. This is important because the tests add menuList items to the main form.
I have also been able to create a new application domain and load the test assembly from there, but now the test loads as it's own application and not as an MDI child.
It's a fairly simple question...is it possible to dynamically load *and* unload a dll assembly that is an MDI child? I have spent days testing and googling and haven't found a solution.
-
7 iunie 2012 15:56
Hi Funjay23,
I never found a working solution for my problem and your problem is basically the same.
But you can always try the paid support.
I hope you find manage to find a solution to this problem someday.Best regards,
Matthias.Hope This Helps!
If this post answers your question, please click "Mark As Answer".
If this post is helpful please click "Mark as Helpful".
Else you got to wait until a MVP or MCC replies they are the "PRO's"