windows - 如何杀死进程窗口的所有递归子级

标签 windows api recursion process pid

我有一个问题,但没有解决方案。

我的程序运行并创建了一些进程,但进程继续创建另一个进程。 我不知道如何让所有的 child 都杀光。

我使用 CreateToolhelp32Snapshot 函数获取所有父级为我的程序(主线程)的子级......并继续从主线程的每个子级获取所有子级。

hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );

如果我使用这个解决方案,性能会很低,因为我在第一次就有了所有进程的PID,所以我不需要再次调用CreateToolhelp32Snapshot

我可以采取哪种最佳解决方案来获取进程窗口的所有递归子项?

最佳答案

首先,看一下 Win32 Job API .一项功能是能够自动终止属于同一作业的所有进程。查看TerminateJobObject API。

编辑:Chen 先生刚刚在博文中谈到了那个确切的主题。 Destroying all child processes (and grandchildren) when the parent exits

那么,你的问题。您可以构建所有当前正在运行的进程的 std::map,键是 PID,值是子进程的 std::vector。然后您可以在 map 上递归以终止进程及其所有子进程。

// 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;

}

如果你想测试上面的程序,这里有一个小的进程树生成器

// 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;

}

关于windows - 如何杀死进程窗口的所有递归子级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20469327/

相关文章:

c++ - 用 C++ 编码时,你能在 visual studio 中删除 stdafx.h 吗?

windows - 如何修复 "The _imaging C module is not installed"Django/WSGI/Apache

api - 如何将切片器值设置为Power BI中第一个可用值表单表?

android - BluetoothLeScanner.startScan() 在 Marshmallow 中需要新权限?

ios - 为什么“ self ”无法识别?

Ruby:检查Windows远程主机中是否安装了程序

node.js - Windows powershell 中的 NODE_ENV 返回未定义

javascript - 错误: origin_mismatch when using Google calendar API with port 444

c++ - C++:用另一个字母递归地替换一个字母中所有字母的实例

python - 如何将 for 循环转换为递归方法?