:C++で:: CreateProcessを呼び出してWindows実行ファイルを起動するにはどうすればよいですか?例を探してい
- はEXEが終了するのをEXE
- 待機を起動します。
- 実行ファイルが終了したら、すべてのハンドルを適切に閉じます。
:C++で:: CreateProcessを呼び出してWindows実行ファイルを起動するにはどうすればよいですか?例を探してい
このような何か:
STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;
if (CreateProcess(path, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx
の例では、ちょうどあなたの定数やプログラムを含む変数とargv[1]
を置き換えるがあります。
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain(int argc, TCHAR *argv[])
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if(argc != 2)
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
// Start the child process.
if(!CreateProcess(NULL, // No module name (use command line)
argv[1], // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return;
}
// Wait until child process exits.
WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
あなたのexeファイルは、コンソールアプリケーションであることを起こる場合は、あなたがstdoutとstderrを読んで興味があるかもしれない - そのために、私は謙虚にあなたを参照してくださいよこの例では:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q190351
これは、コードの一口のビットだが、私は産卵して読み取るために、このコードのバリエーションを使用しました。
半関連のメモで、現在のプロセスよりも多くの権限を持つプロセスを開始する場合(通常のユーザーとして実行されているメインアプリケーションから管理者権限を必要とする管理アプリケーションを起動するなど) Vista上でCreateProcess()を使用してUACダイアログを起動することはできません(有効であると仮定して)。ただし、ShellExecute()を使用すると、UACダイアログが表示されます。
アプリケーションがWindows GUIアプリケーションの場合、アプリケーションのメッセージが処理されないため、待機するために以下のコードを使用するのは理想的ではありません。ユーザーには、アプリケーションがハングしたように見えます。
WaitForSingleObject(&processInfo.hProcess, INFINITE)
それがWindowsメッセージキューを処理し続けると、アプリケーションが応答残るよう、以下のテストされていないコードが良いかもしれないような何か:
//-- wait for the process to finish
while (true)
{
//-- see if the task has terminated
DWORD dwExitCode = WaitForSingleObject(ProcessInfo.hProcess, 0);
if ( (dwExitCode == WAIT_FAILED )
|| (dwExitCode == WAIT_OBJECT_0)
|| (dwExitCode == WAIT_ABANDONED))
{
DWORD dwExitCode;
//-- get the process exit code
GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);
//-- the task has ended so close the handle
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
//-- save the exit code
lExitCode = dwExitCode;
return;
}
else
{
//-- see if there are any message that need to be processed
while (PeekMessage(&message.msg, 0, 0, 0, PM_NOREMOVE))
{
if (message.msg.message == WM_QUIT)
{
return;
}
//-- process the message queue
if (GetMessage(&message.msg, 0, 0, 0))
{
//-- process the message
TranslateMessage(&pMessage->msg);
DispatchMessage(&pMessage->msg);
}
}
}
}
ベア心の中でWaitForSingleObject
缶を使用していることこのシナリオであなたを困らせます。以下は、私のウェブサイトのヒントから抜粋したものです。
問題は、アプリケーションにウィンドウがありますが、メッセージをポンピングしていないために発生します。スポーンされたアプリケーションがブロードキャストターゲット(HWND_BROADCASTまたはHWND_TOPMOST)のいずれかを使用してSendMessageを呼び出すと、SendMessageはすべてのアプリケーションがメッセージを処理するまで新しいアプリケーションに戻りませんが、アプリケーションはメッセージを処理できませんメッセージをポンピングしていないので....新しいアプリがロックするので、あなたの待ち時間は決して成功しません....デッドロック。あなたが生成されたアプリケーションの上に絶対的なコントロールを持っている場合は
、そのようなSendMessageTimeoutではなく、SendMessage関数を使用するなど、あなたが取ることができる措置が存在する(例えば、DDEのイニシエーションのために、誰もがまだいることを使用している場合)。しかし、たとえばSetSysColors APIを使用するなど、コントロールを持たない暗黙的なSendMessageブロードキャストを引き起こす状況があります。このラウンド
唯一の安全な方法があります。
MsgWaitForMultipleObjects
APIを使用してください。これは、Windows 10で動作する新しい例です.Windows 10 SDKを使用する場合は、代わりにCreateProcessWを使用する必要があります。この例はコメントされており、うまくいけば自明です。
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <cstdlib>
#include <string>
#include <algorithm>
class process
{
public:
static PROCESS_INFORMATION launchProcess(std::string app, std::string arg)
{
// Prepare handles.
STARTUPINFO si;
PROCESS_INFORMATION pi; // The function returns this
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
//Prepare CreateProcess args
std::wstring app_w(app.length(), L' '); // Make room for characters
std::copy(app.begin(), app.end(), app_w.begin()); // Copy string to wstring.
std::wstring arg_w(arg.length(), L' '); // Make room for characters
std::copy(arg.begin(), arg.end(), arg_w.begin()); // Copy string to wstring.
std::wstring input = app_w + L" " + arg_w;
wchar_t* arg_concat = const_cast<wchar_t*>(input.c_str());
const wchar_t* app_const = app_w.c_str();
// Start the child process.
if(!CreateProcessW(
app_const, // app path
arg_concat, // Command line (needs to include app path as first argument. args seperated by whitepace)
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
throw std::exception("Could not create child process");
}
else
{
std::cout << "[ ] Successfully launched child process" << std::endl;
}
// Return process handle
return pi;
}
static bool checkIfProcessIsActive(PROCESS_INFORMATION pi)
{
// Check if handle is closed
if (pi.hProcess == NULL)
{
printf("Process handle is closed or invalid (%d).\n");
return FALSE;
}
// If handle open, check if process is active
DWORD lpExitCode = 0;
if(GetExitCodeProcess(pi.hProcess, &lpExitCode) == 0)
{
printf("Cannot return exit code (%d).\n", GetLastError());
throw std::exception("Cannot return exit code");
}
else
{
if (lpExitCode == STILL_ACTIVE)
{
return TRUE;
}
else
{
return FALSE;
}
}
}
static bool stopProcess(PROCESS_INFORMATION &pi)
{
// Check if handle is invalid or has allready been closed
if (pi.hProcess == NULL)
{
printf("Process handle invalid. Possibly allready been closed (%d).\n");
return 0;
}
// Terminate Process
if(!TerminateProcess(pi.hProcess,1))
{
printf("ExitProcess failed (%d).\n", GetLastError());
return 0;
}
// Wait until child process exits.
if(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED)
{
printf("Wait for exit process failed(%d).\n", GetLastError());
return 0;
}
// Close process and thread handles.
if(!CloseHandle(pi.hProcess))
{
printf("Cannot close process handle(%d).\n", GetLastError());
return 0;
}
else
{
pi.hProcess = NULL;
}
if(!CloseHandle(pi.hThread))
{
printf("Cannot close thread handle (%d).\n", GetLastError());
return 0;
}
else
{
pi.hProcess = NULL;
}
return 1;
}
};//class process
#endif //win32
のWaitForSingleObjectラインは(INFINITE processInfo.hProcess、)のWaitForSingleObject( '&' なし)::あるべき – wimh
なぜ使用:: WaitForSingleObject関数ではなく、他のAPI呼び出しにグローバル名前空間を指定するために? –
それは習慣の力になります –