質問、意見はこちらに |
|
|
プロセス間通信とは
同一コンピューター上で起動しているアプリケーション間でデータを受け渡したいことは時々有る。
Frameworkには『リモート処理』という方法でデータの受け渡しを行なう方法が有る。
この方法に関してはいずれ又日を改めて説明することにするが、ここでは従来の方法のAPIを使用した、
プロセス間通信を紹介する。
この方法は、送信側はAPIのSendMessageで送り、受信側はWndProcのメッセージループで受け取ることになる。
難しいことはあまり無いのだが、文字列の送受信では構造体のCOPYDATASTRUCTを使うので、この処理が
少々面倒である。
送信側 仕様
先ず相手のアプリケーション名を入力して、送るメッセージと送る数値を2つ入力して「送信」を押すと
相手にメッセージが投げられるものとする。
コードの説明 宣言
APIは全部で3つ使用する、先ず相手のWindowのハンドルを取得する、「FindWindow」と
相手に数値を送る「SendMessage」と文字列を送る「SendMessage」であるSendMessageは同じ
名前の関数で有るが、引数の形が違います。
始めの関数は引数として1番目に相手のWindowのハンドルを、2番目、3番目に数値を持ちます。
一方2番目の「SendMessage」は1番目は同じで有るが2番目は0を3番目には「COPYDATASTRUCT」と言う
構造体を持ちます。
「COPYDATASTRUCT」は値渡しではなく参照渡し(ref)ですので注意して下さい。
C#コード
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern Int32 SendMessage(Int32 hWnd, Int32 Msg, Int32 wParam,
ref COPYDATASTRUCT lParam);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern Int32 SendMessage(Int32 hWnd, Int32 Msg,
Int32 wParam, Int32 lParam);
public const Int32 WM_COPYDATA = 0x4A;
public const Int32 WM_USER = 0x400;
//COPYDATASTRUCT構造体
public struct COPYDATASTRUCT
{
public Int32 dwData; //送信する32ビット値
public Int32 cbData; //lpDataのバイト数
public string lpData; //送信するデータへのポインタ(0も可能)
}
VB.NETコード
'COPYDATASTRUCT構造体
Public Structure COPYDATASTRUCT
Public dwData As Int32 '送信するビット値
Public cbData As Int32 'lpDataのバイト数
Public lpData As String '送信するデータへのポインタ(0も可能)
End Structure
Public Const WM_COPYDATA As Int32 = &H4A
Public Const WM_USER As Int32 = &H400
"user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
"user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function SendMessage( _
ByVal hWnd As IntPtr, _
ByVal wMsg As Int32, _
ByVal wParam As Int32, _
ByVal lParam As Int32) As Integer
End Function
"user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function SendMessage( _
ByVal hWnd As IntPtr, _
ByVal wMsg As Int32, _
ByVal wParam As Int32, _
ByRef lParam As COPYDATASTRUCT) As Integer
End Function
データの送信
C#コード
//送信ボタン押下
private void butSend_Click(object sender, EventArgs e)
{
Int32 result = 0;
//相手のウィンドウハンドルを取得します
Int32 hWnd = FindWindow(null, txtName.Text);
if (hWnd == 0)
{
//ハンドルが取得できなかった
MessageBox.Show("相手Windowのハンドルが取得できません");
return;
}
//文字列メッセージを送信します
if (txtMessage.Text != string.Empty)
{
//送信データをByte配列に格納
byte[] bytearry =
System.Text.Encoding.Default.GetBytes(txtMessage.Text);
Int32 len = bytearry.Length;
COPYDATASTRUCT cds;
cds.dwData = 0; //使用しない
cds.lpData = txtMessage.Text; //テキストのポインターをセット
cds.cbData = len + 1; //長さをセット
//文字列を送る
result = SendMessage(hWnd, WM_COPYDATA, 0, ref cds);
}
//数値メッセージを送信します
if (txtInt1.Text != string.Empty && txtInt2.Text != string.Empty)
{
Int32 int1 = 0;
Int32 int2 = 0;
try
{
//数値に正しく変換出来るか?
int1 = int.Parse(txtInt1.Text);
int2 = int.Parse(txtInt2.Text);
}
catch
{
MessageBox.Show("入力された数値が正しく有りません");
return;
}
//数値を送る
result = SendMessage(hWnd, WM_USER, int1, int2);
}
}
VB.NET コード
'送信ボタン押下
Private Sub butSend_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles butSend.Click
Dim result As Int32 = 0
'相手のウィンドウハンドルを取得します
Dim hWnd As Int32 = FindWindow(Nothing, txtName.Text)
If hWnd = 0 Then
'ハンドルが取得できなかった
MessageBox.Show("相手Windowのハンドルが取得できません")
Return
End If
'文字列メッセージを送信します
If txtMessage.Text <> String.Empty Then
'送信データをByte配列に格納
Dim bytearry() As Byte = _
System.Text.Encoding.Default.GetBytes(txtMessage.Text)
Dim len As Int32 = bytearry.Length
Dim cds As COPYDATASTRUCT
cds.dwData = 0 '使用しない
cds.lpData = txtMessage.Text 'テキストのポインターをセット
cds.cbData = len + 1 '長さをセット
'文字列を送る
result = SendMessage(hWnd, WM_COPYDATA, 0, cds)
End If
'数値メッセージを送信します
If txtInt1.Text <> String.Empty And txtInt2.Text <> String.Empty Then
Dim int1 As Int32 = 0
Dim int2 As Int32 = 0
Try
'数値に正しく変換出来るか?
int1 = CType(txtInt1.Text, Int32)
int2 = CType(txtInt2.Text, Int32)
Catch
MessageBox.Show("入力された数値が正しく有りません")
Return
End Try
'数値を送る
result = SendMessage(hWnd, WM_USER, int1, int2)
End If
End Sub
|