Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 是否可以只按名称管理作业对象,而不保留打开的句柄?_C_Windows_Process_Handle_Jobs - Fatal编程技术网

C 是否可以只按名称管理作业对象,而不保留打开的句柄?

C 是否可以只按名称管理作业对象,而不保留打开的句柄?,c,windows,process,handle,jobs,C,Windows,Process,Handle,Jobs,使用流程,我可以执行以下操作: int pid; ::CreateProcess(NULL, cmd, ..., &pi); pid = pi.dwProcessId; ::CloseHandle(pi.hProcess); // then later... HANDLE proc = ::OpenProcess(PROCESS_TERMINATE, FALSE, pid); ::TerminateProcess(proc, 1); ::CloseHandle(proc); 以这种方式

使用流程,我可以执行以下操作:

int pid;
::CreateProcess(NULL, cmd, ..., &pi);
pid = pi.dwProcessId;
::CloseHandle(pi.hProcess);
// then later...
HANDLE proc = ::OpenProcess(PROCESS_TERMINATE, FALSE, pid);
::TerminateProcess(proc, 1);
::CloseHandle(proc);
以这种方式,我只能通过pid来管理windows进程,这对于多平台代码来说很好

我想将此模式扩展到作业对象:

HANDLE job = ::CreateJobObject(NULL, name);
::AssignProcessToJobObject(job, proc); // proc from above
::CloseHandle(job);
// then later...
job = ::OpenJobObject(JOB_OBJECT_TERMINATE, FALSE, name);
::TerminateJobObject(job, 1);
说清楚点,我不在这份工作中,但我的孩子在这个过程中。“当作业的最后一个句柄已关闭且所有相关进程已退出时,作业将被销毁”。在本例中,我的主进程已关闭其最后一个句柄,但子进程仍在运行,并且仍有一个句柄。调用
IsProcessInJob(proc、NULL和isit)
确认作业仍然存在。但是,我打开作业的调用返回NULL,错误代码为error\u FILE\u NOT\u FOUND


所以问题是:我的主进程在关闭作业后是否有办法获得该作业的句柄?

NT对象管理器就是这样工作的。几乎所有对象都是“临时的”,这意味着当不再存在对它们的引用(内核模式指针引用或句柄)时,它们将被删除。您应该能够通过对作业对象调用
NtMakePermanentObject
来更改此行为。不过,我以前从未尝试过这种方法。

NT对象管理器就是这样工作的。几乎所有对象都是“临时的”,这意味着当不再存在对它们的引用(内核模式指针引用或句柄)时,它们将被删除。您应该能够通过对作业对象调用
NtMakePermanentObject
来更改此行为。不过,我以前从未尝试过这种方法。

是的,这是可能的。但是,请注意:

// This example will fail to reopen and terminate the job.
// Processes cmd and ping stay running
STARTUPINFO si;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));

// BEGIN BLOCK A
::CreateProcess(NULL, "cmd /c ping 127.0.0.1 -n 10 > nul",
    NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ".", &si, &pi);
HANDLE job = ::CeateJobObject(NULL, "myjob");
::AssignProcessToJobObject(job, pi.hProcess);
// END BLOCK A

::ResumeThread(pi.hThread);
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
::CloseHandle(job);
HANDLE reopenJob = ::OpenJobObject(JOB_OBJECT_TERMINATE, FALSE, "myjob");
if(reopenJob != NULL)
    ::TerminateJobObject(reopenJob, 1);
在这种情况下,重新打开的作业为NULL,错误代码为error\u FILE\u NOT\u FOUND

作业必须在流程之前创建,并且必须继承,才能重新打开作业

// NEW BLOCK A
HANDLE job = ::CreateJobObject(NULL, "myjob");
::SetHandleInformation(job, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
::CreateProcess(NULL, "cmd /c ping 127.0.0.1 -n 10 > nul",
    NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ".", &si, &pi);
::AssignProcessToJobObject(job, pi.hProcess);

如果您的目标是使用PID命名作业,请注意,此创建顺序阻止这种约定。这仍然意味着,为了重新打开作业,除PID外,还必须跟踪某些信息。

是的,这是可能的。但是,请注意:

// This example will fail to reopen and terminate the job.
// Processes cmd and ping stay running
STARTUPINFO si;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(PROCESS_INFORMATION));

// BEGIN BLOCK A
::CreateProcess(NULL, "cmd /c ping 127.0.0.1 -n 10 > nul",
    NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ".", &si, &pi);
HANDLE job = ::CeateJobObject(NULL, "myjob");
::AssignProcessToJobObject(job, pi.hProcess);
// END BLOCK A

::ResumeThread(pi.hThread);
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
::CloseHandle(job);
HANDLE reopenJob = ::OpenJobObject(JOB_OBJECT_TERMINATE, FALSE, "myjob");
if(reopenJob != NULL)
    ::TerminateJobObject(reopenJob, 1);
在这种情况下,重新打开的作业为NULL,错误代码为error\u FILE\u NOT\u FOUND

作业必须在流程之前创建,并且必须继承,才能重新打开作业

// NEW BLOCK A
HANDLE job = ::CreateJobObject(NULL, "myjob");
::SetHandleInformation(job, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
::CreateProcess(NULL, "cmd /c ping 127.0.0.1 -n 10 > nul",
    NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ".", &si, &pi);
::AssignProcessToJobObject(job, pi.hProcess);

如果您的目标是使用PID命名作业,请注意,此创建顺序阻止这种约定。这仍然意味着,除了PID之外,还必须跟踪一些信息,以便重新打开作业。

这是一个很好的答案,尽管它不能满足我的需要。如果我需要管理JobObject句柄或NT内核对象来帮助windows自动清理,那么我只需要控制句柄。@RyanCalhoun:哦,对不起,我误解了你的问题。您是说作业对象仍然存在,但无法按名称打开它?我不确定作业是否仍然存在。IsProcessInJob调用表明确实如此。OpenJobObject绝对不允许我按名称打开它。MSDN文档似乎无法确定作业的最后一个句柄的确切构成,例如,子进程在添加到作业后是否以某种方式具有作业句柄。@RyanCalhoun:您可以使用process Hacker、process Explorer或WinObj来检查作业对象是否存在。双击流程并单击作业选项卡。使用
NtMakePermanentObject
对我有效,允许我在关闭所有句柄后按名称重新打开作业。但是请注意,要使此功能正常工作,您需要激活
SeCreatePermanentPrivilege
。这是一个很好的答案,尽管它不能满足我的需要。如果我需要管理JobObject句柄或NT内核对象来帮助windows自动清理,那么我只需要控制句柄。@RyanCalhoun:哦,对不起,我误解了你的问题。您是说作业对象仍然存在,但无法按名称打开它?我不确定作业是否仍然存在。IsProcessInJob调用表明确实如此。OpenJobObject绝对不允许我按名称打开它。MSDN文档似乎无法确定作业的最后一个句柄的确切构成,例如,子进程在添加到作业后是否以某种方式具有作业句柄。@RyanCalhoun:您可以使用process Hacker、process Explorer或WinObj来检查作业对象是否存在。双击流程并单击作业选项卡。使用
NtMakePermanentObject
对我有效,允许我在关闭所有句柄后按名称重新打开作业。但是请注意,要使此功能正常工作,您需要激活
SeCreatePermanentPrivilege
。您应该能够按名称重新打开作业对象。你能提供一个完整的自足的示例程序来演示你的问题吗?@HarryJohnston,你的评论促使我在整理我的小示例时尝试了一些新的排列方式。在正确的情况下,您是正确的,我可以重新打开作业句柄。您应该可以按名称重新打开作业对象。你能提供一个完整的自足的示例程序来演示你的问题吗?@HarryJohnston,你的评论促使我在整理我的小示例时尝试了一些新的排列方式。您是正确的,在正确的情况下,我可以重新打开作业句柄。如果要使用PID命名作业,请使用DuplicateHandle显式为子进程提供句柄的副本,而不是让它继承副本。如果要使用PID命名作业,使用DuplicateHandle显式地为子进程提供句柄的副本,而不是让它继承副本。