![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
| 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. |
| |||||||
![]() |
| |
| | #1 (permalink) |
| | 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 Specs![]() |
| | #2 (permalink) |
| | 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 Specs![]() |
| | #3 (permalink) |
| | 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 Specs![]() |
![]() |
| 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 | |||