|
Problem calling interface of .NET Remoted object via Powershell The platform is Powershell V1 (tried V2 runtime as well) on Windows XP SP3
against an application written using .NET 2.0 SP1.
I'm trying to use Powershell to run (script) part of our .NET application
but have come across a [serious] issue attempting to call methods on an
Interface
implemented by a class accessed by .NET Remoting.
I've created simple object in order to demonstrate the issue.
1) Interfaces - Declares the contract for the object
namespace RemotingInterfaces
{
using System;
public interface IRemotingService
{
string GetServerName();
}
}
2) Server - Implements the contract in a class that is also derived from
MarshallByRefObject
namespace RemotingServer
{
public class EntryPoint
{
public static void Main( string[] args )
{
TcpServerChannel channel = new TcpServerChannel( 9988 );
ChannelServices.RegisterChannel( channel, false );
RemotingConfiguration.RegisterWellKnownServiceType( typeof(
RemotingService ), "RemotingService", WellKnownObjectMode.Singleton );
Console.WriteLine( "Press Any Key" );
Console.ReadLine();
}
}
public class RemotingService : MarshalByRefObject, IRemotingService
{
public RemotingService() { }
public string GetServerName()
{
return Dns.GetHostName();
}
public override object InitializeLifetimeService()
{
return null;
}
}
}
3) Client - Provides access to the class using a factory pattern
namespace RemotingClient
{
public class RemClient
{
private IRemotingService resService;
public RemClient()
{
ChannelServices.RegisterChannel( new TcpClientChannel() );
}
public IRemotingService GetServer()
{
resService = (IRemotingService) Activator.GetObject( typeof(
IRemotingService ), "tcp://localhost:9988/RemotingService" );
return resService;
}
}
}
Here's an extract of the Powershell script that demonstrates the problem:
[Reflection.Assembly]::LoadFrom( $binPath + "\RemotingClient.exe")
[Reflection.Assembly]::LoadFrom( $binPath + "\RemotingInterfaces.dll")
$objRemClient = New-Object -TypeName RemotingClient.RemClient
$objRemServer = $objRemClient.GetServer()
$objRemServer.GetType()
$objRemServer.GetServerName()
The call to GetType() on the $objRemServer object returns the following:
TypeHandle : System.RuntimeTypeHandle
DeclaringMethod :
BaseType : System.Object
UnderlyingSystemType : System.MarshalByRefObject
FullName : System.MarshalByRefObject
Attempting to call GetServerName() on $objRemServer yields the following
error:
Method invocation failed because [System.MarshalByRefObject] doesn't contain
a method named 'GetServerName'.
I've tried casting the value using the following syntax:
$objRemServer = [RemotingInterfaces.IRemotingService]
$objRemClient.GetServer()
but this yields the following error:
Cannot convert value "RemotingServer.RemotingService" to type
"RemotingInterfaces.IRemotingService". Error: "Attempted to call a method
declared on type
'System.IConvertible' on an object which exposes
'RemotingServer.RemotingService'."
Even reflecting the server types directly in to the Powershell script using:
[Reflection.Assembly]::LoadFrom( $binPath + "\RemotingServer.exe")
....
$objRemServer = [RemotingServer.RemotingService] $objRemClient.GetServer()
yields the following error:
Cannot convert value "RemotingServer.RemotingService" to type
"RemotingServer.RemotingService". Error: "Attempted to call a method declared
on type
'System.IConvertible' on an object which exposes
'RemotingServer.RemotingService'."
As can be seen by the error messages, Powershell does actually know what
type the object is (RemotingServer.RemotingService) but when accessed
directly it
implies it is 'only' of type MarshalByRefObject and it does not seem
possible to successfully cast to a different type in the object hierarchy.
Does anyone know of a way to access the members of the Interface as
implemented by an object instance accessed through .NET Remoting? Thanks in
advance! |