Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Adding a control from a different AppDomain... how?

426 views
Skip to first unread message

ThunderMusic

unread,
Jan 14, 2008, 11:33:31 AM1/14/08
to
Hi,
I currently have an application that must load plugins. It's impossible to
unload an assembly inside a single AppDomain, so I must create a different
AppDomain for each plugin I load so I can uload it when I don't need it
anymore. In the design document I received, I have to create the following :
"Load the assembly, get the configuration user control, display the user
control... When the user control is not needed anymore, unload the
assembly."... I can load the assembly (in a different appdomain), I can get
the user control, I can unload the assembly (by unloading the appdomain),
but I can't display the user control because I receive an exception (which I
don't really understand) : "Remoting cannot find field 'parent' on type
'System.Windows.Forms.Control'."... How can it not find the field 'parent'?
Is there a way to make it work? I can't believe MS didn't think about this
possibility which is used in about all "plugin based" application, so there
must be something I'm missing.

Thanks

ThunderMusic


Nicholas Paldino [.NET/C# MVP]

unread,
Jan 14, 2008, 11:46:24 AM1/14/08
to
The solution that you have right now is to use the System.AddIn
namespace, and use a WPF control from another app domain (this scenario is
supported). The WPF control would then have Windows Forms controls embedded
in it (through Windows Forms <-> WPF interop) and you would embed that
control on your form. Here is the post from the CLR Add-In Team Blog which
explains the process:

http://blogs.msdn.com/clraddins/archive/2008/01/03/support-for-windows-forms-in-hosts-and-add-ins.aspx


--
- Nicholas Paldino [.NET/C# MVP]
- m...@spam.guard.caspershouse.com

"ThunderMusic" <NoSpAmdanlata...@NoSpAm.com> wrote in message
news:%236P7tts...@TK2MSFTNGP05.phx.gbl...

Jon Skeet [C# MVP]

unread,
Jan 14, 2008, 11:52:04 AM1/14/08
to
On Jan 14, 4:33 pm, "ThunderMusic"

My experience is that this will work, with a *lot* of careful work, so
long as you make the plugins each have their own message pump. They
need to be in their own windows which are then reparented (Windows
SetParent call). Be very careful when threading calls between the
plugin and the host. Never create a control on a thread or in an
appdomain other than the one which it will essentially be running in.

You'll find a lot of posts saying all of this can't be done. It can,
but you need to be careful - and you really do need a message pump in
each AppDomain.

Jon

ThunderMusic

unread,
Jan 14, 2008, 11:59:18 AM1/14/08
to
hi, thanks for your answer... but it would require framework 3.5 and we
have to use 2.0 right now because the application has been created some time
ago and we only have VS 2005...

Thanks

ThunderMusic

"Nicholas Paldino [.NET/C# MVP]" <m...@spam.guard.caspershouse.com> wrote in
message news:%23wfuZxs...@TK2MSFTNGP02.phx.gbl...

ThunderMusic

unread,
Jan 14, 2008, 12:10:05 PM1/14/08
to
Hi, thanks for your answer....

you say : "Never create a control on a thread or in an appdomain other than
the one which it will essentially be running in."...
How can I create a control directly from my application's AppDomain if I
want to load it from the assembly and unload (or dispose) the assembly
afterward? To do this, I must create it in a different AppDomain (if I
understand it all right). Actually, all we need to do is done and working,
except this point... If we load the assembly from the main AppDomain,
everything works great, but we need to unload the assemblies so we don't
take like 1gb of memory... ;) the plugins can be pretty big (like 10-12Mb
each) and there can be many (up to int.Max) so we don't want our users to
have to restart the application because they loaded up too many plugins in
the same session just because we can't unload them...

Take for instance, a product that is well known (not MS tought), Cakewalk
Sonar, or Digidesign Protools (audio products)... They use VST plugins (and
many others types)... each plugin has it's own UI for configuration...
That's exactly what we want to do... Can you imagine such products if they
didn't unload the plugins they used in the session? the memory would
increase and increase so nothing else can be done... it would be awful...

Well anyway... I use different AppDomain to load the assemblies, get the
Usercontrols from these appdomains and keep the appdomain alive during all
my use of the created usercontrol, and unload the appdomain when the
usercontrol is not needed anymore and the process is done... If it is in
anyway possible to unload an assembly from the main appdomain or to use a
user control from a second appdomain, I need to know how... ;)

Thanks a lot

ThunderMusic


"Jon Skeet [C# MVP]" <sk...@pobox.com> wrote in message
news:33a2d533-d403-4ae3...@k2g2000hse.googlegroups.com...

london calling

unread,
Jan 14, 2008, 12:28:00 PM1/14/08
to
Hi ThunderMusic.. No real answers but maybe some things to think about.. Does
the UI and the actual bones of the processing (I'm assuming audio FX) have to
be in the same assembly? If not the UI can be part of the same App domain and
just create 'unloadable' appdomains to host the processors as required.. Also
are the assemblies so big because they contain lots of embedded resources? if
so could they be moved to disk and forget unloading the assembly? just a
thought.. jd

Jon Skeet [C# MVP]

unread,
Jan 14, 2008, 12:48:46 PM1/14/08
to
ThunderMusic <NoSpAmdanlata...@NoSpAm.com> wrote:
> Hi, thanks for your answer....
>
> you say : "Never create a control on a thread or in an appdomain other than
> the one which it will essentially be running in."...
> How can I create a control directly from my application's AppDomain if I
> want to load it from the assembly and unload (or dispose) the assembly
> afterward?

You need to load one of your assemblies into the new AppDomain, and get
that to create the control.

> To do this, I must create it in a different AppDomain (if I
> understand it all right). Actually, all we need to do is done and working,
> except this point... If we load the assembly from the main AppDomain,
> everything works great, but we need to unload the assemblies so we don't
> take like 1gb of memory... ;) the plugins can be pretty big (like 10-12Mb
> each) and there can be many (up to int.Max) so we don't want our users to
> have to restart the application because they loaded up too many plugins in
> the same session just because we can't unload them...

Indeed. That's one of the reasons we do it too.

> Take for instance, a product that is well known (not MS tought), Cakewalk
> Sonar, or Digidesign Protools (audio products)... They use VST plugins (and
> many others types)... each plugin has it's own UI for configuration...
> That's exactly what we want to do... Can you imagine such products if they
> didn't unload the plugins they used in the session? the memory would
> increase and increase so nothing else can be done... it would be awful...
>
> Well anyway... I use different AppDomain to load the assemblies, get the
> Usercontrols from these appdomains and keep the appdomain alive during all
> my use of the created usercontrol, and unload the appdomain when the
> usercontrol is not needed anymore and the process is done... If it is in
> anyway possible to unload an assembly from the main appdomain or to use a
> user control from a second appdomain, I need to know how... ;)

No, you can't unload a single assembly from an AppDomain, you have to
unload the whole AppDomain. The important bit is to get some of your
own code (just enough) running in the new AppDomain, so that you can
control it from your "main" AppDomain but still create appropriate
objects (most importantly UI controls) inside the new AppDomain, in the
right thread.

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

london calling

unread,
Jan 14, 2008, 12:50:00 PM1/14/08
to
Maybe more helpful.. check out the System.AddIn namespace/subspaces.. HTH jd

london calling

unread,
Jan 14, 2008, 12:55:02 PM1/14/08
to
sorry.. it's a 3.5 namespace..

ThunderMusic

unread,
Jan 14, 2008, 1:08:36 PM1/14/08
to
Hi,
It actually not audio FX... The current architecture is that we have a
Windows service running which is loading the assemblies to run some
monitoring modules. There's also a "client" application which connects to
the Windows service and asks for a list of the loaded modules and displays
them in a treeview (for design purposes). When the user clicks on the node
of a module, it can see it's configuration control appear in the panel
beside the treeview. Well, that's actually what it should do... Passing a
control via remoting alone doesn't work at all... Actually, the control
goes though, but I can't add it to the panel saying it can't call a static
method remotly... anyways... so we decided to send the library itself (in a
byte[]) via remoting and the client app loads it dynamicly to get the
control and then binds it to the proxy to the remote class in the service to
the module it must be bound to. Right now, everything works fine if we load
the assembly locally in the main AppDomain, but it seems that if remoting is
involved at all, nothing can be done for user controls even if it's
"transparent"...

So we'll try to find something to solve our problem...

Thanks

ThunderMusic

"london calling" <london...@discussions.microsoft.com> wrote in message
news:49398ED9-CDF0-420F...@microsoft.com...

ThunderMusic

unread,
Jan 14, 2008, 1:09:25 PM1/14/08
to
thanks a lot for your help... ;)

"Jon Skeet [C# MVP]" <sk...@pobox.com> wrote in message

news:MPG.21f5b0d...@msnews.microsoft.com...

london calling

unread,
Jan 15, 2008, 6:42:11 PM1/15/08
to
we are aware of the passage of time, we measure it; and in fact we
act as if we were awake. So that half of our life being passed in sleep, we
have on our own admission no idea of truth, whatever we may imagine. As all
our intuitions are, then, illusions, who knows whether the other half of our
life, in which we think we are awake, is not another sleep a little
different from the former, from which we awake when we suppose ourselves
asleep?

And who doubts that, if we dreamt in company, and the dreams chanced to
agree, which is common enough, and if we were always alone when awake, we
should believe that matters were reversed? In short, as we often dream that
we dream, heaping dream upon dream, may it not be that this half of our
life, wherein we think ourselves awake, is itself only a dream on which the
others are grafted, from which we wake at death, during which we have as few
principles of truth and good as during natural sleep, these different
thoughts which disturb us being perhaps only illusions like the flight of
time and the vain fancies of our dreams?

These are the chief arguments on one side and the other.

I omit minor ones, such as the sceptical talk against the impressions of
custom, education, manners, country and the like. Though these influence the
majority of common folk, who dogmatise only on shallow foundations, they are
u


Bill Woodruff

unread,
Jan 17, 2008, 11:27:50 PM1/17/08
to
Visual Studio 2005, .NET FrameWork 2.0, C#, WinForms Application

Hi,

I've read the recent posts by and to 'Thunderbird' (and learned a lot,
thanks, from the usual masters Skeet and Paladino, and others) which involve
AppDomains in a remoting scenario, but I think the issue I am working with
... while related ... is sufficiently different to warrant a new thread.

I'm also working on a plug-in architecture it's for a WinForms based
project.

At run-time I "discover" and load all the Plug-Ins that match a MainApp
Interface with no problem.

I find I can pass complex objects (like the TreeNode of a TreeView) to the
plug-ins' AppDomain, and modify certain properties and have the result show
up in the Main App's UI, no problem.

What I find I can't do ... I assume because WinForm objects like a TreeView
and the Nodes collection object of a TreeView are passed as proxies ... is
create new Nodes in the plug-in app domain and then pass them back to the
Main app and put them in the TreeView in the UI there.

Error trying to create a new TreeView Node in the Plug-In appDomain (yes,
Plug-Ins do contain references for WinForms) :

"SerializationException Crossed an AppDomain Boundary"

Type 'System.Windows.Forms.Control+ControlCollection' in assembly
'System.Windows.Forms, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089' is not marked as serializable.

"Ideally" I'd like to pass the Plug-In a bounding rectangle definition, have
it create a collection of controls, and get those controls back to the Main
AppDomain and plug them into a Panel and then have the Plug-In, based on the
state of its controls, do the "right thing" to conjure up whatever objects
it wants to create and get those objects back to the Main App for
display/use in the main UI.

At this point I believe that is simply not possible ... although Jon Skeet's
comments in his reply to Thunderbird are still inviting me to reconsider and
re-think.

What I do believe is most probable is that there is an optimum architecture
for a situation where :

1. you want to load plug-ins in a separate appDomain (in T'Bird's case one
appDomain per plug-in). so you can unload at will.

2. you want the plug-in to specify its run-time user interface to the Main
appDomain in some terse, easily parsable form.

3. you want the Main appDomain to present the Plug-In's controls/widgets in
the main UI, let the user alter their state at run-time.

4. you want the Plug-In (through direct action at run-time) to trigger some
process that results in modification of complex objects, or creation of new
ones in the Main appDomain.

Appreciate any feedback. I have examined the various add-in/plug-in projects
of CodeProject, the usual books (Petzold, Sells, Liberty, Gunnerson).

It would help me greatly if I had a better sense of exactly what a "proxy"
is, and I appreciate any referrals to learning materials in that area.

thanks !

Bill Woodruff
dotScience
Chiang Mai, Thailand


Jon Skeet [C# MVP]

unread,
Jan 19, 2008, 3:03:09 AM1/19/08
to
Bill Woodruff <msnws...@dotscience.com> wrote:

<snip>

> At this point I believe that is simply not possible ... although Jon Skeet's
> comments in his reply to Thunderbird are still inviting me to reconsider and
> re-think.

Well, it sounds like we're doing significantly different things. In my
case I was able to have a whole area of the main UI which the plugin
"owned", running that UI in a different thread.

> What I do believe is most probable is that there is an optimum architecture
> for a situation where :
>
> 1. you want to load plug-ins in a separate appDomain (in T'Bird's case one
> appDomain per plug-in). so you can unload at will.
>
> 2. you want the plug-in to specify its run-time user interface to the Main
> appDomain in some terse, easily parsable form.
>
> 3. you want the Main appDomain to present the Plug-In's controls/widgets in
> the main UI, let the user alter their state at run-time.
>
> 4. you want the Plug-In (through direct action at run-time) to trigger some
> process that results in modification of complex objects, or creation of new
> ones in the Main appDomain.

Right, that sounds like a reasonable architecture, yes. Easier with WPF
of course, because of the business of specifying the user interface is
easy :)

> It would help me greatly if I had a better sense of exactly what a "proxy"
> is, and I appreciate any referrals to learning materials in that area.

Yes - AppDomains and marshalling is a fairly difficult topic to find
information about. Basically anything which derives from
MarshalByRefObject can be marshalled across an AppDomain boundary by
(automatically) creating a proxy which has a reference to the original
object. However, there are limitations as to what you can do, and I'm
afraid I'm far from an expert on that side of things :(

I basically try to do as little as possible across the app domain
boundary.

Patrick

unread,
Nov 2, 2009, 7:50:13 PM11/2/09
to
How do you get the plugin to be in the main UI?

When I try to add the plugin control to the main UI controls list I get an exception that says the field 'parent' is not accessable.

This is because the control is being remoted.

From http://www.developmentnow.com/g/36_2008_1_0_0_1048063/Adding-a-control-from-a-different-AppDomain---how.htm

Posted via DevelopmentNow.com Groups
http://www.developmentnow.com/g/

0 new messages