Exception when DefineDynamicAssembly() is called in Another AppDomain

U

uberfan

I keep getting the same exception ("The type
System.Reflection.Emit.AssemblyBuilder in Assembly mscorlib,
Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 is
not marked as serializable.") when I try create a dynamicassembly from
a new appdomain. I works when I use the current domain but since I need
to unload these assemblies after I use them, I need them to be in their
own appdomain.
Could someone please help me out with this.. It's been driving nuts for
a few days now. Is it a bug in the 1.1?
thanks


private AssemblyBuilder MakeAssemblyBuilder()
{
// Build a dynamic assembly using Reflection Emit API.

AppDomain dynamicAppDomain =null;
AssemblyBuilder dynamicAsm = null;
AssemblyName assemblyName = new AssemblyName();

assemblyName.Name = "MyDynamicAssembly";
dynamicAppDomain =
AppDomain.CreateDomain(System.Guid.NewGuid().ToString());
dynamicAsm = m_dynamicAppDomain.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.Run);
}
 
D

David Levine

I assume that you mean to write that dynamicAppDomain and m_dynamicAppDomain
are the same field....

It looks like even though you are attempting to create it in the context of
another appdomain, the method DefineDynamicAssembly is returning a reference
to the dynamic assembly back to the default appdomain, and since this
reference is derived from the Assembly class, that causes the assembly to
loaded into both appdomains. It is likely that that the exception occurs
when the reference to the dynamic assembly is attempted to be serialized
across the appdomain boundary back to the default appdomain.

You can create a MBRO object and create an instance of it (a remoted object)
in the remote appdomain, and then instantiate your dynamic assembly in a
method in that object. That will maintain the isolation between the
appdomains.
 
U

uberfan

David, thanks for the sugestion. I tried your suggestion and it worked
out. Thing is I'm back to the original problem. I can't unload a
dynamically loaded dll. After the assembly is created I define a
dynamic module within it. Then a Platform Invocation method. I execute
the method and Unload the new appdomain. Which I would expect to unload
the assembly and all references to the dll which was loaded by
DefinePInvokeMethod. Unfortunatly the file is still locked and cannot
be deleted.

Here's some sample code:


// From Assembly loaded in newly created appdomain
dynamicMod = dynamicAsm.DefineDynamicModule( "tempModule");

// Dynamically construct a global PInvoke signature
// using the input information
MethodBuilder dynamicMethod = dynamicMod.DefinePInvokeMethod("Foo",
"Cpp.DLL",
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard,
returnType,
parameterTypes,
CallingConvention.Winapi,
CharSet.Ansi);

// This global method is now complete
dynamicMod.CreateGlobalFunctions();

// Get a MethodInfo for the PInvoke method
MethodInfo mi = dynamicMod.GetMethod(entryPoint);

// Invoke the static method and return whatever it returns
Object pRetObj = mi.Invoke(null, parameterValues);




Any idea as why the module doesn't unload. I guess I create another
thread for this new problem..
 
D

David Levine

Are you executiong all these within the context of the remote appdomain? In
other words, did you create a remoted object that implemented a method that
actually does the work?
 
U

uberfan

Yes.. Here is the code:


public class CLocalLoader : MarshalByRefObject
{
private AppDomain m_dynamicAppDomain = null;
private CRemoteLoader m_RemoteLoad = null;
public String strErrorMsg = "";

public CLocalLoader()
{
LoadUp();
}

public void Unload()
{
if (m_dynamicAppDomain != null)
{
AppDomain.Unload(m_dynamicAppDomain);
m_dynamicAppDomain = null;
}
if (m_RemoteLoad != null)
m_RemoteLoad = null;
}

public void LoadUp()
{
try
{
// Set up the AppDomainSetup
AppDomainSetup setup = new AppDomainSetup();
setup.ApplicationName = "MyTestApp";
setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
setup.PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory;


m_dynamicAppDomain = AppDomain.CreateDomain("MySecondDomain",
null, setup);

m_RemoteLoad = (CRemoteLoader)
m_dynamicAppDomain.CreateInstanceAndUnwrap("InvokeVadminHook",
"InvokeTest.CRemoteLoader");

}

catch (Exception pError)
{
strErrorMsg = pError.Message;
}
}


public object DynamicPInvoke(string dll, string entryPoint, Type
returnType, Type [] parameterTypes, object [] parameterValues)
{
if (m_RemoteLoad != null )
m_RemoteLoad.CallDynaMethod("tempAssembly", dll, entryPoint,
returnType, parameterTypes, parameterValues);

return null;
}
}




//=============================================================================
/// <summary>This class is used to </summary>
public class CRemoteLoader : MarshalByRefObject
{
String strErrorMsg = "";

public CRemoteLoader()
{
}

public void CallDynaMethod(String strAssemblyName, string dll,
string entryPoint, Type returnType, Type [] parameterTypes, object []
parameterValues)
{

try
{
AssemblyName asmName = new AssemblyName();
asmName.Name = strAssemblyName;

AssemblyBuilder dynamicAsm =
AppDomain.CurrentDomain.DefineDynamicAssembly(asmName,
AssemblyBuilderAccess.Run);

//Create a temp module in the assembly
ModuleBuilder dynamicMod = dynamicAsm.DefineDynamicModule(
"tempModule");

// Dynamically construct a global PInvoke signature using the
input information
MethodBuilder dynamicMethod =
dynamicMod.DefinePInvokeMethod(entryPoint,
dll,
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard,
returnType,
parameterTypes,
CallingConvention.Winapi,
CharSet.Ansi);

// This global method is now complete
dynamicMod.CreateGlobalFunctions();

// Get a MethodInfo for the PInvoke method
MethodInfo mi = dynamicMod.GetMethod(entryPoint);

// Invoke the static method and return whatever it returns
Object pRetObj = mi.Invoke(null, parameterValues);
}

catch (Exception pError)
{
strErrorMsg = pError.Message;
throw pError;
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top