यहां एक तकनीक है कि, अचूक नहीं होने पर, उपयोगी हो सकता है अगर किसी कारण से आप नौकरी ऑब्जेक्ट का उपयोग नहीं कर सकते हैं। विचार एक अज्ञात पाइप बनाना है और बच्चे को प्रक्रिया को पाइप के लिखने के अंत में हैंडल का उत्तराधिकारी होना है।
आम तौर पर, पोते की प्रक्रियाओं को पाइप के लिखने के अंत का भी वारिस होगा। विशेष रूप से, cmd.exe
(उदा।, बैच फ़ाइल से) द्वारा लॉन्च की गई प्रक्रियाएं हैंडल का उत्तराधिकारी होंगी।
एक बार बाल प्रक्रिया समाप्त हो जाने के बाद, मूल प्रक्रिया पाइप के लिखने के अंत में अपने हैंडल को बंद कर देती है, और फिर पाइप से पढ़ने का प्रयास करती है। चूंकि कोई भी पाइप को नहीं लिख रहा है, इसलिए पढ़ना ऑपरेशन अनिश्चित काल तक अवरुद्ध होगा। (निश्चित रूप से आप धागे या एसिंक्रोनस I/O का उपयोग कर सकते हैं यदि आप पोते के लिए इंतज़ार करते समय सामान करना जारी रखना चाहते हैं।)
जब (और केवल जब) पाइप के लिखने के अंत में अंतिम संभाल बंद हो जाता है, तो पाइप का अंत लिखना स्वचालित रूप से नष्ट हो जाता है। यह पाइप को तोड़ता है और पढ़ा गया ऑपरेशन पूरा करता है और एक ERROR_BROKEN_PIPE विफलता की रिपोर्ट करता है।
मैं कई वर्षों से उत्पादन में इस कोड (और उसी कोड के पुराने संस्करण) का उपयोग कर रहा हूं।
// pwatch.c
//
// Written in 2011 by Harry Johnston, University of Waikato, New Zealand.
// This code has been placed in the public domain. It may be freely
// used, modified, and distributed. However it is provided with no
// warranty, either express or implied.
//
// Launches a process with an inherited pipe handle,
// and doesn't exit until (a) the process has exited
// and (b) all instances of the pipe handle have been closed.
//
// This effectively waits for any child processes to exit,
// PROVIDED the child processes were created with handle
// inheritance enabled. This is usually but not always
// true.
//
// In particular if you launch a command shell (cmd.exe)
// any commands launched from that command shell will be
// waited on.
#include <windows.h>
#include <stdio.h>
void error(const wchar_t * message, DWORD err) {
wchar_t msg[512];
swprintf_s(msg, sizeof(msg)/sizeof(*msg), message, err);
printf("pwatch: %ws\n", msg);
MessageBox(NULL, msg, L"Error in pwatch utility", MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
ExitProcess(err);
}
int main(int argc, char ** argv) {
LPWSTR lpCmdLine = GetCommandLine();
wchar_t ch;
DWORD dw, returncode;
HANDLE piperead, pipewrite;
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sa;
char buffer[1];
while (ch = *(lpCmdLine++)) {
if (ch == '"') while (ch = *(lpCmdLine++)) if (ch == '"') break;
if (ch == ' ') break;
}
while (*lpCmdLine == ' ') lpCmdLine++;
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
if (!CreatePipe(&piperead, &pipewrite, &sa, 1)) error(L"Unable to create pipes: %u", GetLastError());
GetStartupInfo(&si);
if (!CreateProcess(NULL, lpCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
error(L"Error %u creating process.", GetLastError());
if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) error(L"Error %u waiting for process.", GetLastError());
if (!GetExitCodeProcess(pi.hProcess, &returncode)) error(L"Error %u getting exit code.", GetLastError());
CloseHandle(pipewrite);
if (ReadFile(piperead, buffer, 1, &dw, NULL)) {
error(L"Unexpected data received from pipe; bug in application being watched?", ERROR_INVALID_HANDLE);
}
dw = GetLastError();
if (dw != ERROR_BROKEN_PIPE) error(L"Unexpected error %u reading from pipe.", dw);
return returncode;
}
धन्यवाद। ऐसा लगता है कि एक सरल WaitForSingleObject मुझे तब नहीं बताएगा जब सभी प्रक्रियाएं निकलती हैं, लेकिन ऐसा लगता है कि मैं एक आईओ पूरा करने वाला पोर्ट बना सकता हूं और JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO के लिए प्रतीक्षा कर सकता हूं। – thudbang
रेमंड चेन ने अपने ब्लॉग में शामिल किया: [मैं नौकरी में सभी प्रक्रियाओं से बाहर निकलने तक कैसे प्रतीक्षा करूं?] (Https://blogs.msdn.microsoft.com/oldnewthing/20130405-00/?p=4743) –