第241章 プロセス


今回は、内容をガラッと変えて、プロセスに関することをやります。 といっても難しいことは省略して、すぐに自分のプログラムに 使えるものを中心にやります。



まずは、実行可能ファイルを実行するプロセスを作成してみます。

BOOL CreateProcess( LPCTSTR lpApplicationName, // 実行可能モジュールの名前 LPTSTR lpCommandLine, // コマンドライン文字列 LPSECURITY_ATTRIBUTES lpProcessAttributes, // プロセスセキュリティ属性 LPSECURITY_ATTRIBUTES lpThreadAttributes, // スレッドセキュリティ属性 BOOL bInheritHandles, // ハンドルの継承の有無 DWORD dwCreationFlags, // プロセスの実行方法 LPVOID lpEnvironment, // 新しいプロセスの環境設定ポインタ LPCTSTR lpCurrentDirectory, // 新しいプロセスのカレントディレクトリ LPSTARTUPINFO lpStartupInfo, // STARTUPINFO構造体へのポインタ LPPROCESS_INFORMATION lpProcessInformation // PROCESS_INFORMATION構造体へのポインタ );

lpApplicationNameは実行ファイルの名前です。フルパスを指定しないときは カレントディレクトリのファイルが実行されます。拡張子がexeの時は省略可能です。

lpCommandLineにはコマンドラインを指定します。lpApplicationNameをNULLにしたときは 実行プログラム名も指定します。

lpProcessAttributesには、LPSECURITY_ATTRIBUTES構造体のポインタを指定します。

lpThreadAttributesには、LPSECURITY_ATTRIBUTES構造体のポインタを指定します。

bInheritHandlesには、新しいプロセスが親プロセスのハンドルを継承するかどうかを 指定します。

dwCreationFlagsには、プロセスの実行方法を指定します。

CREATE_DEFAULT_ERROR_MODE親プロセスのエラーモードを継承しない
CREATE_NEW_CONSOLE新しいプロセスは新しいコンソールを持つ
CREATE_NEW_PROCESS_GROUP新しいプロセスは新しいプロセスグループのルートになる
CREATE_SEPARATE_WOW_VDM16ビットプログラムを別のprivate Virtual DOS Machine (VDM)で 開始する。(NT)
CREATE_SHARED_WOW_VDM16ビットウィンドウプログラムを開始するときのみ有効(NT)。
CREATE_SUSPENDED新しいプロセスのプライマリスレッドをサスペンド状態にする。
CREATE_UNICODE_ENVIRONMENTlpEnvironment環境変数でUNICODE文字セットを使う。
DEBUG_PROCESS呼び出し元がデバッグされている状態で新しいプロセスを作成する。
DEBUG_ONLY_THIS_PROCESS現在のデバッグ状態を子供に接続しない。
DETACHED_PROCESSコンソールプロセスに対して、新しいプロセスはコンソールを持たない。

この他に優先順位クラスを加えることができます。

HIGH_PRIORITY_CLASS高優先順位クラス
IDLE_PRIORITY_CLASS最低優先順位クラス
NORMAL_PRIORITY_CLASS普通の優先順位
NORMAL_PRIORITY_CLASSプリエンプティブ方式のOSの動作を均等に割り当てる

lpEnvironmentは、新しいプロセスの環境設定ポインタを指定します。
name = value
という一連のNULLで終わる文字列で指定して、最後に2つのNULLをつけます。

lpCurrentDirectoryには、新しいプロセスのカレントディレクトリとして使用するパスを指定します。 NULLを指定すると呼び出し元と同じディレクトリとなります。

lpStartupInfoには、表示形式を指定します。

lpProcessInformationには、PROCESS_INFORMATION構造体のポインタを指定します。

成功すると0以外が返されます。

さて、CreateProcess関数で作成したプロセスが終了しても、プロセスのハンドルや スレッドのハンドルはシステム内に残ります。(不要になったらすぐにCloseHandleする)

typedef struct _SECURITY_ATTRIBUTES { // sa DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES;

nLengthはこの構造体の大きさです。

lpSecurityDescriptorはセキュリティデスクリプタへのポインタです。Windows95/98では無視されます。

bInheritHandleは、新しいプロセスが作られたときにハンドルを継承するかどうかを指定します。

STARTUPINFO構造体は次のように定義されています。それぞれのメンバの意味は コメントを参考にしてください。

typedef struct _STARTUPINFO { // si DWORD cb; //構造体の大きさ LPTSTR lpReserved; //予約済み LPTSTR lpDesktop; //NT用 LPTSTR lpTitle; //コンソールアプリのタイトル DWORD dwX; //x位置 DWORD dwY; //y位置 DWORD dwXSize; //幅 DWORD dwYSize; //高さ DWORD dwXCountChars; //コンソールの幅(キャラクタ単位) DWORD dwYCountChars; //コンソールの高さ DWORD dwFillAttribute; //コンソールの前景および背景色 DWORD dwFlags; //どのメンバが有効か WORD wShowWindow; //ウィンドウの表示のパラメータ(ShowWindow) WORD cbReserved2; LPBYTE lpReserved2; HANDLE hStdInput; //入力用ハンドル HANDLE hStdOutput; //出力用ハンドル HANDLE hStdError; //エラーハンドル } STARTUPINFO, *LPSTARTUPINFO;

PROCESS_INFORMATION構造体は次のように定義されています。

typedef struct _PROCESS_INFORMATION { // pi HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; } PROCESS_INFORMATION;

hProcessは新しいプロセスのハンドルです。

hThreadは新しいプロセスのメインスレッドのハンドルです。

dwProcessIdはプロセスIDです。

dwThreadIdはスレッドIDです。

では、プログラムを見てみましょう。これはメニューの 「子プロセスを起動」で「ファイルを開く」コモンダイアログが出てきます。 ここで、起動したいexeを選択すると、それが起動します。

// process01.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "プロセス(&P)" BEGIN MENUITEM "子プロセスを起動(&C)", IDM_PRO END END

メニューのリソース・スクリプトです。

// process01.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); void MyChildProcess(HWND); char szClassName[] = "process01"; //ウィンドウクラス int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるプロセス", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; switch (msg) { case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_PRO: MyChildProcess(hWnd); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; } void MyChildProcess(HWND hWnd) { OPENFILENAME ofn; char szFile[MAX_PATH], szTitle[MAX_PATH]; STARTUPINFO si; PROCESS_INFORMATION pi; memset(&ofn, 0, sizeof(OPENFILENAME)); strcpy(szFile, ""); strcpy(szTitle, ""); memset(&si, 0, sizeof(STARTUPINFO)); memset(&pi, 0, sizeof(PROCESS_INFORMATION)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "プログラム(*.exe)\0*.exe\0全て(*.*)\0*.*\0\0"; ofn.lpstrFile = szFile; ofn.lpstrFileTitle = szTitle; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = "exe"; ofn.lpstrTitle = "起動する子プロセスを選択"; ofn.nMaxFileTitle = MAX_PATH; GetOpenFileName(&ofn); CreateProcess(NULL, szFile, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if (CloseHandle(pi.hProcess)) MessageBox(hWnd, "プロセスハンドルの破棄成功", "OK", MB_OK); if (CloseHandle(pi.hThread)) MessageBox(hWnd, "スレッドハンドルの破棄成功", "OK", MB_OK);; return; }

簡単なので一気に表示しました。CreateProcess関数が実行されたあと、特にプロセスや スレッドのハンドルは不要なので、直ちにCloseHandleしています。

新しく作ったプロセスと連絡をとりたいときは、どうすればよいのでしょうか。 今までもいくつか出てきました。復習してみてください。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 24/Nov/1999 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。