我有一个问题,但没有解决方案。
我的程序运行并创建一些进程,但进程继续创建另一个进程。 我不知道如何让所有的孩子全部杀死。
我使用CreateToolhelp32Snapshot
函数来获取父节点是我的程序(mainthread)的所有子节点......并继续从每个mainthread子节点获取所有子节点。
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
如果我使用此解决方案,性能非常低,因为我第一次拥有所有进程的PID,因此我无需再次调用CreateToolhelp32Snapshot
我可以采用哪种最佳解决方案来获取进程窗口的所有递归子级?
答案 0 :(得分:2)
首先,看看Win32 Job API。一个功能是能够自动终止属于同一作业的所有进程。请参阅TerminateJobObject API。
编辑:陈先生刚刚在博客上写了一篇精确的主题。 Destroying all child processes (and grandchildren) when the parent exits然后,你的问题。您可以构建所有当前正在运行的进程的std :: map,键是PID,值是子进程的std :: vector。然后,您可以在地图上递归以终止进程及其所有子进程。
// KillChildren.cpp
// Usage: pass a PID a argument
#include <Windows.h>
#include <TlHelp32.h>
#include <vector>
#include <map>
typedef std::vector<DWORD> VEC_CHILDS;
typedef VEC_CHILDS::iterator IT_CHILDS;
typedef std::map<DWORD, VEC_CHILDS> MAP_PIDS;
typedef MAP_PIDS::iterator IT_PIDS;
void KillProcess( DWORD dwPID ) {
HANDLE hProcess = OpenProcess( PROCESS_TERMINATE | SYNCHRONIZE, FALSE, dwPID );
if ( hProcess == NULL ) {
printf( "Cant't OpenProcess for PID %u, Reason %u\n", dwPID, GetLastError() );
return;
}
BOOL bWin32Success = TerminateProcess( hProcess, 0 );
if ( bWin32Success == 0 ) {
printf( "Cant't TerminateProcess for PID %u, Reason %u\n",
dwPID, GetLastError() );
} else {
DWORD dwRetVal = WaitForSingleObject( hProcess, 2000 );
if ( dwRetVal != WAIT_OBJECT_0 ) {
printf( "Failed to Wait for Process Termination for PID %u,"
"RetVal %u Reason %u\n", dwPID, dwRetVal, GetLastError() );
} else {
printf( "Process %u Terminated\n", dwPID );
}
}
CloseHandle( hProcess );
}
void KillChilds( DWORD dwParentPID, MAP_PIDS & mPids ) {
IT_PIDS it = mPids.find( dwParentPID );
if ( it == mPids.end() ) return;
VEC_CHILDS & vChilds = it->second;
for ( IT_CHILDS itChild = vChilds.begin(); itChild != vChilds.end(); ++itChild ) {
KillChilds( *itChild, mPids );
}
KillProcess( dwParentPID );
}
// usage: PID as first arg
int main( int argc, char* argv[] ) {
if ( argc <= 1 ) return -1;
DWORD dwPID = atoi( argv[ 1 ] );
HANDLE hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if ( hProcessSnap == INVALID_HANDLE_VALUE ) return -1;
// build PID list with children
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) ) {
CloseHandle( hProcessSnap );
return -1;
}
MAP_PIDS mPids;
do {
// Add as a Parent, with no child, yet, if not already done
IT_PIDS it = mPids.find( pe32.th32ProcessID );
if ( it == mPids.end() ) mPids[ pe32.th32ProcessID ] = VEC_CHILDS();
// Process the Parent
it = mPids.find( pe32.th32ParentProcessID );
if ( it == mPids.end() ) {
// unknown parent, add it with one child
VEC_CHILDS vChilds;
vChilds.push_back( pe32.th32ProcessID );
mPids[ pe32.th32ParentProcessID ] = vChilds;
} else {
// Parent already here, add one more child
it->second.push_back( pe32.th32ProcessID );
}
} while ( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
KillChilds( dwPID, mPids );
return 0;
}
如果你想测试上面的程序,这里有一个小的Process Tree生成器
// CreateChildren.cpp
// beware, messing may be 'fork bombing'
#include <Windows.h>
int main( int argc, char* argv[] ) {
srand( GetTickCount() );
// always childs if args
if ( argc == 0 ) {
int iRandom = rand();
if ( iRandom % 3 ) Sleep( INFINITE );
}
char szFullExeName[ MAX_PATH ];
DWORD dwCopied = GetModuleFileName( NULL, szFullExeName, sizeof( szFullExeName ) );
if ( dwCopied == 0 ) return -1;
STARTUPINFO si;
memset( &si, 0, sizeof( si ) );
si.cb = sizeof( si );
PROCESS_INFORMATION pi;
int ChildCount = rand() % 3;
while ( ChildCount-- ) {
BOOL bWin32Success = CreateProcess( szFullExeName, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
if ( bWin32Success ) {
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
}
Sleep( INFINITE );
return 0;
}