Я хочу получить PID каждого процесса, который я создал в C ++, и завершить каждый после определенного времени - PullRequest
0 голосов
/ 07 мая 2018

Я новичок в C ++ и Windows API. Сейчас у меня есть то, что я могу распечатать только PID первого процесса приложения. Если я создам, скажем, 4 процесса, я хочу получить их PID; распечатайте его в консоли и завершите каждый из них через определенное время (используя хронограф).

Пример обзора:
1. for process=1 until process=5
2. Call notepad.exe
3. Get the current PID of this process and print in the console.
4. Perform some execution from this processID
5. increment process
6. Whoever successfully executed, terminate the PID.

Вот мой код.

#include <iostream>
#include <string>
#include <tchar.h>
#include <process.h>
#include <windows.h>
#include <tlhelp32.h>
#include <stdlib.h>

using namespace std;

//  Forward declarations:
BOOL GetProcessList();
BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode);


int main(void)
{

// Gives info on the thread and process for the new process
PROCESS_INFORMATION pif;

// Defines how to start the program
STARTUPINFO si;

// Zero the STARTUPINFO struct
ZeroMemory(&si, sizeof(si));

// Must set size of structure
si.cb = sizeof(si);

for (int i = 0; i < 3; i++) {

    BOOL bRet = CreateProcess(L"C:\\Users\\notepad.exe", // Path to executable file
        NULL,   // Command string - not needed here
        NULL,   // Process handle not inherited
        NULL,   // Thread handle not inherited
        FALSE,  // No inheritance of handles
        0,      // No special flags
        NULL,   // Same environment block as this prog
        NULL,   // Current directory - no separate path
        &si,    // Pointer to STARTUPINFO
        &pif); // Pointer to PROCESS_INFORMATION

    if (FALSE == bRet)
    {
        MessageBox(HWND_DESKTOP, L"Unable to start program", L"", MB_OK);
        return EXIT_FAILURE;
    }
}

// Close handle to process
CloseHandle(pif.hProcess);

// Close handle to thread
CloseHandle(pif.hThread);

//return EXIT_SUCCESS;
//system("pause");

GetProcessList();
system("pause");
return 0;
}

BOOL GetProcessList()
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;

// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
    return(FALSE);
}

// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);

// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32))
{
    CloseHandle(hProcessSnap);  // clean the snapshot object
    return(FALSE);
}

// Now walk the snapshot of processes 
do
{
    //string str = pe32.szExeFile;
    wchar_t *sample = pe32.szExeFile;
    wstring ws(sample);
    string str(ws.begin(), ws.end());
    //cout << "Haha" << endl;
    if (str == "notepad.exe") // put the name of your process you want to kill
    {
        //print the PID
        cout << "\n" <<pe32.th32ProcessID << endl;
        system("pause");
        TerminateMyProcess(pe32.th32ProcessID, 1);
    }

} while (Process32Next(hProcessSnap, &pe32));

CloseHandle(hProcessSnap);
return(TRUE);
}

BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_TERMINATE;
BOOL  bInheritHandle = FALSE;
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
if (hProcess == NULL)
    return FALSE;

BOOL result = TerminateProcess(hProcess, uExitCode);

CloseHandle(hProcess);

return result;
}

Есть идеи, как я могу получить все PID одного и того же приложения и одновременно завершить его?

1 Ответ

0 голосов
/ 07 мая 2018

Поскольку PROCESS_INFORMATION pif содержит идентификатор недавно созданного процесса в DWORD dwProcessId, вы можете, например, создать свой собственный список, добавив каждый pif.dwProcessId к std::vector<DWORD> processIds.

А чтобы завершить созданные процессы, просто сделайте что-то вроде

for (auto processId : processIds) {
    TerminateMyProcess(processId, 1);
}

Edit:

Я думаю, что только что реализовал улучшение, используя std::remove_if из #include <algorithm> и std::bind из #include <functional>.

Вместо for(auto processId : processIds){...} используйте это:

processIds.erase(std::remove_if(processIds.begin(), processIds.end(), std::bind(TerminateMyProcess, std::placeholders::_1, 1)));

С помощью std::remove_if вы можете удалить элементы из контейнера, если переданная функция (в данном случае TerminateMyProcess), которая принимает в качестве одного аргумента элемент из контейнера, возвращает true.

Поскольку TerminateMyProcess, очевидно, имеет два аргумента, DWORD и UINT, мы можем использовать std :: bind в качестве функции-оболочки вокруг TerminateMyProcess, которая принимает один аргумент DWORD (placeholder :: _ 1), в то время как UINT установлено на 1.

Таким образом, успешно завершенные идентификаторы процессов будут удалены из вектора, оставив только идентификаторы процессов, которые не могут быть завершены.


Еще одно редактирование для отражения Комментарий IInspctable :

После того, как ваше приложение создало все эти процессы (в вашем примере notepad.exe), у каждого из них есть определенный идентификатор процесса. Представьте, например, что пока ваше приложение ожидает время завершения этих процессов, один из них уже завершается. Идентификатор процесса больше не используется и может быть назначен операционной системой новому и совершенно другому процессу, который не имеет никакого отношения к вашему приложению или notepad.exe. Обычно вы не хотите завершать какой-либо процесс. ;)

Создать один std::vector<HANDLE> processes.
Для каждого созданного процесса сохраняйте pif.hProcess в этом векторе. Не закрывайте ручку на этом этапе. Измените TerminateMyProcess на то, что он принимает HANDLE в качестве первого аргумента.
Используйте

processes.erase(std::remove_if(processes.begin(), processes.end(), std::bind(TerminateMyProcess, std::placeholders::_1, 1)));

для завершения процессов и (в случае успешного завершения) удаления их дескрипторов из вектора. Оставшиеся дескрипторы можно использовать для обработки ошибок и т. Д.


Рабочий пример:

#include <Windows.h>
#include <process.h>

#include <vector>
#include <algorithm>
#include <functional>

#include <chrono>
#include <thread>

std::vector<HANDLE> processes;

void create_process() {
    STARTUPINFO si;
    SecureZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);

    PROCESS_INFORMATION pi;
    SecureZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    if (CreateProcess(L"C:\\windows\\system32\\notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        CloseHandle(pi.hThread);
        processes.push_back(pi.hProcess);
    }
}

BOOL terminate_process(HANDLE handle, UINT exitCode) {
    TerminateProcess(handle, exitCode);
    CloseHandle(handle);

    return TRUE;
}

// Alternative (simplified), makes `std::bind` unnecessary:
BOOL alt_terminate_process(HANDLE handle) {
    TerminateProcess(handle, 1);
    CloseHandle(handle);

    return TRUE;
}

int main()
{
    for (int i = 0; i < 3; ++i) {
        create_process();
    }

    std::this_thread::sleep_for(std::chrono::seconds{ 5 });

    // use either
    processes.erase(std::remove_if(processes.begin(), processes.end(), std::bind(terminate_process, std::placeholders::_1, 1)));
    // or
    processes.erase(std::remove_if(processes.begin(), processes.end(), alt_terminate_process));

    return 0;
}
...