 |
2010年02月24日(水) |
 |
|
C#のサービスとC++アプリケーションのプログラム間通信 |
- 開発環境
- OS:Windows 7 Ultimate
- IDE:Visual Studio 2008 SP1
- 概 要
デスクトップアプリケーション(C++)の起動時、サービスプログラム(C#)に起動したことを通知。
終了時、同様に終了したことを通知する。
プログラム間通信には名前付きパイプを使用する。
- サービスプログラム(C#)
- System.Timers.Timer をツールボックスからドラッグ。プロパティ・イベントに以下の内容で設定。
- プロパティ -
Name=timer
Interval=300
- イベント -
Elapsed=timer_Elapsed
- サービスの開始イベント - OnStart()
protected override void OnStart( string[] args )
{
timer.Start();
}
- サービスの停止イベント - OnStop()
protected override void OnStop()
{
timer.Stop();
}
- タイマーイベント - timer_Elapsed
private void timer_Elapsed( object sender, ElapsedEventArgs e )
{
char [] readBuff = new char[100];
NamedPipeServerStream pipeStream = null;
StreamReader reader = null;
StreamWriter writer = null;
// タイマーの中断
timer.Stop();
try {
// アクセス権限の取得
PipeSecurity pipeSecurity = GetPipeSecurity();
// 名前付きパイプのオープン
pipeStream = GetPipeStream( pipeSecurity );
// 接続を待機する
pipeStream.WaitForConnection();
// 受信データの読込
reader = new StreamReader( pipeStream );
reader.Read( readBuff, 0, 8 );
string readString =
new string( readBuff, 0, BUFF_SIZE );
・
・ (ここに処理を記述する)
・
// 送信データの書込
writer = new StreamWriter( pipeStream );
writer.Write( "OK" );
writer.Flush();
} catch( Exception ex ) {
・
・
} finally {
if( pipeStream != null ) {
pipeStream.Dispose();
pipeStream = null;
}
// タイマーの再開
timer.Start();
}
}
- アクセス権限の取得 - GetPipeSecurity()
WellKnownSidType.WorldSid とすることでどのユーザーからもアクセス
可能とする。
※この AddAccessRule をしておかないと、呼出側は、ERROR_ACCESS_DENIED (5) でエラーになる。
private PipeSecurity GetPipeSecurity()
{
PipeSecurity pipeSecurity = null;
using( NamedPipeServerStream pipeStream = new NamedPipeServerStream(
"MyPipe", PipeDirection.InOut, 1,
PipeTransmissionMode.Message, PipeOptions.None ) )
{
// PipeSecurity オブジェクトを取得
pipeSecurity = pipeStream.GetAccessControl();
}
SecurityIdentifier worldSid = new SecurityIdentifier(
WellKnownSidType.WorldSid, null );
// アクセス規則を、アクセス制御リスト (DACL) に追加
pipeSecurity.AddAccessRule(new PipeAccessRule( worldSid,
PipeAccessRights.ReadWrite, AccessControlType.Allow ) );
return pipeSecurity;
}
- 名前付きパイプのオープン - GetPipeStream()
private NamedPipeServerStream GetPipeStream(PipeSecurity pipeSecurity)
{
return new NamedPipeServerStream( "MyPipe", PipeDirection.InOut, 1,
PipeTransmissionMode.Message, PipeOptions.None, 256, 256,
pipeSecurity );
}
※PipeSecurity を指定するコンストラクタには、in/out のバッファサイズまで
指定しなければならなかったのでとりあえず、ともに 256 としておいた。
- デスクトップアプリケーション(C++)
- 名前付きパイプでの送受信
int DoCallNamedPipe(char* pszSendBuff, int nSendSize)
{
SetLastError( NO_ERROR );
char szReadBuff[10];
DWORD dwRead;
ZeroMemory( szReadBuff, sizeof(szReadBuff) );
CallNamedPipe( _T("\\\\.\\pipe\\MyPipe"), pszSendBuff, nSendSize,
&szReadBuff, sizeof(szReadBuff), &dwRead, 300 );
return GetLastError();
}
※C#のパイプ名との差異に注意!!
- WM_CREATE
DoCallNamedPipe( "START", strlen( "START" ) );
- WM_DESTROY
DoCallNamedPipe( "END", strlen( "END" ) );
|
|