Discussion:
CreateInstanceAndUnwrap returns a MarshalByRefObject
(too old to reply)
Gordon Henriksen
2003-12-13 00:10:09 UTC
Permalink
Hi everyone,

I've been struggling with this for a while to no avail.

I have an internal application which uses remoting to
launch AppDomains and load/unload user assemblies. I'm
trying to integrate it with Visual Studio .NET as an add-
in. I've hit a rather major obstacle with using remoting
from an add-in, though, and boiled it down to a rather
simple test case:

using System;
using System.IO;

namespace ICLUBcentral.Example.AppDomainFailure {
public abstract class CLI {
public static void Main() {
AppDomain ad = AppDomain.CreateDomain(
"My First AppDomain");

object remoteObj =
ad.CreateInstanceFromAndUnwrap(
typeof(Dummy).Assembly.Location,
typeof(Dummy).FullName);

Console.Out.WriteLine(
"the proxy is of type ["
+ remoteObj.GetType().Assembly.FullName
+ "]" + remoteObj.GetType().FullName);

Console.Out.WriteLine(
"wish it were of type ["
+ typeof(Dummy).Assembly.FullName
+ "]" + typeof(Dummy).FullName);

AppDomain.Unload(ad);

Console.Out.Write("[press enter]");
Console.Out.Flush();
Console.In.ReadLine();
}
}

public class Dummy : MarshalByRefObject {
public Dummy() {
// Empty.
}

public string HelloWorld() {
return "Hello, world.";
}
}
}

When I run that as an application, it works: The object
returned from CreateInstanceFromAndUnwrap is of the type I
asked for. When I run it from within a Visual Studio .NET
add-in (with the Console I/O replaced by MessageBox.Show,
say), remoteObject's type is System.MarshalByRefObject!
remoteObject's type should be a *subclass* of
MarshalByRefObject; it shouldn't be *exactly*
MarshalByRefObject! I don't know how to identify what's
different in the Visual Studio .NET execution environment
which would prevent this from working. Help, anyone?


The output of the above code (exactly) on the console is:

the proxy is of type [ICCTest, Version=1.0.1441.33463,
Culture=neutral, PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy
wish it were of type [ICCTest, Version=1.0.1441.33463,
Culture=neutral, PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy

The output from within my Visual Studio .NET add-in (with
console I/O replaced) is:

the proxy is of type [mscorlib, Version=1.0.3300.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]
System.MarshalByRefObject
wish it were of type [ICLUBcentral.Testing.VSAddIn,
Version=1.0.1441.33461, Culture=neutral,
PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy

(Sorry, the full source for an add-in would utterly
obfuscate the test. The above class should be pretty easy
invoke from one, though.)


Note: The behavior is the same with
CreateInstanceAndUnwrap (but I have to use AppDomainSetup
to set the search path, which makes the example longer).

Note also: Visual Studio .NET 2002 (upgrading soon).

--

Gordon Henriksen
IT Manager
ICLUBcentral Inc.
***@iclub.com
Dmitriy Lapshin [C# / .NET MVP]
2003-12-13 11:23:28 UTC
Permalink
Hi Gordon,

Does this prevent you from casting the returned reference to the desired
type? I use cross-AppDomain remoting rather actively in a VS .NET add-in and
I have never encountered such a problem.

IMPORTANT: You should still ensure the assembly loaded into the created
AppDomain can be loaded from the primary AppDomain. If it cannot be loaded
from the main AppDomain, the reference returned by CreateInstanceAndUnwrap
is unusable. In the case of an add-in, it's AppDomain's private path can set
up somewhere outside the folder you expect it to point to. Therefore, you
might need to add a handler for the ResolveAssembly event to ensure the
plug-in assembly can be successfully loaded to the primary AppDomain.

Phew...pretty cumbersome. Hope it makes sense.
--
Dmitriy Lapshin [C# / .NET MVP]
X-Unity Test Studio
http://x-unity.miik.com.ua/teststudio.aspx
Bring the power of unit testing to VS .NET IDE
Post by Gordon Henriksen
Hi everyone,
I've been struggling with this for a while to no avail.
I have an internal application which uses remoting to
launch AppDomains and load/unload user assemblies. I'm
trying to integrate it with Visual Studio .NET as an add-
in. I've hit a rather major obstacle with using remoting
from an add-in, though, and boiled it down to a rather
using System;
using System.IO;
namespace ICLUBcentral.Example.AppDomainFailure {
public abstract class CLI {
public static void Main() {
AppDomain ad = AppDomain.CreateDomain(
"My First AppDomain");
object remoteObj =
ad.CreateInstanceFromAndUnwrap(
typeof(Dummy).Assembly.Location,
typeof(Dummy).FullName);
Console.Out.WriteLine(
"the proxy is of type ["
+ remoteObj.GetType().Assembly.FullName
+ "]" + remoteObj.GetType().FullName);
Console.Out.WriteLine(
"wish it were of type ["
+ typeof(Dummy).Assembly.FullName
+ "]" + typeof(Dummy).FullName);
AppDomain.Unload(ad);
Console.Out.Write("[press enter]");
Console.Out.Flush();
Console.In.ReadLine();
}
}
public class Dummy : MarshalByRefObject {
public Dummy() {
// Empty.
}
public string HelloWorld() {
return "Hello, world.";
}
}
}
When I run that as an application, it works: The object
returned from CreateInstanceFromAndUnwrap is of the type I
asked for. When I run it from within a Visual Studio .NET
add-in (with the Console I/O replaced by MessageBox.Show,
say), remoteObject's type is System.MarshalByRefObject!
remoteObject's type should be a *subclass* of
MarshalByRefObject; it shouldn't be *exactly*
MarshalByRefObject! I don't know how to identify what's
different in the Visual Studio .NET execution environment
which would prevent this from working. Help, anyone?
the proxy is of type [ICCTest, Version=1.0.1441.33463,
Culture=neutral, PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy
wish it were of type [ICCTest, Version=1.0.1441.33463,
Culture=neutral, PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy
The output from within my Visual Studio .NET add-in (with
the proxy is of type [mscorlib, Version=1.0.3300.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]
System.MarshalByRefObject
wish it were of type [ICLUBcentral.Testing.VSAddIn,
Version=1.0.1441.33461, Culture=neutral,
PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy
(Sorry, the full source for an add-in would utterly
obfuscate the test. The above class should be pretty easy
invoke from one, though.)
Note: The behavior is the same with
CreateInstanceAndUnwrap (but I have to use AppDomainSetup
to set the search path, which makes the example longer).
Note also: Visual Studio .NET 2002 (upgrading soon).
--
Gordon Henriksen
IT Manager
ICLUBcentral Inc.
Gordon Henriksen
2003-12-15 15:12:57 UTC
Permalink
Hi Dmitry,

Thanks for your reply.
Post by Dmitriy Lapshin [C# / .NET MVP]
Does this prevent you from casting the returned
reference to the desired type? I use cross-AppDomain
remoting rather actively in a VS .NET add-in and I have
never encountered such a problem.
Yes, it prevents me from casting. The object is EXACTLY of
type System.MarshalByRefObject, rather than being my
subclass.

Yes, the assembly can be loaded in the parent AppDomain
(VS.NET), at least insofar as it is *already* loaded--I've
had no luck either way using a type in a separate assembly
vs. using a type contained within my add-in's assembly.
Post by Dmitriy Lapshin [C# / .NET MVP]
IMPORTANT: You should still ensure the assembly loaded
into the created AppDomain can be loaded from the
primary AppDomain. If it cannot be loaded from the main
AppDomain, the reference returned by
CreateInstanceAndUnwrap is unusable. In the case of an
add-in, it's AppDomain's private path can set up
somewhere outside the folder you expect it to point to.
Therefore, you might need to add a handler for the
ResolveAssembly event to ensure the plug-in assembly can
be successfully loaded to the primary AppDomain.
Do I need to worry about this if the assembly is already
loaded? I worried about this and made sure the assembly
was loaded (by creating a new instance of a type from the
target assembly) before my routine attempted remoting. It
had no effect.
--
Gordon Henriksen
IT Manager
ICLUBcentral Inc.
***@iclub.com
Dmitriy Lapshin [C# / .NET MVP]
2003-12-15 16:23:29 UTC
Permalink
Gordon,

Try to move the Dummy class out to a separate assembly and register that
assembly in the GAC. I once did it with some assembly that caused me
troubles when being loaded to a custom AppDomain and putting it to the GAC
worked like a charm.

If the GAC is inappropriate, I'd then try changing these lines:

typeof(Dummy).Assembly.Location,
typeof(Dummy).FullName;

to some fixed constants, as I have seen typeof(Something) returning
System.RuntimeType instead of the expected type, when run in a VS .NET
add-in code. At least display the values of these properties in a separate
message box before attempting to create the Dummy object instance. You might
be surprised with the output.
--
Dmitriy Lapshin [C# / .NET MVP]
X-Unity Test Studio
http://x-unity.miik.com.ua/teststudio.aspx
Bring the power of unit testing to VS .NET IDE
Post by Gordon Henriksen
Hi Dmitry,
Thanks for your reply.
Post by Dmitriy Lapshin [C# / .NET MVP]
Does this prevent you from casting the returned
reference to the desired type? I use cross-AppDomain
remoting rather actively in a VS .NET add-in and I have
never encountered such a problem.
Yes, it prevents me from casting. The object is EXACTLY of
type System.MarshalByRefObject, rather than being my
subclass.
Yes, the assembly can be loaded in the parent AppDomain
(VS.NET), at least insofar as it is *already* loaded--I've
had no luck either way using a type in a separate assembly
vs. using a type contained within my add-in's assembly.
Post by Dmitriy Lapshin [C# / .NET MVP]
IMPORTANT: You should still ensure the assembly loaded
into the created AppDomain can be loaded from the
primary AppDomain. If it cannot be loaded from the main
AppDomain, the reference returned by
CreateInstanceAndUnwrap is unusable. In the case of an
add-in, it's AppDomain's private path can set up
somewhere outside the folder you expect it to point to.
Therefore, you might need to add a handler for the
ResolveAssembly event to ensure the plug-in assembly can
be successfully loaded to the primary AppDomain.
Do I need to worry about this if the assembly is already
loaded? I worried about this and made sure the assembly
was loaded (by creating a new instance of a type from the
target assembly) before my routine attempted remoting. It
had no effect.
--
Gordon Henriksen
IT Manager
ICLUBcentral Inc.
Sebastien Lambla
2003-12-13 22:53:34 UTC
Permalink
Agreed with Dmitriy, try to cast it to the type you want..
--
Sebastien Lambla
http://thetechnologist.is-a-geek.com/blog/
Post by Gordon Henriksen
Hi everyone,
I've been struggling with this for a while to no avail.
I have an internal application which uses remoting to
launch AppDomains and load/unload user assemblies. I'm
trying to integrate it with Visual Studio .NET as an add-
in. I've hit a rather major obstacle with using remoting
from an add-in, though, and boiled it down to a rather
using System;
using System.IO;
namespace ICLUBcentral.Example.AppDomainFailure {
public abstract class CLI {
public static void Main() {
AppDomain ad = AppDomain.CreateDomain(
"My First AppDomain");
object remoteObj =
ad.CreateInstanceFromAndUnwrap(
typeof(Dummy).Assembly.Location,
typeof(Dummy).FullName);
Console.Out.WriteLine(
"the proxy is of type ["
+ remoteObj.GetType().Assembly.FullName
+ "]" + remoteObj.GetType().FullName);
Console.Out.WriteLine(
"wish it were of type ["
+ typeof(Dummy).Assembly.FullName
+ "]" + typeof(Dummy).FullName);
AppDomain.Unload(ad);
Console.Out.Write("[press enter]");
Console.Out.Flush();
Console.In.ReadLine();
}
}
public class Dummy : MarshalByRefObject {
public Dummy() {
// Empty.
}
public string HelloWorld() {
return "Hello, world.";
}
}
}
When I run that as an application, it works: The object
returned from CreateInstanceFromAndUnwrap is of the type I
asked for. When I run it from within a Visual Studio .NET
add-in (with the Console I/O replaced by MessageBox.Show,
say), remoteObject's type is System.MarshalByRefObject!
remoteObject's type should be a *subclass* of
MarshalByRefObject; it shouldn't be *exactly*
MarshalByRefObject! I don't know how to identify what's
different in the Visual Studio .NET execution environment
which would prevent this from working. Help, anyone?
the proxy is of type [ICCTest, Version=1.0.1441.33463,
Culture=neutral, PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy
wish it were of type [ICCTest, Version=1.0.1441.33463,
Culture=neutral, PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy
The output from within my Visual Studio .NET add-in (with
the proxy is of type [mscorlib, Version=1.0.3300.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089]
System.MarshalByRefObject
wish it were of type [ICLUBcentral.Testing.VSAddIn,
Version=1.0.1441.33461, Culture=neutral,
PublicKeyToken=null]
ICLUBcentral.Example.AppDomainFailure.Dummy
(Sorry, the full source for an add-in would utterly
obfuscate the test. The above class should be pretty easy
invoke from one, though.)
Note: The behavior is the same with
CreateInstanceAndUnwrap (but I have to use AppDomainSetup
to set the search path, which makes the example longer).
Note also: Visual Studio .NET 2002 (upgrading soon).
--
Gordon Henriksen
IT Manager
ICLUBcentral Inc.
Loading...