我是 C 新手,正在使用 Win32 API 创建一个带有
CreateProcessW()
的进程。这是我的第一个C 程序。它打开 notepad.exe
并使用 dwProcessId
输出进程 ID。但输出的PID始终与我在任务管理器中看到的打开notepad.exe
进程的PID不同。这是为什么?
C代码:
#include <stdio.h>
#include <windows.h>
int main (void){
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
if (!CreateProcessW(
L"C:\\Windows\\System32\\notepad.exe",
NULL, // Command line arguments
NULL, // Process security attributes
NULL, // Thread security attributes
FALSE, // Handle inheritance
0, // Creation flags
NULL, // Environment block
NULL, // Current directory
&si, // Startup information
&pi)) // Process information
{
printf("(-) failed to create process, error: %ld\n", GetLastError());
return EXIT_FAILURE;
}
// Print PID
printf("Process ID: %lu\n", pi.dwProcessId);
Sleep(9000); // Wait for 5 seconds
// Close process and thread handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return EXIT_SUCCESS;
}
例如,运行时控制台输出为“进程ID:35692”,但在任务管理器中搜索记事本时,显示的PID为20736。
我做错了什么?
您观察到的问题可能是由于 Windows 中的以下行为造成的:
理解进程和父进程关系:
当您调用 CreateProcessW 启动 notepad.exe 时,Windows 可能会启动 初始“存根”或“启动器”进程。这个过程可以创建 子进程(如实际的记事本窗口),有时 主记事本窗口本身将出现在不同的进程 ID 下 在任务管理器中。
子进程创建:Windows 在创建 notepad.exe 期间可能会启动多个进程。您看到的 pi.dwProcessId 是 对于由CreateProcessW直接创建的进程。然而, 记事本可能会分叉成多个进程,您在其中看到的那个进程 任务管理器可能是一个不同的子进程,特别是在 现代版本的 Windows 中的进程可以产生额外的 工作进程或 UI 进程。
处理方法:
检查子进程:现代应用程序,包括记事本、 启动后可能会产生额外的子进程。这 CreateProcessW返回的进程ID指的是父进程, 不一定是与主窗口或 UI 关联的窗口。
调查工具:您可以使用 Process Explorer 等工具(来自 Sysinternals)来观察进程树。流程资源管理器将 显示父进程和子进程。你应该能够 将 notepad.exe 视为返回的 PID 的子进程 创建进程W。
解决方法: 如果您需要任务管理器中显示的记事本窗口的实际进程 ID,您可以在创建记事本窗口后使用窗口句柄检索它:
以下是对代码的示例修改,用于检索与记事本窗口关联的实际进程 ID:
#include <stdio.h>
#include <windows.h>
int main(void) {
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
// Create the Notepad process
if (!CreateProcessW(
L"C:\\Windows\\System32\\notepad.exe",
NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
printf("(-) failed to create process, error: %ld\n", GetLastError());
return EXIT_FAILURE;
}
// Print the process ID of the created process
printf("Created Process ID: %lu\n", pi.dwProcessId);
// Wait a little to let the window appear
Sleep(2000);
// Find the Notepad window (class name "Notepad", or try NULL for any window)
HWND hwnd = FindWindowW(L"Notepad", NULL);
if (hwnd == NULL) {
printf("(-) failed to find Notepad window, error: %ld\n", GetLastError());
} else {
// Get the process ID associated with the window
DWORD windowProcessId;
GetWindowThreadProcessId(hwnd, &windowProcessId);
printf("Process ID of Notepad window: %lu\n", windowProcessId);
}
// Wait a bit more
Sleep(9000);
// Close process and thread handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return EXIT_SUCCESS;
}
说明:
此方法可确保您获得在任务管理器中看到的实际记事本窗口的 PID,而不仅仅是 CreateProcessW 创建的初始进程。
总结: CreateProcessW返回的进程ID是正确的,但它指的是启动记事本的进程。实际的记事本窗口可能与子进程相关联。 要获取您在任务管理器中看到的窗口的 PID,您可以使用 FindWindow 和 GetWindowThreadProcessId 来检索窗口的进程 ID。