473,503 Members | 2,098 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Load and unload Child App Domain Assemblies

I am trying to load and unload assemblies dynamically and call methods
and properties when loaded into an Appdomain

I can load assemblies all day in the current AppDomain without
references and without interfaces if need be. But try as I may they
will ot unload. I have been working on this problem for weeks. I have
seen other apps using Remoting but I know there has got to be a way to
create a child AppDomain and reference obkect via reflection and uload
the child domain when finished.

My Scenario. I have windows services which are basically libraries
called obviously by a service wrapper. Since the wrapper does the
instansiation, I want to update these dlls without stopping and
restarting my service.

I have created a mockup using a form and a separate dll

Here is the mockup simple dll the form will call:

using System;

namespace TestClass
{
public class Test : MarshalByRefObject
{
public string GetResponse()
{
return "Test Response 1";
}
}
}
Here is the form code:
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;

namespace DomainTest
{

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnLoad;
private System.Windows.Forms.Button btnUnload;
private System.Windows.Forms.Button btnCall;
private System.Windows.Forms.TextBox txtResponse;

private AppDomain _runDomain;
private Assembly _assembly;
private Type _typTest;
Object _objTest;
AppDomainSetup _appSetup;

private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
_appSetup = new AppDomainSetup();
_appSetup.ApplicationBase =
@"E:\Development\.Net\CSharp\Examples\AppDomain\Ap pDomainEnvironment";
_runDomain = AppDomain.CreateDomain("MyDomain", null, _appSetup);
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnLoad = new System.Windows.Forms.Button();
this.btnUnload = new System.Windows.Forms.Button();
this.btnCall = new System.Windows.Forms.Button();
this.txtResponse = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// btnLoad
//
this.btnLoad.Location = new System.Drawing.Point(30, 35);
this.btnLoad.Name = "btnLoad";
this.btnLoad.Size = new System.Drawing.Size(70, 25);
this.btnLoad.TabIndex = 0;
this.btnLoad.Text = "Load";
this.btnLoad.Click += new System.EventHandler(this.btnLoad_Click);
//
// btnUnload
//
this.btnUnload.Enabled = false;
this.btnUnload.Location = new System.Drawing.Point(300, 35);
this.btnUnload.Name = "btnUnload";
this.btnUnload.Size = new System.Drawing.Size(70, 25);
this.btnUnload.TabIndex = 1;
this.btnUnload.Text = "Unload";
this.btnUnload.Click += new System.EventHandler(this.btnUnload_Click);
//
// btnCall
//
this.btnCall.Enabled = false;
this.btnCall.Location = new System.Drawing.Point(166, 35);
this.btnCall.Name = "btnCall";
this.btnCall.Size = new System.Drawing.Size(70, 25);
this.btnCall.TabIndex = 2;
this.btnCall.Text = "Call";
this.btnCall.Click += new System.EventHandler(this.btnCall_Click);
//
// txtResponse
//
this.txtResponse.Location = new System.Drawing.Point(30, 85);
this.txtResponse.Name = "txtResponse";
this.txtResponse.Size = new System.Drawing.Size(340, 20);
this.txtResponse.TabIndex = 3;
this.txtResponse.Text = "";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(402, 441);
this.Controls.Add(this.txtResponse);
this.Controls.Add(this.btnCall);
this.Controls.Add(this.btnUnload);
this.Controls.Add(this.btnLoad);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void btnLoad_Click(object sender, System.EventArgs e)
{
_assembly = AppDomain.CurrentDomain.Load("TestClass");
_typTest = _assembly.GetType("TestClass.Test");
_objTest = _runDomain.CreateInstance("TestClass", "TestClass.Test");
System.Diagnostics.Debug.WriteLine(_objTest.GetTyp e());

btnCall.Enabled = _objTest != null;
btnUnload.Enabled = _objTest != null;
btnLoad.Enabled = _objTest == null;
}

private void btnCall_Click(object sender, System.EventArgs e)
{
MethodInfo method = _typTest.GetMethod("GetResponse");
txtResponse.Text = (string) method.Invoke(_objTest, null);
}

private void btnUnload_Click(object sender, System.EventArgs e)
{
AppDomain.Unload(_runDomain);
btnCall.Enabled = false;
btnLoad.Enabled = true;
btnUnload.Enabled = false;
}
}
}
The Results:

The issue is that when calligna method off of the newly created object
I get the following error:

Object does not match target type.

I looked at the actual object type from the object created with this
line of code:

_objTest = _runDomain.CreateInstance("TestClass", "TestClass.Test");

The object is not a TestClass.Test Type object, it is a
System.Runtime.Remoting.ObjectHandle type object.

Soooooooooooooooooooo....

How to get around this? Am I even close here?

Nov 17 '05 #1
2 6854
Hi Brian,

You can use the "CreateInstanceAndUnwrap" method on the AppDomain, which
creates a new instance of the specified Type in the app domain. Below is
a sample:
AppDomain newAppdomain = AppDomain.CreateDomain("NewDomain");
AppDomainController controller =
(AppDomainController)newAppdomain.CreateInstanceAn dUnwrap(
"AppDomainSample", "AppDomainSample.AppDomainController");

CreateInstanceAndUnwrap will unwrap the handle, and convert it into an
object reference, which you can then cast to the correct Type.

Another thing I noticed: If you want to make sure that you can unload
the assembly successfully, you need to make sure that you do not
reference it in your original AppDomain.

For example, you do a:
_typTest = _assembly.GetType("TestClass.Test");

This will load the Type (and therefore it's assembly) in your original
AppDomain, which is probably NOT what you want.

If you use a controller class in the new AppDomain, you can go
indirectly through this controller, for example:

controller.Load("MyTestAssembly");
controller.Load("MyBadAssembly");

object result = controller.ExecuteMethod(
"MyTestAssembly",
"MyTestAssembly.MyClass",
"Add",
new object[] { 100, 22 });

Hope this helps,

Bennie Haelen
br*********@gmail.com wrote:
I am trying to load and unload assemblies dynamically and call methods
and properties when loaded into an Appdomain

I can load assemblies all day in the current AppDomain without
references and without interfaces if need be. But try as I may they
will ot unload. I have been working on this problem for weeks. I have
seen other apps using Remoting but I know there has got to be a way to
create a child AppDomain and reference obkect via reflection and uload
the child domain when finished.

My Scenario. I have windows services which are basically libraries
called obviously by a service wrapper. Since the wrapper does the
instansiation, I want to update these dlls without stopping and
restarting my service.

I have created a mockup using a form and a separate dll

Here is the mockup simple dll the form will call:

using System;

namespace TestClass
{
public class Test : MarshalByRefObject
{
public string GetResponse()
{
return "Test Response 1";
}
}
}
Here is the form code:
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;

namespace DomainTest
{

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnLoad;
private System.Windows.Forms.Button btnUnload;
private System.Windows.Forms.Button btnCall;
private System.Windows.Forms.TextBox txtResponse;

private AppDomain _runDomain;
private Assembly _assembly;
private Type _typTest;
Object _objTest;
AppDomainSetup _appSetup;

private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
_appSetup = new AppDomainSetup();
_appSetup.ApplicationBase =
@"E:\Development\.Net\CSharp\Examples\AppDomain\Ap pDomainEnvironment";
_runDomain = AppDomain.CreateDomain("MyDomain", null, _appSetup);
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnLoad = new System.Windows.Forms.Button();
this.btnUnload = new System.Windows.Forms.Button();
this.btnCall = new System.Windows.Forms.Button();
this.txtResponse = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// btnLoad
//
this.btnLoad.Location = new System.Drawing.Point(30, 35);
this.btnLoad.Name = "btnLoad";
this.btnLoad.Size = new System.Drawing.Size(70, 25);
this.btnLoad.TabIndex = 0;
this.btnLoad.Text = "Load";
this.btnLoad.Click += new System.EventHandler(this.btnLoad_Click);
//
// btnUnload
//
this.btnUnload.Enabled = false;
this.btnUnload.Location = new System.Drawing.Point(300, 35);
this.btnUnload.Name = "btnUnload";
this.btnUnload.Size = new System.Drawing.Size(70, 25);
this.btnUnload.TabIndex = 1;
this.btnUnload.Text = "Unload";
this.btnUnload.Click += new System.EventHandler(this.btnUnload_Click);
//
// btnCall
//
this.btnCall.Enabled = false;
this.btnCall.Location = new System.Drawing.Point(166, 35);
this.btnCall.Name = "btnCall";
this.btnCall.Size = new System.Drawing.Size(70, 25);
this.btnCall.TabIndex = 2;
this.btnCall.Text = "Call";
this.btnCall.Click += new System.EventHandler(this.btnCall_Click);
//
// txtResponse
//
this.txtResponse.Location = new System.Drawing.Point(30, 85);
this.txtResponse.Name = "txtResponse";
this.txtResponse.Size = new System.Drawing.Size(340, 20);
this.txtResponse.TabIndex = 3;
this.txtResponse.Text = "";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(402, 441);
this.Controls.Add(this.txtResponse);
this.Controls.Add(this.btnCall);
this.Controls.Add(this.btnUnload);
this.Controls.Add(this.btnLoad);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void btnLoad_Click(object sender, System.EventArgs e)
{
_assembly = AppDomain.CurrentDomain.Load("TestClass");
_typTest = _assembly.GetType("TestClass.Test");
_objTest = _runDomain.CreateInstance("TestClass", "TestClass.Test");
System.Diagnostics.Debug.WriteLine(_objTest.GetTyp e());

btnCall.Enabled = _objTest != null;
btnUnload.Enabled = _objTest != null;
btnLoad.Enabled = _objTest == null;
}

private void btnCall_Click(object sender, System.EventArgs e)
{
MethodInfo method = _typTest.GetMethod("GetResponse");
txtResponse.Text = (string) method.Invoke(_objTest, null);
}

private void btnUnload_Click(object sender, System.EventArgs e)
{
AppDomain.Unload(_runDomain);
btnCall.Enabled = false;
btnLoad.Enabled = true;
btnUnload.Enabled = false;
}
}
}
The Results:

The issue is that when calligna method off of the newly created object
I get the following error:

Object does not match target type.

I looked at the actual object type from the object created with this
line of code:

_objTest = _runDomain.CreateInstance("TestClass", "TestClass.Test");

The object is not a TestClass.Test Type object, it is a
System.Runtime.Remoting.ObjectHandle type object.

Soooooooooooooooooooo....

How to get around this? Am I even close here?

Nov 17 '05 #2
Hi Brian,

You can use the "CreateInstanceAndUnwrap" method on the AppDomain, which
creates a new instance of the specified Type in the app domain. Below is
a sample:
AppDomain newAppdomain = AppDomain.CreateDomain("NewDomain");
AppDomainController controller =
(AppDomainController)newAppdomain.CreateInstanceAn dUnwrap(
"AppDomainSample", "AppDomainSample.AppDomainController");

CreateInstanceAndUnwrap will unwrap the handle, and convert it into an
object reference, which you can then cast to the correct Type.

Another thing I noticed: If you want to make sure that you can unload
the assembly successfully, you need to make sure that you do not
reference it in your original AppDomain.

For example, you do a:
_typTest = _assembly.GetType("TestClass.Test");

This will load the Type (and therefore it's assembly) in your original
AppDomain, which is probably NOT what you want.

If you use a controller class in the new AppDomain, you can go
indirectly through this controller, for example:

controller.Load("MyTestAssembly");
controller.Load("MyBadAssembly");

object result = controller.ExecuteMethod(
"MyTestAssembly",
"MyTestAssembly.MyClass",
"Add",
new object[] { 100, 22 });

Hope this helps,

Bennie Haelen
br*********@gmail.com wrote:
I am trying to load and unload assemblies dynamically and call methods
and properties when loaded into an Appdomain

I can load assemblies all day in the current AppDomain without
references and without interfaces if need be. But try as I may they
will ot unload. I have been working on this problem for weeks. I have
seen other apps using Remoting but I know there has got to be a way to
create a child AppDomain and reference obkect via reflection and uload
the child domain when finished.

My Scenario. I have windows services which are basically libraries
called obviously by a service wrapper. Since the wrapper does the
instansiation, I want to update these dlls without stopping and
restarting my service.

I have created a mockup using a form and a separate dll

Here is the mockup simple dll the form will call:

using System;

namespace TestClass
{
public class Test : MarshalByRefObject
{
public string GetResponse()
{
return "Test Response 1";
}
}
}
Here is the form code:
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;

namespace DomainTest
{

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnLoad;
private System.Windows.Forms.Button btnUnload;
private System.Windows.Forms.Button btnCall;
private System.Windows.Forms.TextBox txtResponse;

private AppDomain _runDomain;
private Assembly _assembly;
private Type _typTest;
Object _objTest;
AppDomainSetup _appSetup;

private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
_appSetup = new AppDomainSetup();
_appSetup.ApplicationBase =
@"E:\Development\.Net\CSharp\Examples\AppDomain\Ap pDomainEnvironment";
_runDomain = AppDomain.CreateDomain("MyDomain", null, _appSetup);
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnLoad = new System.Windows.Forms.Button();
this.btnUnload = new System.Windows.Forms.Button();
this.btnCall = new System.Windows.Forms.Button();
this.txtResponse = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// btnLoad
//
this.btnLoad.Location = new System.Drawing.Point(30, 35);
this.btnLoad.Name = "btnLoad";
this.btnLoad.Size = new System.Drawing.Size(70, 25);
this.btnLoad.TabIndex = 0;
this.btnLoad.Text = "Load";
this.btnLoad.Click += new System.EventHandler(this.btnLoad_Click);
//
// btnUnload
//
this.btnUnload.Enabled = false;
this.btnUnload.Location = new System.Drawing.Point(300, 35);
this.btnUnload.Name = "btnUnload";
this.btnUnload.Size = new System.Drawing.Size(70, 25);
this.btnUnload.TabIndex = 1;
this.btnUnload.Text = "Unload";
this.btnUnload.Click += new System.EventHandler(this.btnUnload_Click);
//
// btnCall
//
this.btnCall.Enabled = false;
this.btnCall.Location = new System.Drawing.Point(166, 35);
this.btnCall.Name = "btnCall";
this.btnCall.Size = new System.Drawing.Size(70, 25);
this.btnCall.TabIndex = 2;
this.btnCall.Text = "Call";
this.btnCall.Click += new System.EventHandler(this.btnCall_Click);
//
// txtResponse
//
this.txtResponse.Location = new System.Drawing.Point(30, 85);
this.txtResponse.Name = "txtResponse";
this.txtResponse.Size = new System.Drawing.Size(340, 20);
this.txtResponse.TabIndex = 3;
this.txtResponse.Text = "";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(402, 441);
this.Controls.Add(this.txtResponse);
this.Controls.Add(this.btnCall);
this.Controls.Add(this.btnUnload);
this.Controls.Add(this.btnLoad);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);

}
#endregion
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void btnLoad_Click(object sender, System.EventArgs e)
{
_assembly = AppDomain.CurrentDomain.Load("TestClass");
_typTest = _assembly.GetType("TestClass.Test");
_objTest = _runDomain.CreateInstance("TestClass", "TestClass.Test");
System.Diagnostics.Debug.WriteLine(_objTest.GetTyp e());

btnCall.Enabled = _objTest != null;
btnUnload.Enabled = _objTest != null;
btnLoad.Enabled = _objTest == null;
}

private void btnCall_Click(object sender, System.EventArgs e)
{
MethodInfo method = _typTest.GetMethod("GetResponse");
txtResponse.Text = (string) method.Invoke(_objTest, null);
}

private void btnUnload_Click(object sender, System.EventArgs e)
{
AppDomain.Unload(_runDomain);
btnCall.Enabled = false;
btnLoad.Enabled = true;
btnUnload.Enabled = false;
}
}
}
The Results:

The issue is that when calligna method off of the newly created object
I get the following error:

Object does not match target type.

I looked at the actual object type from the object created with this
line of code:

_objTest = _runDomain.CreateInstance("TestClass", "TestClass.Test");

The object is not a TestClass.Test Type object, it is a
System.Runtime.Remoting.ObjectHandle type object.

Soooooooooooooooooooo....

How to get around this? Am I even close here?

Nov 17 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1546
by: Lloyd Sheen | last post by:
I am having trouble gettting an assembly loaded with Assembly.LoadFrom. I can get the assembly call the method I need to call. Now I want to unload the assembly. I need to do this so that the...
2
8460
by: Patrick Blackman | last post by:
I have a program that search the application path for all the Dll that implement a certain interface IText ,when a Dll with the interface is found ,I run a method called IText.Format() which works...
2
10819
by: Lauren Hines | last post by:
Hello, I have read numerous post stating that the only way to unload an assembly (DLL in my case) is to create a separate AppDomain, load the assembly, then unload it by calling AppDomain.Unload....
0
462
by: brianbender | last post by:
I am trying to load and unload assemblies dynamically and call methods and properties when loaded into an Appdomain I can load assemblies all day in the current AppDomain without references and...
4
6221
by: Brett Baisley | last post by:
I am used to VB6 where frmMain.unload, frmNew.load worked. What replaced this in vb.net?
2
2191
by: Artem | last post by:
When I use the method Thread.Abort, it only sends a request of aborting to OS to stop a thread. The thread itself isn't killed and allocated resources aren't released. I tried to run that thread...
6
4704
by: Ronald S. Cook | last post by:
We have a Windows app that has one main form (a shell, sort of). We then load user controls into a panel on the form depending on what the user has selected. Our current code to unload the...
0
940
by: =?Utf-8?B?ZGF2aWQ=?= | last post by:
hi, Can anyone plz let me know that how my user in child1.domain.com can login to the child2.domain.com. I think it is quite possible cause evry child domain is by default having two way...
0
2193
by: praveenselvam636 | last post by:
hai! how can i apply a group policy which was created for the parent domain controller users to the child domain users.i am finding difficult to apply a parent domain group policy to...
0
7204
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7091
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7342
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
7464
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5586
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5018
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4680
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3162
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1516
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.