Windows에서 하위 프로세스를 자동으로 삭제하려면 어떻게 해야 하나요?

StackOverflow https://stackoverflow.com/questions/53208

  •  09-06-2019
  •  | 
  •  

문제

C++ Windows 앱에서는 여러 장기 실행 하위 프로세스를 시작합니다(현재는 CreateProcess(...)를 사용하여 이 작업을 수행합니다.

하위 프로세스가 자동으로 닫히도록 하고 싶습니다. 내 주요 프로세스가 충돌하는 경우 또는 폐쇄되었습니다.

"부모"의 충돌에 대해 이 작업이 작동해야 한다는 요구 사항 때문에 운영 체제의 일부 API/기능을 사용하여 이 작업을 수행해야 한다고 생각합니다.모든 "하위" 프로세스가 정리됩니다.

어떻게 해야 하나요?

도움이 되었습니까?

해결책

Windows API는 "작업 개체"라는 개체를 지원합니다.다음 코드는 기본 애플리케이션이 종료될 때(해당 핸들이 정리될 때) 모든 프로세스를 종료하도록 구성된 "작업"을 생성합니다.이 코드는 한 번만 실행되어야 합니다.:

HANDLE ghJob = CreateJobObject( NULL, NULL); // GLOBAL
if( ghJob == NULL)
{
    ::MessageBox( 0, "Could not create job object", "TEST", MB_OK);
}
else
{
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };

    // Configure all child processes associated with the job to terminate when the
    jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
    if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
    {
        ::MessageBox( 0, "Could not SetInformationJobObject", "TEST", MB_OK);
    }
}

그런 다음 각 하위 프로세스가 생성되면 다음 코드를 실행하여 각 하위 프로세스를 실행하고 작업 개체에 추가합니다.

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;

// Launch child process - example is notepad.exe
if (::CreateProcess( NULL, "notepad.exe", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
    ::MessageBox( 0, "CreateProcess succeeded.", "TEST", MB_OK);
    if(ghJob)
    {
        if(0 == AssignProcessToJobObject( ghJob, processInfo.hProcess))
        {
            ::MessageBox( 0, "Could not AssignProcessToObject", "TEST", MB_OK);
        }
    }

    // Can we free handles now? Not sure about this.
    //CloseHandle(processInfo.hProcess); 
    CloseHandle(processInfo.hThread);
}

비스타 참고:보다 Vista에서는 AssignProcessToJobObject가 항상 "액세스 거부"를 반환합니다. Vista에서 AssignProcessToObject()에 대한 액세스 거부 문제가 발생하는 경우.

다른 팁

다소 해킹적인 해결책 중 하나는 상위 프로세스가 각 하위 프로세스에 디버거로 연결되는 것입니다(사용 디버그활성프로세스).디버거가 종료되면 모든 디버기 프로세스도 종료됩니다.

더 나은 해결책(자식 프로세스도 작성했다고 가정)은 하위 프로세스가 상위 프로세스를 모니터링하고 상위 프로세스가 사라지면 종료하도록 하는 것입니다.

Windows 작업 개체는 시작하기에 좋은 곳인 것 같습니다.작업 개체의 이름은 잘 알려져 있거나 자식에게 전달되어야 합니다(또는 핸들을 상속받아야 함).실패한 IPC "하트비트"를 통해 또는 부모 프로세스 핸들의 WFMO/WFSO를 통해 부모가 사망할 때 자식에게 이를 알려야 합니다.이 시점에서 모든 하위 프로세스는 TermianteJobObject가 전체 그룹을 중단시킬 수 있습니다.

별도의 감시 프로세스를 계속 실행할 수 있습니다.유일한 작업은 현재 프로세스 공간을 관찰하여 설명하는 것과 같은 상황을 찾아내는 것입니다.충돌 후 원래 애플리케이션을 다시 시작하거나 사용자에게 다른 옵션을 제공하고 디버그 정보 등을 수집할 수도 있습니다.첫 번째 감시를 감시하기 위해 두 번째 감시자가 필요하지 않도록 충분히 단순하게 유지하십시오.

아마도 시작하는 프로세스의 목록을 유지하고 프로그램을 종료할 때 하나씩 제거해야 할 것입니다.C++에서 이 작업을 수행하는 구체적인 내용은 잘 모르겠지만 어렵지는 않습니다.어려운 부분은 아마도 애플리케이션 충돌 시 하위 프로세스가 종료되는지 확인하는 것입니다..Net에는 처리되지 않은 예외가 발생할 때 호출되는 함수를 추가하는 기능이 있습니다.C++이 동일한 기능을 제공하는지 잘 모르겠습니다.

각 프로세스를 C++ 개체로 캡슐화하고 해당 프로세스의 목록을 전역 범위에 유지할 수 있습니다.소멸자는 각 프로세스를 종료할 수 있습니다.프로그램이 정상적으로 종료되면 제대로 작동하지만 충돌이 발생하면 모든 베팅이 꺼집니다.

대략적인 예는 다음과 같습니다.

class myprocess
{
public:
    myprocess(HANDLE hProcess)
        : _hProcess(hProcess)
    { }

    ~myprocess()
    {
        TerminateProcess(_hProcess, 0);
    }

private:
    HANDLE _hProcess;
};

std::list<myprocess> allprocesses;

그런 다음 시작할 때마다 allprocessess.push_back(hProcess);을 호출하세요.

내 머리 꼭대기에서 바로 :

  • 프로세스 대신 스레드 사용을 고려해 보셨나요?
  • 메인 스레드/프로세스의 핸들을 하위 프로세스에 전달하고 해당 핸들을 기다리도록 해보세요.스레드 핸들을 기다리는 것은 해당 스레드가 완료되고 종료될 때까지 기다리기 때문에 스레드에 대해 작동합니다.프로세스에서 작동할지 확실하지 않은 경우 MSDN을 확인하여 이를 확인해야 합니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top