読者です 読者をやめる 読者になる 読者になる

★ The Tsuchinoko News 2 (つちのこ通信2) ★

重要な話から、どうでもいいことまで。ほとんど役に立たないことを書き連ねています。

【PC】VB6 から VB2010 への移行(その3)プロセス間通信(送信)

IT雑感

f:id:tsuchinoko118:20120425070932j:image:w560過去の資産としてVisual Basic 6 のものがあったとして、全システムを一気に .NET(Visual Studio 2010)まで持っていければ一番いいのだろうけれども、費用や時間の問題からなかなかそうは出来ないケースもある。

そんなとき、筆者は、とくに変更したい一部(変更しなくてはならない一部)を、またもや VB6を引っ張り出して書き直すのではなく、将来的なことも考えて VB2010 で書くことにしている。このとき完全に独立したプロセス(プログラム)なら Shell() で呼び出せばそれでおわりだが、VB6のプロセスと VB2010 のプロセスで何らかの連絡や共有を行いたい場合がある。

一番簡単な共有はファイルだが速度に問題がありそうだ。次の選択肢としてはメモリマップトファイル(MMF)で”共有メモリ”を使う方法で VB2010(.NET Freamwork 4)なら元から MMF のクラスもあって取り扱いも容易だ。

しかしながら何らかの連絡を行いたい場合には、どちらもタイマーで値の変更を監視したりしなければならず、けっこうなリソースを食ってしまう。実際にやってみたが、ややもたつきを感じるくらいには速度も落ちる。

そこで筆者は、窓から窓にメッセージを投げつける PostMessage を使うことにしている。

メッセージの受信は少々ややこしいが、送信はカンタン。


VB6 の場合

Private Declare Function FindWindow _
    Lib "user32" Alias "FindWindowW" _
    (ByVal lpClassName As String, _
     ByVal lpWindowName As String) As Long


Private Declare Function PostMessage _
    Lib "user32" Alias "PostMessageW" _
   (ByVal hwd As Long, _
    ByVal msg As Long, _
    ByVal wpara As Long, ByVal lpara As Long) As Long

const pmSTART = &h0
const pmDATA = &h1
const pmEND = &h2

Public Sub VB6から送信(Str As String)

    Dim hSend As Long
    Dim c as string
    Dim I as integer

    hSend = FindWindow(vbNullString, "相手のプロセスの窓の名前")
    If hSend <> 0 Then
    
        
        'メッセージ送信開始
        PostMessage hSend,"適当な共有名",pmSTART, 0
        
        '文字列の送信
        For I = 1 To Len(Str)
          c = Mid(Str, I, 1)
          PostMessage hSend,"適当な共有名",pmDATA, Asc(c)
        Next
        
        'メッセージ送信終了
        PostMessage hSend,"適当な共有名",pmEND, 0

    End If

End Sub

というような感じ。
APIのFindWindowで、メッセージを送りたい相手の窓の名前からハンドルを取得。そこに PostMessageでメッセージを投げつけている。

Const で定義した pmSTART や pmDATA は 勝手ルール。受信側でこのルールに基づいて処理をして受け取るようにする。この場合 VB6 から VB2010 へ投げつけているので、受信の処理は VB2010 側に記述することになる。



VB2010 の場合(ほぼ同じ・・・というか全く同じ(笑))

 _
          Private Function FindWindow( _
            ByVal lpClassName As String, _
            ByVal lpWindowName As String) As IntPtr
          End Function

 _
          Public Function PostMessage( _
                            ByVal hwd As IntPtr, _
                            ByVal msg As IntPtr, _
                            ByVal wpara As IntPtr, _
                            ByVal lpara As IntPtr) As IntPtr
          End Function

const pmSTART = &h0
const pmDATA = &h1
const pmEND = &h2


Public Sub VB2010から送信(Str As String)

    Dim I As Integer
    Dim c as string

   'ハンドル取得
    Dim hWnd As Int32 = FindWindow(Nothing,"VB6の窓の名前")
    If hWnd <> 0 Then

       'メッセージ送信開始
       PostMessage(hWnd,"適当な共有名",pmSTART, 0)

       '文字列の送信
       For I = 0 To Str.Length - 1
           c = Str.Substring(I, 1)    
           PostMessage(hWnd,"適当な共有名",pmDATA,Asc(c))
       Next

       'メッセージ送信終了
       PostMessage(hWnd,"適当な共有名",pmEND, 0)

    End If

End Sub

これで VB6 へメッセージを投げつけることができる。

あとは「受信」をそれぞれに用意するが「そういう仕掛けをつくる」のはちょっとややこしい。これは次回。