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

AppDomain and Memory Issues

132 views
Skip to first unread message

Baddabing

unread,
Sep 19, 2002, 3:15:14 AM9/19/02
to
Trent,

I haven't tested it but I suspect your problem is related to maintaining
isolation between your AppDomains. The way you have written your
code, the AppDomainTesting.TestEngine object is still being attached to your
primary AppDomain because of the CreateInstanceAndUnwrap call (and cast)
which is returning a (proxy) TestEngine object. Although it is a proxy, the
primary AppDomain still attaches to the assembly as metadata is required.

To solve this, an indirection solution (yuck) where the primary AppDomain
has NO knowledge of the assembly is required (class factory and invoke by
interface?).

Eric Gunnerson has recently written an article on dynamic assemblies on MSDN
which may help (sorry can't find the reference).

For this reason, I can't see how the AppDomain recycling scheme supplied by
MS in the thread of 15 July 2002 could work. Has anyone actually
managed to implement it successfully - how?

Regards,
Baddabing

"Trent" <noj...@mail.com> wrote in message
news:u3e06BoWCHA.436@tkmsftngp10...
> I have been working on loading and unload the VSA Engine into AppDomain to
> reduce the amount of memory usage in my application. I have built a test
> environment that will create and unload a VSA Engine into a AppDomain.
> While this reduces the amount of memory used compared to simple creating
and
> destroying the VAS Engine in the one domain, I still have an increase in
> memory.
>
> Have I set up the configuration for the domain incorrectly or is this the
> wrong way.
>
> I have attached the project and the code it anybody would like to test it.
> You will notice an increase in memory if the engine is complied.
>
> Test (With a for loop of 100)
> Without Compile Memory Usage = 15,000 k
> With compile Memory usage = 30,000 K
>
> While these memory values are low, it cause problems in the production
> environment when the number of engines and complexity of the script
> increase.
>
> Thanks
>
> using System;
> using System.Reflection;
> using System.Windows.Forms;
> using System.Collections;
> namespace AppDomainTesting
> {
> /// <summary>
> /// Summary description for Class1.
> /// </summary>
> class Class1
> {
> /// <summary>
> /// The main entry point for the application.
> /// </summary>
> [STAThread]
> static void Main(string[] args)
> {
> for(int i=0; i<100; i++)
> {
> AppDomain appDomain = null;
> AppDomainSetup setup = new AppDomainSetup();
> AppDomainSetup appDomainSetUp = new AppDomainSetup();
>
> Console.WriteLine("Insatance = "+i.ToString());
> try
> {
>
> appDomain =
>
AppDomain.CreateDomain(System.Guid.NewGuid().ToString(),null,appDomainSetUp)
> ;
>
> string assemblyName = Assembly.GetAssembly(
> typeof(AppDomainTesting.ScriptEngine) ).FullName;
>
> AppDomainTesting.TestEngine test =
>
(AppDomainTesting.TestEngine)appDomain.CreateInstanceAndUnwrap(assemblyName,
> "AppDomainTesting.TestEngine");
> //comment out the next line and memory usage will be lower
> test.Compile();
> test.Run();
>
> }
> catch(System.Exception err)
> {
> string error = err.ToString();
> System.Windows.Forms.MessageBox.Show(error);
> }
> finally
> {
> if(appDomain != null)
> AppDomain.Unload(appDomain);
> }
>
> }
>
> Console.WriteLine("Total Memory =" +
GC.GetTotalMemory(true).ToString());
> Console.WriteLine("Press Enter To End");
> if(Console.Read()>0)
> return;
> }
> }
> public class TestEngine : System.ComponentModel.Component
> {
> private ScriptEngine engine;
> public TestEngine()
> {
> engine = new ScriptEngine();
> }
> public void Compile()
> {
> engine.Compile();
> }
> public void Run()
> {
>
> if(engine.IsCompiled)
> {
> engine.Run();
>
> string strNamespace = engine.RootNamespace;
> string FullName = strNamespace +".script";
>
> // Get the method from the type
> Type ModType = engine.Assembly.GetType(FullName,true,true);
> System.Reflection.MethodInfo method = ModType.GetMethod("main");
> if (method != null)
> method.Invoke(null,null);
> }
> }
> }
> public class ScriptEngine : Microsoft.VisualBasic.Vsa.VsaEngine
> {
> public ScriptEngine()
> {
> this.RootMoniker = "MemoryTesting://script";
> this.Site = new VsaBaseSite();
> this.InitNew();
> this.RootNamespace = "scriptcode";
> this.Name = "scriptcode";
> Microsoft.Vsa.IVsaReferenceItem systemRef=
>
(Microsoft.Vsa.IVsaReferenceItem)this.Items.CreateItem("system.dll",Microsof
> t.Vsa.VsaItemType.Reference, Microsoft.Vsa.VsaItemFlag.None);
> systemRef.AssemblyName = "System.dll";
> Microsoft.Vsa.IVsaCodeItem code=
>
(Microsoft.Vsa.IVsaCodeItem)this.Items.CreateItem("main",Microsoft.Vsa.VsaIt
> emType.Code, Microsoft.Vsa.VsaItemFlag.Module);
> code.SourceText= this.script;
>
> }
> private string script = "Option Strict Off\n"+
> "Option Explicit Off\n"+
> "Imports System\n"+
> "Imports System.Windows.Forms\n"+
> "Public Module script\n"+
> "Sub main\n"+
> //"MessageBox.Show(\"Testing\")\n"+
> "Console.WriteLine(\"Testing \" & DateTime.Now.ToLongTimeString())\n"+
> //"MessageBox.Show(\"Testing\")\n"+
> "End Sub\n"+
> "End Module\n";
> }
> public class VsaBaseSite :Microsoft.Vsa.IVsaSite
> {
>
>
> #region Implementation of IVsaSite
> public object GetEventSourceInstance(string itemName, string
> eventSourceName)
> {
> return null;
> }
> public object GetGlobalInstance(string name)
> {
> return null;
> }
> public void Notify(string notify, object info)
> {
>
> }
> public bool OnCompilerError(Microsoft.Vsa.IVsaError error)
> {
> Console.WriteLine(error.ToString());
> return true;
> }
> public void GetCompiledState(out byte[] pe, out byte[] debugInfo)
> {
> pe = null;
> debugInfo = null;
>
> }
>
> #endregion
> }
> }
>
>
>
>
>


Trent

unread,
Sep 19, 2002, 2:06:52 PM9/19/02
to
Hello Baddabing

Thanks for the ideas. I have not been successfully able to implement them
yet, but I'm still trying. The link to the article you mention; (watch for
word wrap)

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/htm
l/csharp05162002.asp

another usefully article can be found at Codeproject

http://www.codeproject.com/csharp/livecodedotnet.asp

If anybody has been successful in implementing AppDomain recycling scheme
using the VSA engine please let me know

Thanks

Trent

"Baddabing" <re...@togroup.com> wrote in message
news:#H9Ppw6XCHA.2652@tkmsftngp10...

Baddabing

unread,
Sep 20, 2002, 7:31:56 AM9/20/02
to
Trent,

Exactly - that's the idea. One point though, is that typically the
interface and class factory would be created in their own DLL.

The really bad news is that you will find that memory continues to be
consumed when instantiating (thats all it takes) the VB engine in a second
AppDomain, even after that second AppDomain is unloaded. This is not the
case for the JScript engine.

( MS - I would really like to know the cause of this VB engine unload memory
issue - is it related to there being no mechanism to fully unload a
domain-neutral assembly?)

This flaw I think prevents the use of the VB engine in this scenario.
Microsoft, I believe, have stated that it was never intended the use of a
second AppDomain solution to solve the assembly unload dilemma. The whole
point of their solution is access to live objects and events which is
negated by having to use a second AppDomain.

The necessity to use a second AppDomain in a compile many times scenario,
and then pay the price in regards to live objects and events, means that
Script for the Dotnet framework remains suitable only for a compile once/run
many times scenario IMHO.

Regards,
Baddabing

"Trent" <noj...@mail.com> wrote in message

news:#WVWVFDYCHA.444@tkmsftngp12...
> I have attached a working copy of the of AppDomain recycling scheme that I
> put together from the articles. hopefully this is the right way???
>
> Trent


>
>
> "Trent" <noj...@mail.com> wrote in message

> news:OIYfvcAYCHA.2452@tkmsftngp09...

JM Servera

unread,
Sep 20, 2002, 11:42:06 AM9/20/02
to
I'm testing this application with the allocation profiler (
http://www.gotdotnet.com/userarea/filedetails.aspx?FileName=AllocationProfil
er.zip ) and seems to work ok, think that GC.GetTotalMemory gives you just
an estimation of the allocated heap.
"Baddabing" <re...@togroup.com> escribió en el mensaje
news:eaUfvkJYCHA.1732@tkmsftngp10...

Baddabing

unread,
Sep 20, 2002, 7:45:58 PM9/20/02
to
Hi JM,

This isn't a managed memory issue.

Simply instantiating the VB Engine in a second AppDomain, and then
successfully unloading that AppDomain, leaves allocated system memory. As
mentioned this is not visibly the case for the JScript engine or for an
arbitrary assembly generated through the Reflection.Emit namespace into a
non-primary domain.

On my system, creating an instance of the VB engine into a second AppDomain
and unloading the AppDomain grows system memory usage by (very) approx.
4.5mb every 100 instantiations.

All I can think of, is that this is a domain-neutral assembly issue and the
VSA VB code (domain-neutral assemblies statics and CLR data structures are
freed on an AppDomain unload but not code) is huge or something. Seems
unlikely to me, but it could be tested by implementing ones own CLR host
with CorBindToRuntimeEx specifying no domain-neutral assemblies (other than
mscorlib.dll).

As per my previous message I think that having to use a second AppDomain
(for a compile many/run few scenario) negates the real advantages of Script
for the .Net Framework (live objects and events). Furthermore, I'd hazard a
guess that the script team have let out a few expletives about the CLR's
inability to unload an assembly. If one could - scripting would be soooo
schweeet.

But would be useful to know if anyone has implemented a VB engine AppDomain
recycling scheme where system memory doesn't grow as I describe? Anyone
have any other thoughts or a solution?

Regards,
Baddabing

"JM Servera" <soyla...@yahoo.es> wrote in message
news:#tIchwLYCHA.3736@tkmsftngp08...

Baddabing

unread,
Sep 20, 2002, 8:01:57 PM9/20/02
to
JM,

BTW thanks for the allocation profiler link - didn't know about it and it
looks excellent.

Thanks,
Baddabing

"JM Servera" <soyla...@yahoo.es> wrote in message
news:#tIchwLYCHA.3736@tkmsftngp08...

JM Servera

unread,
Sep 23, 2002, 4:12:02 AM9/23/02
to
Hi Baddabing!
Thanks for your explanation. I was in the belief that the Garbage
Collector will someday free the memory.
As you, I'm very disappointed with having to use a second AppDomain to
allow my app unloading the script.
I'm developing a service that will run scheduled scripts and I need to
unload them every time that they have run, so, if the service has this
memory leaks then I can't put it in production... and this will not make my
boss very happy.
So, I'm also very interested in finding anyone who found the way to
"correctly" unload the VB engine. (Actually, not only interested, I do need
it).
Thanks again,
JM

"Baddabing" <re...@togroup.com> escribió en el mensaje

news:O8JB6#PYCHA.2452@tkmsftngp11...

Baddabing

unread,
Sep 23, 2002, 7:35:19 AM9/23/02
to
JM,

I've actually been going nuts over this AppDomain issue and am about to give
up. However, I believe I was wrong in stating that this is only an issue
with the VB VSA engine.

My experiments lead me to now believe that continually instantiating
(different each time) assemblies into a secondary AppDomain which is then
unloaded, leads to a substantial increase in system memory use - recoverable
only at end of process. This is the case even if interaction between the
default and secondary AppDomain is limited to invoking of methods through an
interface returned through a factory created instance of the assembly in the
second AppDomain - i.e. the default AppDomain knows nothing about the remote
assembly other than through that interface.

This doesn't really impact on generating a small number of dynamic
assemblies for things like plugins, but sure does for scripting where one
might want to generate and load hundreds of assemblies.

Would be really grateful if someone could show me I'm wrong?

Your project sounds interesting - is it web based?

Best regards,
Baddabing

"JM Servera" <soyla...@yahoo.es> wrote in message

news:#YyPAjtYCHA.2260@tkmsftngp09...

JM Servera

unread,
Sep 24, 2002, 4:35:31 AM9/24/02
to
Hi Baddabing!
My service it's planned to be a multithreaded windows service that reads
scripts from a database and runs them depending on its scheduling
information.
As I was very upset with the memory leaks past week, I've created a simple
windows service that opened up to 6 threads at a time and each one opened a
database connection, with a random lifetime for every opened thread between
200 and 600 milliseconds.
I've found that my service was slowly eating my system memory at about 2MB a
day, even closing every thread's db connection and calling GC.Collect(). So,
I've decided to let it run for some days to see if the runtime core will eat
memory forever or, as it is supposed to do, it will free the unused memory
when it decided that it was the time to do it.
Finally, after 8 days of running, the service freed the memory and started
its cycle again. It seems that the managed heap remains allocated by the
system until it decides to free it. The managed allocations and GC
collections are made into this heap, and we do not have any control over
this one, we can free blocks of memory into it, but not the heap itself.
It's something like we have to trust on the core for allocating and freeing
memory depending on the system needs.
The main problem is that this is not clearly explained in the documentation.
I will be very interested if someone (any ms guy) can explain this behavior
in a more technical fashion and tell me if I'm too optimistic.
Note: I still didn't try it with a vsa vb.net engine, it was just a
multithreading service test.

Greetings from Mallorca,
JM

"Baddabing" <re...@togroup.com> escribió en el mensaje

news:OskTnUvYCHA.952@tkmsftngp12...

Miljan Mitrovic

unread,
Sep 24, 2002, 7:39:35 AM9/24/02
to
I too noticed this behavior in similar surbconstances. I even made an app to
"eat" the memory and service responded by freeing it's memory to accomodate
outer requests. I did not try to force mem release with a 3rd party memory
recoverers. Anyone?


"JM Servera" <soyla...@yahoo.es> wrote in message

news:uWcuxU6YCHA.1152@tkmsftngp10...

Thong Nguyen

unread,
Sep 24, 2002, 7:44:46 AM9/24/02
to
Wah. It's driving me nuts too. There's no way to add dynamic scripting to
an application without the ability to unload a dynamically created assembly.
Loading the assembly into another appdomain causes severe speed issues (and
great difficulting wrt marshalling).

I hope Microsoft addresses this soon :(.

BTW, check out the DynamicJava project
(http://koala.ilog.fr/djava/#overview). It supports dynamic interpretation
of Java. C# needs something like this :|.

::Tum

"Baddabing" <re...@togroup.com> wrote in message

news:OskTnUvYCHA.952@tkmsftngp12...

JM Servera

unread,
Oct 4, 2002, 7:30:08 AM10/4/02
to
Finally I've isolated the code that is leaking memory: IVSAEngine.Compile
for both VB and JS engines is consuming virtual memory.
My service fulfills all the requirements for AppDomain unloading
(MarshalByRef, creating instances from interfaces etc...) and after three
weeks of tests and profiling I'm pretty sure that the call that is eating
memory is the Compile method.
Every GC collection frees physical memory, but not virtual memory (under the
task admin choose view->select columns and check the virtual memory option),
so after about two hours of continously compiling and running scripts my
virtual memory is totally full.
The scripts are so simple as a Console.WriteLine, and I don't have published
objects.
Just commenting this standard code stops the bug:
if(engine.Compile())
{
try
{
engine.Run();
Assembly assem = engine.Assembly;
Type type = assem.GetType("MyNetScript."+script.Name);
MethodInfo method = type.GetMethod("Main");
try
{
method.Invoke(null, null); // I've tried also with (this,null)
}
catch(Exception ex)
{
Debug.WriteLine("Invoke " + ex.Message);
if (ex.InnerException!=null)
Debug.WriteLine("\t"+ex.InnerException.Message);
throw ex;
}
}
catch(Exception ex)
{
Debug.WriteLine("Engine: " + ex.Message);
if(ex.InnerException!=null)
Debug.WriteLine("Engine Run: " + ex.InnerException.Message);
throw ex;
}
}

I've also tried to comment the inner code of the "if" without any luck, so,
I'm sure that the method that is leaking is the "Compile" one.
In any other case I've tested AppDomain loading/unloading works fine, it
just begins leaking
I really do need a solution or workaround for this leak.

"Miljan Mitrovic" <miljan@pexim(.dot.)co(.dot.)yu> escribió en el mensaje
news:ulp0o77YCHA.2580@tkmsftngp12...

Baddabing

unread,
Oct 4, 2002, 9:26:54 AM10/4/02
to
JM,

Are you sure that this is really the issue? Commenting out the compile
means that the SAME assembly is continually getting loaded into a recycled
appdomain. Definately no memory problems with that.

The real issue is whenever a DIFFERENT assembly is loaded (each time) into a
recycled appdomain. I think you will see this behaviour with ANY
dynamically generated assembly, whether through codedom or vsa.

This is the (current) .NET VSA scripting paradox - you can use scripting if
you don't have to compile many scripts (or you can stop and restart the
process). But then why use scripting?

What do you think - can you try it?

Baddabing

"JM Servera" <soyla...@yahoo.es> wrote in message

news:#FzY8k5aCHA.2612@tkmsftngp12...

JM Servera

unread,
Oct 4, 2002, 9:39:32 AM10/4/02
to
Ok, I'll try it.

"Baddabing" <re...@togroup.com> escribió en el mensaje
news:uKVOMm6aCHA.1692@tkmsftngp09...

Baddabing

unread,
Oct 4, 2002, 9:47:09 AM10/4/02
to
JM,

With your permission, I'll email you private to discuss some of these
issues. Am interested to hear your thoughts.

Baddabing

"JM Servera" <soyla...@yahoo.es> wrote in message

news:#iiLQt6aCHA.1652@tkmsftngp11...

Peter Torr (MS)

unread,
Oct 4, 2002, 9:09:41 PM10/4/02
to
"Baddabing" <re...@togroup.com> wrote in message
news:#U44np7ZCHA.2336@tkmsftngp08...
> 1. load an assembly into a second AppDomain
> 2. unload that AppDomain
>
> Repeat the above 2 steps, a large (>100) number of times, with a DIFFERENT
> assembly each time. What happens to system memory on your system?

Hi,

Loading, executing, and unloading a simple assembly 500 times gave rise to a
modest increase in memory. I compiled the script below into 500 assemblies,
then ran them with the host code.

Initial footprint was 7,288 k Mem, and 4,460 k Virtual Mem. After looping
500 times, it was 9,396 k and 5,400 respectively. I'll pass this on to the
runtime people.

How many assemblies to do you expect to be loading in real situations? How
often? How big are they?

Peter

--
Peter Torr -- pt...@microsoft.com
This must be the disclaimer I waited years to read:
http://www.microsoft.com/info/cpyright.htm


// ---------- byref.js ----------
import IFace
import System

class Ob extends MarshalByRefObject implements Test
{
function Test()
{
print("My AppDomain is " + AppDomain.CurrentDomain.FriendlyName)
}
}


// ---------- iface.js ----------
package IFace
{
interface Test
{
function Test() : void
}
}


// ---------- host.js ----------
import IFace
import System
import System.Reflection

print("Starting... press a key")
System.Console.ReadLine()

for (var i : int = 1; i <= 500; i++)
{
var ad : AppDomain = AppDomain.CreateDomain("MyDomain" + i)
var ob : Test = ad.CreateInstanceAndUnwrap("byref" + i, "Ob")
ob.Test()
ob = null
AppDomain.Unload(ad)
ad = null
}

var ass : Assembly[] = AppDomain.CurrentDomain.GetAssemblies()
for (var j : int in ass)
print(ass[j])

GC.Collect()
GC.Collect()
GC.Collect()

print("Done... press a key")
System.Console.ReadLine()


JM Servera

unread,
Oct 7, 2002, 7:44:42 AM10/7/02
to
Hi Peter,
I'm developing a windows service that checks for scheduled scripts every
5 seconds and runs them in a different thread each one; the number of
scripts depend on the customer needs.
I'm currently doing stress testing and I run many different scripts with
different time periods (10, 15, 25 seconds and one once a day). After about
2 hours my memory is full. The scripts I compile and run for my tests are so
simple as a Console.WriteLine, just for knowing that my script really ran.

Thanks,
JM

"Peter Torr (MS)" <pt...@microsoft.com> escribió en el mensaje
news:uI$c2uAbCHA.1712@tkmsftngp11...

JM Servera

unread,
Oct 7, 2002, 10:39:05 AM10/7/02
to
I've tried to load different assemblies and yes, it seems to keep some
memory every time.
I've tried it with sdk 1.0 and 1.1 with the same result.
Started wit 3.912 mem 2.808 virtual and finished with, 8568 mem and 4372
virtual for about 254 assemblies.
This was my C# code... maybe buggy...

using System;

namespace Test
{
class Class1
{
static int count=0;
public static void loadModule()
{
try
{
string assemblyName=(string)
AppDomain.CurrentDomain.GetData("AssemblyName");
object c=(object) System.Reflection.Assembly.LoadFrom(assemblyName);
Console.WriteLine("{0} loaded in
{1}",assemblyName,AppDomain.CurrentDomain.FriendlyName);
}
catch{}
}

static void SearchDlls(string path)
{
foreach(string s in System.IO.Directory.GetDirectories(path))
{
foreach(string file in System.IO.Directory.GetFiles(s,"*.dll"))
{
AppDomain p=null;
p= AppDomain.CreateDomain("test");
p.SetData("AssemblyName", file);
p.DoCallBack(new CrossAppDomainDelegate(loadModule));
count++;
AppDomain.Unload(p);
}
SearchDlls(s);


}
}
[STAThread]
static void Main(string[] args)
{

string s=System.Environment.GetEnvironmentVariable("ProgramFiles");
System.Reflection.Assembly[] assemblies=
AppDomain.CurrentDomain.GetAssemblies();
for (int i=0; i<assemblies.Length; i++)
{
Console.WriteLine(assemblies[i].FullName);
}
Console.WriteLine("Press <return> to start");
Console.ReadLine();
SearchDlls(String.Format("{0}\\Microsoft.Net\\SDK",s));
Console.WriteLine("Loaded {0} assemblies",count);
assemblies= AppDomain.CurrentDomain.GetAssemblies();
for (int i=0; i<assemblies.Length; i++)
{
Console.WriteLine(assemblies[i].FullName);
}
assemblies= null;
s= null;
GC.Collect();
GC.Collect();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.ReadLine();
}

}
}

"JM Servera" <soyla...@yahoo.es> escribió en el mensaje
news:#iiLQt6aCHA.1652@tkmsftngp11...

Peter Torr (MS)

unread,
Oct 10, 2002, 3:23:57 PM10/10/02
to
"Peter Torr (MS)" <pt...@microsoft.com> wrote in message
news:uI$c2uAbCHA.1712@tkmsftngp11...

> I'll pass this on to the runtime people.

I'm still trying to get an answer to this one...

Peter


Rick Bullotta

unread,
Jan 4, 2003, 9:33:56 AM1/4/03
to
Any answer yet? Any info on mods to the VSA subsystem in .NET Framework
1.1?

Thx.

- Rick

"Peter Torr (MS)" <pt...@microsoft.com> wrote in message

news:ulM2qLJcCHA.2112@tkmsftngp09...

Stacey Blaschke

unread,
Feb 6, 2003, 5:34:45 PM2/6/03
to
I was wondering if this issue has been looked at and if their is a fix for
the appdomain unloading memory leak. I too am working on a script engine for
our app am hoping for a fix to this memory leak in the near future.

Thanks,
Stacey Blaschke
eEye Digital Security

"Peter Torr (MS)" <pt...@microsoft.com> wrote in message

news:ulM2qLJcCHA.2112@tkmsftngp09...

Berkflow

unread,
Apr 18, 2003, 1:59:59 PM4/18/03
to
I have been also trying to figure out how to deal with mounting memory usage
in my scripting application and wanted to at least try the AppDomain
approach. However, when I create the app domain for my assembly it fails on
the AppDomain.CreateInstanceAndUnwrap() call because it expects everything
in it to be serializable. I made all of my classes serializable, but I need
to create the VsaEngine in there (via Microsoft.Vsa.VsaLoader) and that
class is not serializable, so I am not sure how other developers have
managed to do this. Any ideas would be most appreciated.

- Steve

"Rick Bullotta" <rickbu...@comcast.net> wrote in message
news:eCTdJ5$sCHA.2124@TK2MSFTNGP12...

Viatcheslav V. Vassiliev

unread,
Apr 19, 2003, 2:33:39 AM4/19/03
to
Create a serializable wrapper class that holds VsaEngine (or other object
you need) inside. Try to have minimum cross-domain calls (implement most
activity in your wrapper).

Regards,
Viatcheslav V. Vassiliev

"Berkflow" <sbe...@hotmail.com> сообщил/сообщила в новостях следующее:
news:ucQ5URdB...@TK2MSFTNGP11.phx.gbl...

Jim Bob

unread,
Apr 21, 2003, 11:54:11 AM4/21/03
to
Here is some code that shows the basics - it is a C# console application
hosting a VB script engine.

Also check the following article.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/htm
l/csharp05162002.asp

http://www.west-wind.com/presentations/DynamicCode/DynamicCode.htm

Sorry for any word wrap.


using System;
using Microsoft.VisualBasic.Vsa;
using Microsoft.Vsa;
using System.Reflection;

namespace Recycle


{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{

AppDomain engineDomain = null;
System.IO.StreamWriter writer = null;
try
{
int max = 100;
if(args.Length > 0 )
max = Convert.ToInt32(args[0])+1;


string assemblyName =
Assembly.GetAssembly(typeof(Recycle.ScriptEngine)).FullName;
for(int i = 1; i < max; i++)
{
Console.WriteLine("Instance = "+i.ToString());
engineDomain = AppDomain.CreateDomain("EngineDomain",null,null);
ScriptEngine engine = (ScriptEngine)
engineDomain.CreateInstanceAndUnwrap(assemblyName,"Recycle.ScriptEngine");
engine.Compile();
engine.Close();
AppDomain.Unload(engineDomain);
engineDomain = null;
}

}
catch(System.Exception error)
{
Console.Write(error.ToString());
}
finally
{
if(writer != null)
writer.Close();
writer = null;
}
Console.WriteLine("Press any key to end.");
Console.Read();
}
}

public class ScriptEngine :System.MarshalByRefObject
{
Microsoft.VisualBasic.Vsa.VsaEngine engine;
private string _script;
public ScriptEngine()
{
this._script = "Imports System\n"+


"Public Module script\n"+

"\tSub main\n"+
"\tSystem.Console.WriteLine(\"VSA Engine \")\n"+
"\tEnd Sub\n"+
"End Module";
this.engine = new VsaEngine();

engine.RootMoniker = "Recycle://script";
this.engine.Site = new VsaSiteImpl();
engine.InitNew();
engine.RootNamespace = "Test";
engine.Name = "Test";
engine.GenerateDebugInfo = false;

Microsoft.Vsa.IVsaReferenceItem systemRef=
(Microsoft.Vsa.IVsaReferenceItem)engine.Items.CreateItem("system.dll",Micros
oft.Vsa.VsaItemType.Reference, Microsoft.Vsa.VsaItemFlag.None);
systemRef.AssemblyName = "system.dll";
Microsoft.Vsa.IVsaCodeItem scriptCode=
(Microsoft.Vsa.IVsaCodeItem)engine.Items.CreateItem("main",Microsoft.Vsa.Vsa
ItemType.Code,VsaItemFlag.Module);
scriptCode.SourceText=this._script;

}
public void Close()
{
this.engine.Close();
}
public void Compile()
{
this.engine.Compile();
}
public void Run()
{
if(this.engine.IsCompiled)
{
this.engine.Run();


string strNamespace = engine.RootNamespace;
string FullName = strNamespace +".script";
// Get the method from the type
Type ModType = engine.Assembly.GetType(FullName,true,true);

string main = "main";
System.Reflection.MethodInfo method = ModType.GetMethod(main);
method.Invoke(null,null);

}
}
}
}
public class VsaSiteImpl : Microsoft.Vsa.IVsaSite
{

#region Implementation of IVsaSite
public object GetEventSourceInstance(string itemName, string
eventSourceName)
{
return null;
}
public object GetGlobalInstance(string name)
{
return null;
}
public void Notify(string notify, object info)
{

}
public bool OnCompilerError(Microsoft.Vsa.IVsaError error)
{
Console.Write(error.ToString());
return false;


}
public void GetCompiledState(out byte[] pe, out byte[] debugInfo)
{
pe = null;
debugInfo = null;

}

#endregion}
}


"Viatcheslav V. Vassiliev" <sup...@oledbdirect.com> wrote in message
news:uAW4Cdn...@TK2MSFTNGP12.phx.gbl...

Berkflow

unread,
Apr 22, 2003, 12:06:42 PM4/22/03
to
Thanks. Got it working! Code samples are always great. Of course, this
brought me to where this thread started which is that memory still leaks
using AppDomains.
So I started working on another way of calling the VSA engine by wrapping it
in an executable. Having its own process space should guarantee the memory
goes away when the app terminates. There's more overhead in this method of
course, but I figure in my case, I can keep the app running on a per object
basis as it runs through several scripts (this is a script based workflow
app).
Now the only problem I have is this - I am trying to call a method in my
.NET app by starting the app, then creating an object inside that app that I
can then manipulate to load and execute scripts using .NET remoting.
However, in my client code I can't figure out how to create the object since
it seems you need the type of the object and I can't get the type by adding
a reference since you can't reference an exe only dlls. Anyone know how to
do this?
Here's some sample code of how I am trying to do this. It fails when trying
to get the type "MyVsaServer.WorkItem". (return value for t is null).
sysProc = new System.Diagnostics.Process();

sysProc.StartInfo.FileName = "MyVsaServer.exe";

sysProc.Start();

Type t = Type.GetType("MyVsaServer.WorkItem");

System.Runtime.Remoting.ObjRef or = sysProc.CreateObjRef(t);

IWorkItem wi = (IWorkItem)or.GetRealObject(new
System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.S
treamingContextStates.All));

----------------------------------------------------------------------------
---------------

"Jim Bob" <idont...@msn.ca> wrote in message
news:OR4hB5BC...@TK2MSFTNGP10.phx.gbl...

JM Servera

unread,
Jun 11, 2003, 4:30:53 AM6/11/03
to
Are there any news about this Issue? There's a lot of time that nobody talks
about that and we need a scripting platform for .NET.
We had to use the ooooold VB ScriptControl in our .NET applications and
that's not very smart...
Thanks.
"Berkflow" <sbe...@hotmail.com> escribió en el mensaje
news:ucQ5URdB...@TK2MSFTNGP11.phx.gbl...

clint...@gmail.com

unread,
Jan 13, 2005, 11:47:19 AM1/13/05
to
I'm experiencing this same thing as well. Any ideas?
0 new messages