我尽可能地减少了代码sscce 这段代码的作用是什么:
CreateProcess
TerminateProcess
从CreateProcess
获取的句柄上使用TerminateProcess
取消记事本。OpenProcess
是异步#include "stdafx.h"
#include <windows.h>
#include "Psapi.h"
#include <TlHelp32.h>
#include <iostream>
#include <cassert>
typedef unsigned long PID;
typedef const std::string& P_PATH;
// Launch an executable given by a path and set a few infomatives stuffs passed as ref parameters
bool launch_process(P_PATH path, STARTUPINFO& info, PROCESS_INFORMATION& processInfo, HANDLE& hProcess, PID& pid)
{
setlocale(LC_ALL, "en_US.utf8");
std::wstring widestr = std::wstring(path.begin(), path.end());
const wchar_t* widecstr = widestr.c_str();
LPTSTR szCmdline = _tcsdup(widecstr);
if (CreateProcess(szCmdline, NULL, NULL, NULL, false, NULL, NULL, NULL, &info, &processInfo))
{
hProcess = processInfo.hProcess;
pid = processInfo.dwProcessId;
return true;
}
return false;
}
int main(int argc, char* argv[])
{
// Setup
// -----
bool OK = false;
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
HANDLE hProcess;
PID pid = 0;
// launch notepad
// --------------
OK = launch_process("C:\\WINDOWS\\System32\\notepad.exe", info, processInfo, hProcess, pid);
assert(OK);
// wait a bit
// ----------
system("PAUSE");
SetLastError(0);
// get Handle on notepad
// ---------------------
hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, false, static_cast<DWORD>(pid));
std::cout << "Error: " << GetLastError() << std::endl;
// Kill notepad
// ------------
UINT exitCode = 0;
DWORD dwWaitResult = 0;
SetLastError(0);
OK = TerminateProcess(hProcess, exitCode);
std::cout << "Error: " << GetLastError() << std::endl;
// ensure everything went well ( we need to wait because TerminateProcess is asynchronous )
if (!OK || (dwWaitResult != WaitForSingleObject(hProcess, INFINITE)))
return -1;
// Cleanup
CloseHandle(hProcess);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
hProcess = nullptr;
processInfo.hProcess = nullptr;
// Ya know what let's reopen the pid I just killed
// ( you can see that notepad was started then killed, you can check the pid does not exist in either the task manager or processExplorer )
SetLastError(0);
hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, false, static_cast<DWORD>(pid));
std::cout << "Error: " << GetLastError() << std::endl;
// Yeah I can speak to the deads!
if (hProcess != nullptr)
{
LPWSTR szProcessName = L"";
GetModuleFileNameEx(hProcess, NULL, szProcessName, sizeof szProcessName);
char c_szText[MAX_PATH];
wcstombs(c_szText, szProcessName, wcslen(szProcessName) + 1);
// But the deads have no names
std::cout << "Error: " << GetLastError() << std::endl;
std::cout << "Zombie Name: " << c_szText << std::endl;
}
return 0;
}
on dead pid 您可以在调试中轻松检查(在OpenProcess之前),在任务管理器或processExplorer中找不到给定的Pid。但是没有其他Windows API函数似乎接受这个Pid
vec4 ArrayTextureBlend(in vec3 texCoord)
{
float frac = fract(texCoord.z);
texCoord.z = floor(texCoord.z);
vec4 top = texture(arrayTex, texCoord);
vec4 bottom = texture(arrayTex, texCoord + vec3(0, 0, 1));
return mix(top, bottom, frac); //Linearly interpolate top and bottom.
}
答案 0 :(得分:9)
它没有出现在任务管理器的进程列表中,因为它已终止。任务管理器不显示僵尸(此行为不同于例如显示僵尸的Linux ps -Af f
)。
它仍然存在并且OpenProcess
可以访问,因为进程对象尚未被破坏,即它处于僵尸状态。这将是因为另一个进程有一个开放的句柄。例如,
道德:
不要指望一旦关闭手柄就会销毁过程对象,因为你的手柄不是唯一的手柄。
僵尸状态对于进程来说是一个完全合法的状态。如果进程终止,所有进程都将处于僵尸状态,有人正在等待用GetExitCodeProcess
读取退出代码,或者对该过程的状态有任何其他兴趣。通常,一旦读取退出代码,对流程的兴趣就会减弱,句柄将被关闭,最后流程将被销毁。
一旦进程被销毁,就可以重用PID。 (相反,在关闭所有句柄之前,不能重复使用PID)。在Windows中,内核更喜欢低编号的PID,并且可以非常快速地重用它们。这种行为不同于Linux,它更喜欢递增PID,并且在达到最大值之前不会重复使用它们。
如果您想要进程的句柄,请不要关闭它。