none
.NET Remoting処理で「System.InvalidCastException: 引数の戻り値の型が無効です。」の例外が発生する。 RRS feed

回答

  • 自己解決できました。

    クライアントのコンポーネントをグローバルアセンブリキャッシュに登録するとうまく動きました。

    ホストAには登録が完了していたため、うまく動作していました。

    ありがとうございました。
    2006年10月19日 14:41

すべての返信

  • ※申し訳ありません。この質問と同様の質問を以下の場所にも投稿しております。
    http://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=al2&namber=17952&rev=&no=0
    問題が解決次第、速やかにすべての掲示板に報告いたします。
    よろしくお願いします。

    .NET Remotingを使用してアプリケーションを作成しています。
    クライアントアプリケーションとサーバアプリケーションを作成し、
    ホストA(WindowsXP)、B(WindowsServer2003)ともにそれぞれ配置しました。
    どちらのホストもクライアント、サーバになり得ます)

    この状態で、
    ・ホストAクライアントからホストAサーバへのアクセスは正常に動作しました。
    ・ホストAクライアントからホストBサーバへのアクセスは正常に動作しました。

    しかし、
    ・ホストBクライアントからはホストBサーバへのアクセス
    ・ホストBクライアントからはホストAサーバへのアクセス
    の際に以下の例外が発生してしまいます。

    正常に動作する構成もあるので、原因がよくわかりません。
    Activator.GetObjectも成功しているのでファイアウォールの問題でもなさそうなのですが。。。

    この例外が発生する原因をご存知の方いらっしゃいましたらご教授お願いいたします。m(_ _)m

    --------------------------------------------------------
    System.InvalidCastException: 引数の戻り値の型が無効です。
       場所 System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type paramType)
       場所 System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg, Object[] outArgs, Object returnValue)
       場所 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       場所 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       場所 CompanyName.RemoteShell.Client.IShellFactory.Create()
       場所 CompanyName.RemoteShell.Client.TcpClient.Execute(String serverName, String commandLine, String& standardOutput, String& standardError)
    --------------------------------------------------------

    以下に各クラスのソースコードを示します。
    長文で申し訳ありませんがすべて関連していると思われるので。。

    【クライアント側】
    ■ITcpClientインターフェースは以下です。
    --------------------------------------------------------
    Imports System.Runtime.InteropServices

    ''' <summary>
    ''' RemoteShellクラスのインターフェース。
    ''' VC++6.0からRemoteShellクラスにアクセスする際にこのインターフェースを使用する。
    ''' </summary>
    Public Interface ITcpClient

        ''' <summary>
        ''' リモートコマンド実行処理
        ''' </summary>
        ''' <param name="serverName">サーバ名</param>
        ''' <param name="commandLine">実行するコマンドを指定する。引数もまとめて指定する。</param>
        ''' <returns>コマンドの実行結果を返す。ただしコマンドの実行に失敗した場合は-1を返す。</returns>
        Function Execute(ByVal serverName As String, ByVal commandLine As String, ByRef standardOutput As String, ByRef standardError As String) As Integer

    End Interface
    --------------------------------------------------------

    ■TcpClientクラス
    --------------------------------------------------------
    Imports System
    Imports System.Runtime.InteropServices
    Imports System.Runtime.Remoting
    Imports System.Runtime.Remoting.Channels
    Imports System.Runtime.Remoting.Channels.Tcp

    ''' <summary>
    ''' リモートシェルクライアントクラス。
    ''' 指定されたサーバに対してコマンド実行の要求を行います。
    ''' </summary>
    <ClassInterface(ClassInterfaceType.None), _
    Guid("EC4C522F-4C61-43d3-8165-8B4BA78A9849")> _
    Public Class TcpClient
        Implements ITcpClient

        Private tcpChannel As TcpChannel

        ''' <summary>
        ''' コンストラクタ。
        ''' </summary>
        Public Sub New()
            Try
                tcpChannel = ChannelServices.GetChannel("tcp")
                If tcpChannel Is Nothing Then
                    ' クライアントチャンネルを登録する。
                    tcpChannel = New TcpChannel()
                    ChannelServices.RegisterChannel(tcpChannel, False)
                End If
            Catch ex As Exception
                Console.Error.WriteLine(ex.ToString)
            End Try
        End Sub
        ''' <summary>
        ''' 指定されたサーバで指定されたコマンドを実行します。
        ''' </summary>
        ''' <param name="serverName">サーバ名</param>
        ''' <param name="commandLine">コマンドライン文字列</param>
        ''' <returns>実行したコマンドの戻り値を返します。コマンドが実行できなかったときは-1を返します。</returns>
        Public Function Execute(ByVal serverName As String, ByVal commandLine As String, ByRef standardOutput As String, ByRef standardError As String) As Integer Implements ITcpClient.Execute

            Try
                ' 引数のチェック
                If commandLine.Length <= 0 Then
                    Console.WriteLine("コマンドを指定してください。")
                    Return -1
                End If

                Dim factory As IShellFactory = CType(Activator.GetObject(GetType(IShellFactory), _
                                            "tcp://" + serverName + ":" + My.Settings.PortNo.ToString + "/RemoteShellFactory"), IShellFactory)


                Dim manager As IShellManager = factory.Create() '■■■■■■■例外が発生する箇所■■■■■■■

                If manager Is Nothing Then
                    Console.WriteLine("Could not locate server.")
                    Return 1
                End If

                Dim cmdArgs() As String = Split(commandLine)
                Dim response As Integer = manager.Execute(cmdArgs, standardOutput, standardError)
                'Console.Out.WriteLine("RemoteShell.vb:standardOutput=[" + standardOutput + "]")
                'Console.Error.WriteLine("RemoteShell.vb:standardError=[" + standardError + "]")
                Return response

            Catch ex As RemotingException
                Console.Error.WriteLine(ex.ToString)
                Return -1
            Catch ex As Exception
                Console.Error.WriteLine(ex.ToString)
                Return -1
            End Try

        End Function
    End Class
    --------------------------------------------------------

    ■IShellFactoryインターフェースは以下です。
    --------------------------------------------------------
    Imports System

    ''' <summary>
    ''' RemoteShellManagerクラスをRemoteShellServerから取得するためのファクトリインターフェース
    ''' </summary>
    Public Interface IShellFactory

        ''' <summary>
        ''' RemoteShellManagerクラスを生成します。
        ''' </summary>
        ''' <returns>生成されたRemoteShellManagerクラス</returns>
        Function Create() As IShellManager

    End Interface
    --------------------------------------------------------

    ■IShellManagerインターフェースは以下です。
    --------------------------------------------------------
    Imports System

    ''' <summary>
    ''' RemoteShellManagerクラスをクライアントで操作するためのインターフェース
    ''' </summary>
    Public Interface IShellManager

        ''' <summary>
        ''' リモートコマンドを実行します。
        ''' </summary>
        ''' <param name="cmdArgs">リモートで実行するコマンドライン。引数も含めて指定する。</param>
        ''' <param name="standardOutput">コマンド実行時に標準出力に出力された文字列</param>
        ''' <param name="standardError">コマンド実行時に標準エラーに出力された文字列</param>
        ''' <returns>コマンドの実行結果を返します。ただしコマンドの実行に失敗した場合は-1を返す。</returns>
        Function Execute(ByVal cmdArgs() As String, ByRef standardOutput As String, ByRef standardError As String) As Integer

    End Interface

    --------------------------------------------------------

    【サーバ側】
    ■ShellFactoryクラス
    --------------------------------------------------------
    Imports CompanyName.RemoteShell.Client

    ''' <summary>
    ''' RemoteShellを生成するファクトリクラス。
    ''' </summary>
    Public Class ShellFactory
        Inherits MarshalByRefObject
        Implements IShellFactory

        ''' <summary>
        ''' RemoteShellManagerクラスを生成して返します。
        ''' </summary>
        ''' <returns>IRemoteShellManagerインターフェース</returns>
        Public Function Create() As IShellManager Implements IShellFactory.Create
            Return New ShellManager
        End Function

        ''' <summary>
        ''' コンストラクタ。
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            Console.WriteLine("RemoteShellFactory activated.")
        End Sub
    End Class
    --------------------------------------------------------

    ■ShellManagerクラス
    --------------------------------------------------------
    Imports System
    Imports System.ComponentModel
    Imports System.Diagnostics.Process
    Imports System.MarshalByRefObject
    Imports System.Runtime.InteropServices
    Imports CompanyName.RemoteShell.Client

    ''' <summary>
    ''' リモートシェル管理クラス。
    ''' このクラスで実際にコマンドを実行します。
    ''' </summary>
    Public Class ShellManager
        Inherits MarshalByRefObject
        Implements IShellManager

        Private eventLog As EventLog

        ''' <summary>
        ''' コンストラクタ。
        ''' </summary>
        Public Sub New()
            eventLog = New EventLog()
        End Sub
        ''' <summary>
        ''' コマンド実行メソッド
        ''' </summary>
        ''' <param name="cmdArgs">コマンド文字列。引数も含む。</param>
        ''' <param name="standardOutput">標準出力文字列を返す。</param>
        ''' <param name="standardError">標準エラー出力文字列を返す。</param>
        ''' <returns>実行したコマンドの戻り値。ただしコマンドの実行に失敗した場合は-1を返す。</returns>
        Public Function Execute(ByVal cmdArgs() As String, ByRef standardOutput As String, ByRef standardError As String) As Integer Implements IShellManager.Execute

            Try
          
        ~ 省略 ~


            Catch e As Win32Exception
                standardError = e.Message()
                Diagnostics.EventLog.WriteEntry("RemoteShellServer", e.Message(), EventLogEntryType.Error)
                Return -1
            Catch e As Exception
                standardError = e.Message()
                Diagnostics.EventLog.WriteEntry("RemoteShellServer", e.Message(), EventLogEntryType.Error)
                Return -1
            End Try

        End Function
    End Class
    --------------------------------------------------------

    2006年10月19日 12:17
  • 自己解決できました。

    クライアントのコンポーネントをグローバルアセンブリキャッシュに登録するとうまく動きました。

    ホストAには登録が完了していたため、うまく動作していました。

    ありがとうございました。
    2006年10月19日 14:41