Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > PowerShell

Vista Tutorial - Problem calling interface of .NET Remoted object via Powershell

Reply
 
Old 08-05-2008   #1 (permalink)
adamhearn
Guest


 
 

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!

My System SpecsSystem Spec
Old 08-05-2008   #2 (permalink)
Oisin (x0n) Grehan [MVP]
Guest


 
 

Re: Problem calling interface of .NET Remoted object via Powershell

Hi,

It looks like powershell is choking on the transparentproxy/realproxy
trickery that is remoting. One approach might be that you create your
own delegating wrapper type to pass to powershell as a workaround.
E.g. a full class that takes the marshalbyrefobject instance in its
constructor and its methods just delegate to the transparentproxy
instance. Another simpler (but uglier) approach might be to use late
bound calls against the remoted instance:

ps>
[remotingserver.iremotingservice].getmethod("GetServerName").invoke($objRemServer,
@())
TheServerName (hopefully ;-))

This case is definitely a deficiency in powershell and probably needs
its own adapter.

- Oisin
PowerShell MVP
http://www.nivot.org/


On Aug 5, 11:38*am, adamhearn <adamhe...@xxxxxx>
wrote:
Quote:

> 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( "PressAny 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!


My System SpecsSystem Spec
Old 08-06-2008   #3 (permalink)
adamhearn
Guest


 
 

Re: Problem calling interface of .NET Remoted object via Powershel

Hi Oisin,

Thanks for your reply. I tried a late bound call and yes it does work but it
isn't really a viable solution for us (the Powershell scripts were intended
to be written by a test team whose 'programming' skillset isn't the highest).

I believe that for us the better of the two solutions would be to write the
additional layer as you suggest.

I've seen a similar post relating to access of explicitly implemented
interfaces. Hopefully Microsoft will address these 'limitations' in a future
release?!

Thanks again, Adam

"Oisin (x0n) Grehan [MVP]" wrote:
Quote:

> Hi,
>
> It looks like powershell is choking on the transparentproxy/realproxy
> trickery that is remoting. One approach might be that you create your
> own delegating wrapper type to pass to powershell as a workaround.
> E.g. a full class that takes the marshalbyrefobject instance in its
> constructor and its methods just delegate to the transparentproxy
> instance. Another simpler (but uglier) approach might be to use late
> bound calls against the remoted instance:
>
> ps>
> [remotingserver.iremotingservice].getmethod("GetServerName").invoke($objRemServer,
> @())
> TheServerName (hopefully ;-))
>
> This case is definitely a deficiency in powershell and probably needs
> its own adapter.
>
> - Oisin
> PowerShell MVP
> http://www.nivot.org/
>
>
> On Aug 5, 11:38 am, adamhearn <adamhe...@xxxxxx>
> wrote:
Quote:

> > 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!
>
>
>
>
My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
WCF calling the powershell PowerShell
exception calling .net object PowerShell
exception when calling a method: object is read-only PowerShell
Getting Interface ID back from a COM object? PowerShell


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46