Emotion Wave Tech Blog

福岡にあるエモーションウェーブ株式会社のエンジニアが書いています。

VB.netでプロセス間通信(IpcChannel)

最近、webネタが多いのでたまには、.netネタでも。

あまり使う事ないですが、プロセス間で情報のやり取りをしたい時があると思います。 手法は、HTTPやTCPやIPCがありますが、今回は、同一マシン上のプロセス間で行いたいと思いますので、 IPCチャンネルを利用してコーディングしたいと思います。

今回のソリューションの構成は、下記の通り。

ipclibプロジェクト
 ・IpcServerクラス
 ・IpcClientクラス
 ・IpcSharedObjectクラス

serverプロジェクト
 ・form1クラス(画面)

clientプロジェクト
 ・form1クラス(画面)

まずは、サーバー側

Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc

Public Class IpcServer

    Public Property SharedObject() As IpcSharedObject
    Private _channel As IpcServerChannel

    Public Sub New()

        ' チャンネルを登録
        Me._channel = New IpcServerChannel("ipcsrv")
        ChannelServices.RegisterChannel(Me._channel, True)

        ' リモートオブジェクトを生成して公開
        Me._SharedObject = New IpcSharedObject()
        RemotingServices.Marshal(Me._SharedObject, "ipccli", GetType(IpcSharedObject))

    End Sub
End Class

続いてクライアント側

Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc


Public Class IpcClient

    Public Property SharedObject As IpcSharedObject
    Private _channel As IpcClientChannel

    Public Sub New()
        ' クライアントチャンネルの生成
        Me._channel = New IpcClientChannel()

        ' チャンネルを登録
        ChannelServices.RegisterChannel(Me._channel, True)

        ' リモートオブジェクトを取得
        Me._SharedObject = TryCast(Activator.GetObject(GetType(IpcSharedObject),
                                                   String.Format("ipc://{0}/{1}", "ipcsrv", "ipccli")
                                                   ), IpcSharedObject)

    End Sub


End Class

そして、サーバーとクライント側共有するオブジェクト

''' <summary>
''' IPCプロトコル間で共有するクラス
''' </summary>
''' <remarks></remarks>
<Serializable()>
Public Class IpcSharedObject
    Inherits MarshalByRefObject

    ''' <summary>
    ''' ReceivedMessageイベントを発生される(メッセージ送信→メッセージ受信の流れ)
    ''' </summary>
    ''' <param name="message"></param>
    ''' <remarks></remarks>
    Public Sub SendMessage(ByVal message As String)
        'イベントを発生させる
        RaiseEvent ReceivedMessage(message)
    End Sub


    ''' <summary>
    ''' メッセージ受信をイベント
    ''' </summary>
    ''' <param name="messsage"></param>
    ''' <remarks></remarks>
    Public Event ReceivedMessage(ByVal messsage As String)



    ''' <summary>
    ''' インスタンスの有効期間を無制限にするにオーバーライドして戻り値を無効にする
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function InitializeLifetimeService() As Object
        Return Nothing
    End Function

End Class

そして、各ipclibを画面側で呼び出します。 まず、サーバー側画面

Imports ipclib

Public Class server

    Public Sub ReceivedMessage(msg As String)

        Me.Label1.Text = msg
    End Sub

    Private Sub server_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Dim srv = New IpcServer()
        '受信時のイベントを関連付け
        AddHandler srv.SharedObject.ReceivedMessage, AddressOf ReceivedMessage
    End Sub
End Class

最後にクライント側画面

Imports ipclib

Public Class client
    Private cli As IpcClient


    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    'サーバ側プロセスへメッセージを送信
        cli.SharedObject.SendMessage(Me.TextBox1.Text)
    End Sub

    Private Sub client_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        cli = New IpcClient()
    End Sub
End Class

そして実行するとこんな感じでプロセス間でデータのやり取りができます。

f:id:devew:20190322101141p:plain