C++ 监视程序并在崩溃时重新启动它

C++ 监视程序并在崩溃时重新启动它,c++,winapi,signals,C++,Winapi,Signals,我有一个程序有时会崩溃。在这种情况下,我的程序应该自动重新启动。但在通过任务管理器杀死它的同时,它应该结束。 我创建了监视程序,它监视实际程序,并在崩溃时重新启动它。 我使用实际程序发送的信号来终止它来完成这项工作。 我正在使用Windows操作系统。 也就是说,我需要截获发送到监控程序中实际程序的信号过程监控程序应执行以下操作: 创建主进程,从而获得该进程的句柄 等待该句柄发出信号,例如使用WaitForSingleObject,这表示进程已终止 重新启动进程,获取新的进程句柄,然后转到2 您

我有一个程序有时会崩溃。在这种情况下,我的程序应该自动重新启动。但在通过任务管理器杀死它的同时,它应该结束。
我创建了监视程序,它监视实际程序,并在崩溃时重新启动它。
我使用实际程序发送的信号来终止它来完成这项工作。
我正在使用Windows操作系统。

也就是说,我需要截获发送到监控程序中实际程序的信号

过程监控程序应执行以下操作:

  • 创建主进程,从而获得该进程的句柄
  • 等待该句柄发出信号,例如使用
    WaitForSingleObject
    ,这表示进程已终止
  • 重新启动进程,获取新的进程句柄,然后转到2
  • 您应该安排监视器程序始终创建主进程,并且两者都位于作业对象中,该作业对象配置为在父进程终止时终止子进程。然后,当您希望终止程序时,只需终止监视器即可。然后,作业对象确保子程序也被终止


    如果可能的话,您应该修复您的程序,使其不会崩溃

    当然你需要修复你的应用程序,因为它不会崩溃。只有这样才是好的解决办法。无论你下一步做得多么正式(糟糕)

    void Ep()
    {
    //在命令行开始处按*标记
    PWSTR CommandLine=GetCommandLine();
    如果(!CommandLine | |*CommandLine!='*'))
    {
    //监控箱
    WCHAR文件名[最大路径];
    if(ULONG n=GetModuleFileName(0,文件名,RTL编号(文件名)))
    {
    如果(n<最大路径)
    {
    处理信息;
    STARTUPINFO si={sizeof(si)};
    PWSTR命令行=(PWSTR)alloca((wcslen(命令行)+2)*sizeof(WCHAR));
    *新命令行='*';
    wcscpy(命令行+1,命令行);
    //监视并重新启动自循环
    布尔-布雷斯特朗;
    做
    {
    bRestart=FALSE;
    if(CreateProcessW(文件名、新命令行、0、0、0、0、0、0、si和pi))
    {
    CloseHandle(pi.hThread);
    WaitForSingleObject(pi.hProcess,无限);
    乌龙出口代码;
    bRestart=GetExitCodeProcess(pi.hProcess,&exitcode);
    CloseHandle(pi.hProcess);
    如果(bRestart)
    {
    //0xff-由WerFault终止
    //(int)exitcode<0-正在处理异常
    bRestart=exitcode==0xff | |((int)exitcode<0);
    }
    }
    }while(bRestart);
    }
    }
    退出过程(0);
    }
    其他的
    {
    //主要案例
    wcscpy(命令行,命令行+1);
    if(MessageBoxW(0,L“make crash?”,命令行,MB_YESNO)=idies)
    {
    __debugbreak();//模拟崩溃
    }
    退出过程(0);
    }
    }
    
    让我们暂时忽略您的问题,转而解决问题。您正在寻找一种在异常退出时重新启动应用程序的方法,但仍然保留终止应用程序的能力(通过其GUI或任务管理器)


    Windows提供了这方面的服务。系统内置的基础设施允许您注册应用程序,以便在出现未经处理的异常(非正式称为崩溃)时重新启动。

    为什么不修复您的程序,使其不会崩溃?您的问题是什么?你为什么不修复你的程序呢?我的程序很少崩溃,比如说超时,所以重新启动它会使它正常工作。所以在这种情况下,我的监控程序应该重新启动。我的问题是,我不知道如何在监控程序中截取发送给程序的信号。你的程序永远不会崩溃。你需要花更多的时间来解决问题,或者至少找出程序崩溃的原因。但是我应该能够在不终止“监控”程序的情况下终止程序。那么,监控程序如何知道这是故意终止的呢?如果您真的想确保您的流程始终在运行,那么我所概述的过程就是一种方法。也许你需要对你想要达到的目标有一点思考。在我看来,你已经决定了你的解决方案(这是行不通的),不想再考虑其他任何事情了。在这种情况下,祝你好运!
    void Ep()
    {
        // tag by * in begin of CommandLine
        PWSTR CommandLine = GetCommandLine();
    
        if (!CommandLine || *CommandLine != '*')
        {
            // monitor case
    
            WCHAR FileName[MAX_PATH];
            if (ULONG n = GetModuleFileName(0, FileName, RTL_NUMBER_OF(FileName)))
            {
                if (n < MAX_PATH)
                {
                    PROCESS_INFORMATION pi;
                    STARTUPINFO si = { sizeof(si) };
                    PWSTR newCommandLine = (PWSTR)alloca((wcslen(CommandLine) + 2)*sizeof(WCHAR));
                    *newCommandLine = '*';
                    wcscpy(newCommandLine + 1, CommandLine);
    
                    // monitor and restart self in loop
                    BOOL bRestart;
                    do 
                    {
                        bRestart = FALSE;
                        if (CreateProcessW(FileName, newCommandLine, 0, 0, 0, 0, 0, 0, &si, &pi))
                        {
                            CloseHandle(pi.hThread);
                            WaitForSingleObject(pi.hProcess, INFINITE);
                            ULONG exitcode;
                            bRestart = GetExitCodeProcess(pi.hProcess, &exitcode);
                            CloseHandle(pi.hProcess);
                            if (bRestart)
                            {
                                // 0xff - terminated by WerFault
                                // (int)exitcode < 0 - exception in process
                                bRestart = exitcode == 0xff || ((int)exitcode < 0);
                            }
                        }
                    } while (bRestart);
                }
            }
            ExitProcess(0);
        }
        else
        {
            // main case
    
            wcscpy(CommandLine, CommandLine + 1);
    
            if (MessageBoxW(0, L"make crash ?", CommandLine, MB_YESNO) == IDYES)
            {
                __debugbreak();// simulate crash
            }
            ExitProcess(0);
        }
    }