كيف يمكنني الاتصال ::CreateProcess في c++ لإطلاق ويندوز للتنفيذ ؟
سؤال
أبحث عن مثال على ذلك:
- تطلق EXE
- ينتظر EXE إلى النهاية.
- صحيح يغلق جميع مقابض عندما قابل للتنفيذ التشطيبات.
المحلول
شيء من هذا القبيل:
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(مقابل.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 );
}
إذا كنت تطبيق ويندوز واجهة المستخدم الرسومية تطبيق ثم استخدام رمز أدناه للقيام الانتظار ليست مثالية كما الرسائل على التطبيق الخاص بك لن يكون الحصول على المعالجة.أن المستخدم سوف تبدو مثل التطبيق الخاص بك قد علقت.
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);
}
}
}
}
إذا كان الخاص بك exe يحدث أن تكون وحدة التحكم التطبيق, كنت قد تكون مهتمة في قراءة المعياري و stderr -- لذلك سوف بتواضع أحيلكم إلى هذا المثال:
http://support.microsoft.com/default.aspx?scid=kb EN-US;q190351
انها قليلا من الفم من التعليمات البرمجية ، ولكن لقد استخدمت نماذج من هذا القانون أن تفرخ و قراءة.
على شبه المتعلقة ملاحظة إذا كنت تريد أن تبدأ عملية المزيد من الامتيازات من العملية الحالية (أقول إطلاق التطبيق المشرف الذي يتطلب حقوق المسؤول ، من التطبيق الرئيسي تشغيل كمستخدم عادي), لا يمكنك القيام بذلك باستخدام CreateProcess() على ويندوز فيستا لأنه لن يؤدي الحوار UAC (على افتراض أنه هو تمكين).UAC الحوار يتم تشغيلها عند استخدام ShellExecute () ، على الرغم من.
ولعل هذا هو الأكثر كاملة ؟ http://goffconcepts.com/techarticles/development/cpp/createprocess.html
نضع في اعتبارنا أن استخدام WaitForSingleObject
يمكن أن تحصل في ورطة في هذا السيناريو.التالي هو مقصوص من طرف على موقع الويب الخاص بي:
المشكلة تنشأ بسبب التطبيق الخاص بك لديه نافذة ولكن ليس ضخ الرسائل.إذا ولدت تطبيق استدعاء SendMessage مع واحد من بث الأهداف (HWND_BROADCAST أو HWND_TOPMOST) ، ثم SendMessage لن يعود إلى التطبيق الجديد حتى جميع التطبيقات التعامل مع الرسالة ولكن التطبيق الخاص بك لا يمكن التعامل مع الرسالة لأنه ليس ضخ الرسائل....وبالتالي فإن التطبيق الجديد الأقفال حتى الانتظار لم ينجح....الجمود.
إذا كان لديك السيطرة المطلقة على ولدت التطبيق ، ثم هناك تدابير يمكن اتخاذها ، مثل استخدام SendMessageTimeout بدلا من SendMessage (مثلا ، بالنسبة DDE التلقين ، إذا كان أي شخص لا يزال يستخدم هذا).ولكن هناك الحالات التي تسبب الضمني SendMessage تبث أكثر من التي لديك أي سيطرة ، مثل استخدام SetSysColors API على سبيل المثال.
فقط طرق آمنة هذه الجولة هي:
- انشقت الانتظار في موضوع مستقل ، أو
- استخدام مهلة على الانتظار واستخدام مباشر في الانتظار حلقة لضمان ضخ الرسائل ، أو
- استخدام
MsgWaitForMultipleObjects
API.
هنا هو مثال جديد يعمل على نظام التشغيل ويندوز 10.عند استخدام windows10 sdk لديك لاستخدام CreateProcessW بدلا من ذلك.هذا المثال هو علق ونأمل النفس التفسيرية.
#ifdef _WIN32
#include <Windows.h>
#include <iostream>
#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", GetLastError());
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