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? 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?
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? This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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...
|
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....
|
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...
|
by: Brett Baisley |
last post by:
I am used to VB6 where frmMain.unload, frmNew.load worked.
What replaced this in vb.net?
| |
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...
|
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...
|
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...
|
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...
|
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,...
|
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...
| |
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...
|
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...
|
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,...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
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 ...
| |