2009-09-21 2 views
14

구성 파일에서 사용자가 지정한 임의의 다른 프로세스를 호출 할 수 있기를 원하는 응용 프로그램 A가 있습니다.Windows에서 임의의 하위 프로세스를 실행해도 계속 깨끗하게 종료됩니까?

배치 스크립트 B는 사용자가 A로 호출하고자하는 프로세스 중 하나입니다. B는 환경 변수를 설정하고 메시지를 표시하며 컴파일러 C를 ​​호출하여 작업을 수행합니다.

Windows는 임의 프로세스가 정상적으로 종료되도록하는 표준 방법을 제공합니까? A가 콘솔에서 실행되고 CTRL + C를받는다고 가정하십시오. 이것을 B와 C에 전달할 수 있습니까? A가 창에서 실행되고 사용자가 창을 닫으려고하면 B와 C를 취소 할 수 있습니까?

TerminateProcess는 옵션이지만 아주 좋은 것은 아닙니다. A가 B에서 TerminateProcess를 사용하면 C는 계속 실행됩니다. C가 오래 실행되는 경우 문제가 발생할 수 있습니다. C의 첫 번째 인스턴스가 여전히 비밀리에 작동하는 동안 동일한 파일에서 작동하도록 C의 다른 인스턴스를 시작할 수 있기 때문입니다. 또한 TerminateProcess는 깨끗한 종료를 초래하지 않습니다.

GenerateConsoleCtrlEvent는 훌륭하게 들리지만 모든 것이 콘솔에서 실행 중일 때 작동 할 수 있지만 문서에 자신의 콘솔에만 Ctrl + C를 보낼 수 있다고되어 있기 때문에 A가 창에서 실행 중이면 도움이되지 않습니다.

Windows에서 SIGINT와 동일한 기능이 있습니까? 나는이 기사를 찾으려고한다 : http://www.cons.org/cracauer/sigint.html for Windows.

+1

+1 좋은 질문입니다. 웃기는 답변이 없습니다 ... 저는 Win32에서와 비슷한 신호 메커니즘을 알지 못합니다. 자식 프로세스에 통보해야 할 때 GUI 애플리케이션에 WM_CLOSE 메시지를 게시했습니다. 콘솔 응용 프로그램의 경우 입력 및 출력 스트림을 기본 응용 프로그램에 연결하여 만든 응용 프로그램의 경우이를 종료하고 싶을 때 입력 스트림을 닫았습니다. 아이들의 아이들에 관해서는, 나는 그들의 의존성을 정리하기 위해 직접적인 아이들에게 의존했다. :). –

답변

9

나는이 질문에 조금 늦은 것 같지만 어쨌든 같은 문제가있는 사람이라면 무엇인가를 쓸 것이다.

내 응용 프로그램이 GUI 응용 프로그램이 되겠지만 실행 된 프로세스는 대화 형 콘솔 창이 연결되지 않은 상태에서 백그라운드에서 실행되어야한다는 점에서 제 문제점은 비슷합니다.

GenerateConsoleCtrlEvent()를 사용하여이 문제를 해결할 수있었습니다. 까다로운 부분은 정확히 어떻게 문서를 사용할 수 있고 함정에 함몰되어 있는지에 대한 문서가 실제로 명확하지 않다는 점입니다.

내 솔루션은 설명한 내용 (here)을 기반으로합니다. 그러나 그것은 실제로 모든 세부 사항을 설명하지 못했습니다. 그래서 여기에 그것이 작동하도록하는 방법에 대한 세부 사항이 있습니다.

  1. 새로운 도우미 응용 프로그램 "Helper.exe"를 만듭니다. 이 응용 프로그램은 응용 프로그램 (상위)과 닫을 수있게하려는 하위 프로세스 사이에 있습니다. 실제 자식 프로세스도 생성합니다. 이 "중간 사람"프로세스가 있어야합니다 또는 GenerateConsoleCtrlEvent() 실패합니다.

  2. 일부 IPC 메커니즘을 사용하여 부모에서 도우미 프로세스로 통신하여 도우미가 자식 프로세스를 닫아야합니다. 도우미가이 이벤트를 받으면 자체 및 하위 프로세스를 닫는 "GenerateConsoleCtrlEvent (CTRL_BREAK, 0)"을 호출합니다. 자식 프로세스를 취소하려고 할 때 부모가 완료하는 이벤트 객체를 사용했습니다.

은 Helper.exe이 CREATE_NO_WINDOW 및 CREATE_NEW_PROCESS_GROUP 그것을 만들 만듭니다. 그리고 하위 프로세스를 생성 할 때 플래그 (0)가없는 상태로 생성하면 부모로부터 콘솔을 파생시킵니다. 이렇게하지 않으면 이벤트가 무시됩니다.

이렇게 각 단계를 수행하는 것이 매우 중요합니다. 나는 모든 종류의 조합을 시도해 왔지만이 조합 만이 효과가 있습니다. CTRL_C 이벤트를 보낼 수 없습니다.그것은 성공을 돌려 주지만 그 과정에서 무시 될 것입니다. 작동하는 것은 CTRL_BREAK뿐입니다. 둘 다 결국 ExitProcess()를 호출 할 것이기 때문에별로 중요하지 않습니다.

도우미 프로세스가 계속 살도록 허용하는 자식 프로세스 ID의 프로세스 groupd ID로 GenerateConsoleCtrlEvent()를 호출 할 수도 없습니다. 이것은 또한 실패 할 것이다.

저는 하루 종일이 작업을하기 위해 노력했습니다. 이 솔루션은 나를 위해 작동하지만 다른 사람이 추가 할 사항이 있으면 알려주세요. 비슷한 문제가있는 많은 사람들을 발견했지만 그 문제에 대한 확실한 해결책은 찾지 못했습니다. GenerateConsoleCtrlEvent() 작동 방식도 조금 이상합니다. 자세한 내용을 알고 있다면 공유하십시오.

+3

Ctrl + C를 받으면 프로세스 B 또는 C가 정상적으로 종료된다는 보장이 없습니다. –

+0

임의의 응용 프로그램이 Ctrl + C에 응답한다는 보장은 없지만 대상 응용 프로그램이 실제로 ctrl + c에 응답하여 완전히 종료되는 것으로 알려진 경우이 메서드에 대해 알면 중요합니다. 그러한 알려진 응용 프로그램은 깔끔하게 종료됩니다. – Triynko

+0

허용 된 대답은 @KindDragon –

8

마찬가지로 @Shakta는 GenerateConsoleCtrlEvent()이 매우 까다 롭지 만 도우미 프로세스없이 Ctrl + C를 보낼 수 있습니다.

void SendControlC(int pid) 
{ 
    AttachConsole(pid); // attach to process console 
    SetConsoleCtrlHandler(NULL, TRUE); // disable Control+C handling for our app 
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // generate Control+C event 
} 
+0

의 답변이어야합니다. 매우 도움이되었습니다. 단 하나만 빠져 있습니다. AttachConsole을 사용하기 전에 FreeConsole을 호출해야합니다. 그렇지 않으면 호출 프로세스가 이미 콘솔에 연결되어 있으므로 ERROR_ACCESS_DENIED (5)가 표시됩니다. – Yael

+0

이것은 나를 위해 성공한 12 가지 질문에 대한 유일한 대답입니다. 감사합니다! –

관련 문제