異なるプロセス間でのイベントハンドル共有

このQ&Aのポイント
  • WIN32 APIのDuplicateHandleを用いて、異なるプロセス間でのイベントハンドルを共有するためのプログラムを実行すると、想定した動作ができずにエラーが発生します。
  • プロセスAで本物のプロセスハンドルを取得し、プロセスAでイベントを作成します。
  • プロセスBでプロセスAが取得した本物のハンドルとイベントハンドルを用いてイベントハンドルを複製すると、エラーが発生します。
回答を見る
  • ベストアンサー

異なるプロセス間でのイベントハンドルの共有

異なるプロセス間でのイベントハンドルの共有 WIN32 APIのDuplicateHandleを用いて、異なるプロセス間でのイベントハンドルを共有したいのですが、うまく動作しません。(1)~(3)にプログラムの詳細を示します。 (1) プロセスAで「本物」のプロセスハンドルを取得   DuplicateHandle(     GetCurrentProcess(),         GetCurrentProcess(),    // 疑似ハンドル     GetCurrentProcess(),     &RealProcessHandle,     // 本物のハンドル     0,     FALSE,     DUPLICATE_SAME_ACCESS   ); (2) プロセスAでイベントを作成   hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); (3) プロセスBでイベントハンドルを複製   DuplicateHandle(     RealProcessHandle,     // プロセスAが(1)で取得した本物のハンドル     hEvent,           // プロセスAが(2)で取得したイベントハンドル     GetCurrentProcess(),     &hNewEvent,         // プロセスBで利用するためのイベントハンドル     0,     FALSE,     DUPLICATE_SAME_ACCESS   ); 上記のプログラムを実行すると、(1)と(2)は成功するものの、(3)の時点でエラーになり、 GetLastErrorでは6(ハンドルの異常)が表示されます。 プログラムのどこが悪いのでしょうか? 尚、OpenEventによるイベントハンドル共有は、 イベントに名前をつけなくてはならない問題があり、利用しない方針です。

質問者が選んだベストアンサー

  • ベストアンサー
  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.2

作成元のプロセスおよび、作成したハンドルに対して 適切なアクセス権を与えていますか? 特にPROCESS_DUP_HANDLEは、NT/2000以降では必須です。 また、関数に指定するハンドルが間違っているような気がします。 第1引数は”プロセスのハンドル”であり、第4引数は”複製する対象のハンドル”です。 提示されたソースではどちらが正しいのかわかりませんが、 もう一度、MSDNを確認し関数仕様を確認された方が良いように思います。 >&RealProcessHandle,     // 本物のハンドル >RealProcessHandle,     // プロセスAが(1)で取得した本物のハンドル なお、異なるプロセス間では、名前付き以外で共有する場合、 共有メモリや名前付きパイプなどを使用しなければならないパターンもあり 端から名前付きイベントを作成した方が安全な場合もあるので、 本当に名前付きイベントではダメなのか、再考するほうが良いかも知れません。

参考URL:
http://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx
_hitoshi_
質問者

お礼

別プロセスのプロセスハンドルを得るのに、 プロセスIDからOpenProcess関数を使い、 それからDuplicateHandle関数を実行することでうまくいきました。 ありがとうございました。

_hitoshi_
質問者

補足

別プロセスのプロセスハンドルを得るのに、 プロセスIDからOpenProcess関数を使い、 それからDuplicateHandle関数を実行することでうまくいきました。 ありがとうございました。

その他の回答 (1)

  • SaKaKashi
  • ベストアンサー率24% (755/3136)
回答No.1

ハンドルはポインターでアドレスを示すものなので、プロセスAのアドレスはプロセスBでは不当なアドレスになります。

_hitoshi_
質問者

お礼

ありがとうございました。

関連するQ&A

  • イベントハンドルのリーク(?)

    御世話になります。 別の質問 https://okauth.questionbox.jp.msn.com/qa7662007.html で、トラブってるプログラムがあります。(C++) (ハンドル数が増加する) そこで、Process Explorer の Handle view でみたところ、種類が"Event"となっているハンドルが増えている(リーク?)しているようです。(減っていかない) 言葉を素直に受け取ると、「イベントハンドルがリークしている」と言う解釈で良いのでしょうか? であるとすると、「イベントハンドルがリーク」する状況とはどういった状況なのでしょうか? 少なくとも、該当ソースの中にCreateEvent等によるイベントの作成は行っていないのですが・・・ どなたか何か思い当たる事があればご教授頂けると幸いです。 以上、よろしくお願いいたします。

  • プロセスのハンドルを確保

    AプログラムからBプログラムを起動するプログラムを作成しています。 AはループでBプログラムを起動するのですが、Aでプロセスの起動数をチェックし、飽きのプロセスハンドルを確保しBプログラム意を起動する際にAで確保したハンドルを使用して起動するような処理をするにはどうしたらいいでしょうか? 例:プロセス最大起動数:5   Aは10回ループし、Bを起動する。   Aでプロセスハンドルを5個確保する。   Bを起動する際に確保したハンドルを1個使用する。   Bが終了したらハンドルを解放する。   

  • 非同期のプロセス間通信(パイプ)で全データ受信する

    こんにちは。 非同期のプロセス間通信(パイプ)で詰まっています。 環境はWindowsで処理系はC++(Win32)です。 スレッドを用意して、 hPipe = ::CreateFile( L"\\\\.\\pipe\\pipename", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ) ; で作成し、OVERLAPPED構造体を // ZeroMemory( &so, sizeof( OVERLAPPED )) ; sOverlapped.hEvent = ::CreateEvent( NULL, FALSE, FALSE, NULL ) ; として、 const size_t bufsize = 16 ; BYTE     buffer[ uBufSize ] ; DWORD    dwNumberOfBytesRead ; bRet = ::ReadFile( hPipe, buffer, bufsize, &dwNumberOfBytesRead, &so ) ; で読み込みをしています。ReadFile関数はすぐ戻りbRetはFALSEで返ってくるため、GetLastErrorを調べて、 switch( ::GetLastError()) {   case ERROR_IO_PENDING :     bRet = ::GetOverlappedResult( hPipe, &so, &dwNumberOfBytesRead, FALSE ) ;     break ; } としてWaitForMultipleObjectsでsOverlapped.hEventがシグナル状態になったら取得したデータの処理をしています。 シグナル状態になるならないに関わらず、上記のReadFileとGetOverlappedResultはループでぐるぐる回しています。 上記の状態で短いデータならよかったのですが、上記のReadFileで読み込み最大サイズの16バイトを超えてしまとうと、 残りの部分のみしか取得できませんでした。 0123456789ABCDEFabcdefg というデータを受信しようとしたとき、後半のabcdefgだけしか取得できませんでした。 すべてのデータを正しく取得するにはどのようにしたらよいのでしょうか?

  • マルチスレッドプログラミングについて

    こんばんわ。 マルチスレッドプログラミングを行なっています。開発環境はVC++.NET2003でC言語を用いてコンソールアプリケーションを勉強中です。 以下にプログラムを示します。 以下のプログラムは、 (1)ThAとThBが交互に1~10までカウントUP (2)ThBだけが11~20までカウントUP (3)ThAはTh11から、ThBは21からカウントUP というプログラムを記述したつもりなのですが・・・実行開始後は(1)から(3)のように表示できるのですが、それ以降はThAとThBが交互に表示されてしまいます。 (1)から(3)を繰り返す記述の仕方はありますでしょうか? よろしくお願い致します。 HANDLE hEvent[3]; unsigned __stdcall ThB(void *lpx){ int j; int l=1; for(j=1;j<100;j++){ Sleep(100); printf("ThB%d\n",j); if(l%20==0){ SetEvent(hEvent[0]); } l++; } return 0; } unsigned __stdcall ThA(void *lpx){ int k; int j=1; for(k=1;k<100;k++){ Sleep(100); printf("ThA%d\n",k); if(j%10==0){ WaitForSingleObject(hEvent[0],INFINITE); } j++; } SetEvent(hEvent[2]); return 0; } int main(int argc ,char *argv[]){ unsigned int thID[2]; HANDLE hTh[2]; int i; hEvent[0] = CreateEvent(NULL, TRUE, FALSE, "CH0"); hEvent[1] = CreateEvent(NULL, TRUE, FALSE, "CH1"); hEvent[2] = CreateEvent(NULL, TRUE, FALSE, "MAINEVENT"); hTh[0] = (HANDLE)_beginthreadex(NULL, 0, ThA, NULL, 0, &thID[0]); hTh[1] = (HANDLE)_beginthreadex(NULL, 0, ThB, NULL, 0, &thID[1]); WaitForSingleObject(hEvent[2], INFINITE); for(i=0;i<2;i++) CloseHandle(hTh[i]); return 0; }

  • マルチスレッドプログラミングについて

    マルチスレッドプログラミングについていくつか教えて下さい。 マルチスレッドの基礎がまだ分かってないので初心者でも分かり易いようにお願いします。 1:イベントオブジェクトについて教えて下さい。 「イベントオブジェクト」の概念がよく分かりません。 ○シグナル状態と非シグナル状態とはどういう状態なのでしょうか? ○自動リセットの場合ではどのタイミングで切り替わっているのでしょうか?(下記のソースの場合) ○手動リセットの場合ではどのタイミングで切り替えればよいのでしょうか?(下記のソースの場合) 2:CloseHandle() と ExitThread() について教えて下さい。 ○この2つの関数の役割の違いについて教えて下さい。 「スレッドハンドルを閉じる=スレッドを終了」ではないのでしょうか? また、これらの関数実行時にシグナル状態は気にする必要はありますか?(シグナル状態にしなくてよいのか?) 下記のソースは簡略化のためかなり省略されています。 DWORD WINAPI ThreadProc( DWORD i ) { while( true ) { DWORD r = WaitForMultipleObjects( 2, hEvent, FALSE, INFINITE ); if( r == WAIT_OBJECT_0 ) { // 処理1 } else if( r == WAIT_OBJECT_0 ) { // 処理2 } else { ExitThread( TRUE ); // スレッド終了 } } } void MainProc() { // 自動リセットのイベントオブジェクト作成 for( int i=0; i<2; i++ ) { hEvent[i] = CreateEvent( NULL, FALSE, FALSE, NULL ); } // スレッドを作成 hThread = CreateThread( NULL, 0, ThreadProc, NULL, 0, &dwThreadID ); }

  • 【C++】セマフォとプロセスの使い方

    【C++】セマフォとプロセスの使い方 WindowsXPでVC++2008コンパイラを使用して、 プロセスとセマフォについて勉強しています。 外部プログラム(今回は電卓として)を5つ立ち上げるのですが、 同時に立ち上げるのは2つまでとしたい場合、どのように組むのでしょうか。 http://nienie.com/~masapico/api_CreateSemaphore.html こちらにスレッドを使用したセマフォを使ったサンプルがあるのでが、 プロセスを使うとなると、うまく書けません。 ご指導頂けませんでしょうか。 ===現在まで書いたソース=== (5つのプロセスをつくるループも実装していませんが、、、) #include<windows.h> #include<stdio.h> #include<tchar.h> HANDLE g_hSemaphre; void main(){ BOOL bRet; STARTUPINFO si; PROCESS_INFORMATION pi; //Semaphoreオブジェクト g_hSemaphre = CreateSemaphore(NULL,2,2,NULL); bRet = CreateProcess(_T("C:\\WINDOWS\\system32\\calc.exe"), _T(""), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); //プロセス終了 WaitForSingleObject(pi.hProcess,INFINITE); //後処理(プロセス開放) ReleaseSemaphore(g_hSemaphre,1,NULL); //スレッドとプロセスを閉じる。 CloseHandle(pi.hThread); CloseHandle(pi.hProcess); //Semaphoreオブジェクト CloseHandle(g_hSemaphre); }

  • ReadFileでエラーが出ます。

    シリアルポートで非同期でバイナリを受信するプログラムを作成しています。 受信部分は以下のソースです。これで実行すると「データ受信エラー」のダイアログが出ます。 GetLastErrorでは998(メモリ ロケーションへのアクセスが無効です。)が得られました。 ネットで調べましたが何が原因かも分かりません・・。 どうかアドバイスお願いします。 HANDLE hEvent; hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); OVERLAPPED old; ZeroMemory( &old, sizeof(old) ); old.Offset = 0; old.OffsetHigh = 0; old.hEvent = hEvent; DWORD dwCount; char* rdBuf; DWORD dwRead; if(!ReadFile(hCom,rdBuf,dwCount,&dwRead,&old)){ if(ERROR_IO_PENDING == GetLastError()){ GetOverlappedResult(hCom,&old,&dwRead,TRUE); } else MessageBox("データ受信エラー","試作1",MB_ICONSTOP); }

  • 親プロセスの切り離し?

    USBメモリ内で動作するプログラムから、パソコンにインストールされているプログラムを起動後、USBメモリ内にあるプログラムは自動的に終了するようにしています。 この状態で、"ハードウェアの安全な切り外し"で、USBメモリを停止できるようにしたいのですが、何かいい方法はないでしょうか? 試しにメモ帳を利用する、次のコンソールプログラムを作って、USBメモリ内で起動したところ、やはりUSBメモリを停止することができませんでした。 -- #include <windows.h> int main(int argc, char* argv[]) { BOOL bRes; STARTUPINFO si={0}; PROCESS_INFORMATION pi={0}; si.cb = sizeof(STARTUPINFO); if(CreateProcess(NULL, "C:\\Windows\\notepad.exe C:\\a.txt", NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); bRes=TRUE; } return 0; } -- ※C:\\a.txtは適当なテキストファイルを作成して置いてます。 普段、秀丸エディタを使っているので、試しに "C:\\Windows\\notepad.exe C:\\a.txt" を "C:\\Program Files\\Hidemaru\\Hidemaru.exe C:\\a.txt" に変更した試したところ、USBメモリを停止することができました。 秀丸エディタだとUSBメモリを停止することができるので、起動される側のプログラムで何かすれば停止できるようになるとは思いますが、何をすればいいのかさっぱりわからず困っています。

  • 実行中のプログラムIDが取得できない

    ウイルスソフトが動作を占拠して長い間パソコンが動かない対策としてccsvchst.exeの動作を強制終了させるため、以下のプログラムを組みましたが、プロセスID(ハンドル)が取得できません。 タスクマネージャーの終了ボタンからは終了します。 Process32First(hProcesss,&P32); do { if(strcmp("ccsvchst.exe", P32.szExeFile)==0) { handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, P32.th32ProcessID); ・ ・ ・ } ・ ・ ・ } while(Process32Next(hProcesss, &P32) != 0);

  • JavaScript でキーを送る

    JavaScript でキーを送る のはどうしたらいいのでしょうか。 キーボードからではなく、自動的に任意のキーを押させたいのです。 // aキーのkeydownイベントを起こす var _e = document.createEvent("KeyboardEvent"); _e.initKeyEvent("keydown", true, true, null, false, false, false, false, 65, 0); document.getElementById("dummy").dispatchEvent(_e); いろいろ検索して上記のも試しましたが、IE8では動作が確認できませんでした。 IEじゃ無理なんでしょうか。