windows - Jeg ønsker at få PID af hver proces, jeg har oprettet i C ++ og opsige hver efter en bestemt tid

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg er ny i C ++ og Windows Api. Hvad jeg har lige nu, er, at jeg kun kan udskrive PID i den første proces i applikationen. Hvis jeg vil lave en 4-proces, vil jeg få deres PID'er det i konsollen og afslutte hver enkelt af dem efter bestemte tidspunkter (ved brug af chrono).


Eksempeloversigt:

  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.


Her er min kode hidtil.


#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 << "
" <<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;
}


Enhver ide om, hvordan jeg kan få alle PID'er i samme applikation til at køre og afslutte det samtidigt?

Bedste reference


Som PROCESS\_INFORMATION pif indeholder id for den nyoprettede proces i DWORD dwProcessId, kan du for eksempel oprette din egen liste ved at tilføje hver pif.dwProcessId til en std::vector<DWORD> processIds.


Og for at afslutte de oprettede processer, gør bare noget


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





Rediger:


Jeg tror, ​​jeg har lige forstået en forbedring ved hjælp af std::remove\_if fra #include <algorithm> og std::bind fra #include <functional>.


I stedet for for(auto processId : processIds){...} brug dette:


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


Med std::remove\_if kan du slette elementer fra en container, hvis en passeret funktion (i dette tilfælde TerminateMyProcess), der tager som et argument et element fra beholderen, returnerer sandt.


Som TerminateMyProcess har tydeligvis to argumenter, DWORD og UINT, kan vi bruge std :: bind som en wrapperfunktion omkring TerminateMyProcess, der tager et DWORD argument placeholders :: \_ 1) mens UINT er sat til at være 1.


På denne måde vil succesfuldt afviklede processIds blive fjernet fra vektoren, idet kun processIds forlades, der ikke kunne opsiges.





En anden redigering, der afspejler IInspctables kommentar:


Når din ansøgning har oprettet alle disse processer (notepad.exe i dit eksempel), har hver af dem en bestemt procesId. Forestil dig, for eksempel, mens din ansøgning venter på tidspunktet for at afslutte disse processer, bliver en af ​​dem allerede afsluttet. Processens id er nu ikke længere i brug og kan tildeles af operativsystemet til en ny og helt anden proces, der ikke har noget at gøre med din ansøgning eller notepad.exe. Normalt vil du ikke opsige nogen som helst behandle. ;)


Opret en std::vector<HANDLE> processes.

Gem hver pif.hProcess i denne vektor for hver oprettet proces. Luk ikke håndtaget på dette tidspunkt.
Ændre TerminateMyProcess at det tager en HANDLE som det første argument.

Brug


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


at afslutte processer og (hvis den er afsluttet med succes) fjerne deres håndtag fra vektoren. De resterende håndtag kan bruges til fejlhåndtering mv.





Eksempel på arbejde:


#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;
}