关机或重启时正常关闭服务问题

时间:2022-11-02 23:44:11
1.如何能关机或重启时,让服务(包括服务打开的程序)正常关闭(LogEvent信息要有)

2.普通的程序,可以用捕捉WM_QUERYENDSESSION,配合ExitWindowsEx()实现。
但经测试,服务和服务打开的程序(用CreateProcess)根本没有收到WM_QUERYENDSESSION。。。
请问这是什么原因?
有没有其他方法能实现1的功能

先谢谢了,帮顶有分

15 个解决方案

#1


Mark 学习帮顶。

#2


现在基本可以确定
建立服务时加上SERVICE_INTERACTIVE_PROCESS
就可以捕获WM_QUERYENDSESSION

请问有没有不与桌面交互也可以捕获的办法

#3


在服务的HandlerEx函数中响应SERVICE_CONTROL_POWEREVENT事件。

#4


服务程序应该响应SERVICE_CONTROL_STOP指令来执行关闭操作,这样的适应性最强,因为服务不仅仅是在关机或重启时才关闭的,也可能会被用户或者其他程序关闭。

#5


to 满天星
有没有HandlerEx的详细介绍或有代码的例子?
SERVICE_CONTROL_POWEREVENT在哪里定义的,它能阻止关机吗?

#6


引用 4 楼 jameshooo 的回复:
服务程序应该响应SERVICE_CONTROL_STOP指令来执行关闭操作,这样的适应性最强,因为服务不仅仅是在关机或重启时才关闭的,也可能会被用户或者其他程序关闭。

不是很明白。。。
inline void CServiceModule::Handler(DWORD dwOpcode)
{
    switch (dwOpcode)
    {
    case SERVICE_CONTROL_STOP:
        SetServiceStatus(SERVICE_STOP_PENDING);
        PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
        break;
    case SERVICE_CONTROL_PAUSE:
        break;
    case SERVICE_CONTROL_CONTINUE:
        break;
    case SERVICE_CONTROL_INTERROGATE:
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        break;
    default:
        LogEvent(_T("Bad service request"));
    }
}

我这样是不是已经响应了?

#7


HandlerEx是通过RegisterServiceCtrlHandlerEx来设置的,如果用这个函数,就不要用RegisterServiceCtrlHandler了。HandlerEx与Handler基本上是一样的。

#8


如上代码
为什么设置了m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN的情况下

SERVICE_CONTROL_SHUTDOWN收不到呢?

#9


引用 7 楼 cnzdgs 的回复:
HandlerEx是通过RegisterServiceCtrlHandlerEx来设置的,如果用这个函数,就不要用RegisterServiceCtrlHandler了。HandlerEx与Handler基本上是一样的。


但HandlerEx和SERVICE_CONTROL_POWEREVENT在程序里都显示没有定义,需要引用什么文件吗?

#10


HandlerEx是自己定义的函数,用什么名字都可以,在RegisterServiceCtrlHandlerEx时给出名称。
SERVICE_CONTROL_POWEREVENT与其它SERVICE_CONTROL_XXX都是在一起定义的,在Winsvc.h文件中,其值是0xD。

#11



   case SERVICE_CONTROL_STOP:
        SetServiceStatus(SERVICE_STOP_PENDING);
        /*
         * 在这里关闭服务创建的其它进程
        */
        PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
        // 既然用了消息循环,那么还要在消息循环退出后再执行一次 SetServiceStatus(SERVICE_STOPPED);
        // 否则服务管理器会认为服务已经失去响应
        break;

#12


引用 4 楼 jameshooo 的回复:
服务程序应该响应SERVICE_CONTROL_STOP指令来执行关闭操作,这样的适应性最强,因为服务不仅仅是在关机或重启时才关闭的,也可能会被用户或者其他程序关闭。
赞同。

#13


引用 11 楼 jameshooo 的回复:
C/C++ code
   case SERVICE_CONTROL_STOP:
        SetServiceStatus(SERVICE_STOP_PENDING);
        /*
         * 在这里关闭服务创建的其它进程
        */
        PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
        // 既然用了消息循环,那么还要在消息循环退出后再执行一次 SetServiceStatus(SERVICE_STOPPED);
        // 否则服务管理器会认为服务已经失去响应
        break;


这个方法测试了
不能阻止关机

#14


我记得系统关机是不停止服务程序的,也就是不会产生SERVICE_CONTROL_STOP事件。

#15


还是采用交互界面了
虽然问题没有解决还是谢谢各位的关注

#1


Mark 学习帮顶。

#2


现在基本可以确定
建立服务时加上SERVICE_INTERACTIVE_PROCESS
就可以捕获WM_QUERYENDSESSION

请问有没有不与桌面交互也可以捕获的办法

#3


在服务的HandlerEx函数中响应SERVICE_CONTROL_POWEREVENT事件。

#4


服务程序应该响应SERVICE_CONTROL_STOP指令来执行关闭操作,这样的适应性最强,因为服务不仅仅是在关机或重启时才关闭的,也可能会被用户或者其他程序关闭。

#5


to 满天星
有没有HandlerEx的详细介绍或有代码的例子?
SERVICE_CONTROL_POWEREVENT在哪里定义的,它能阻止关机吗?

#6


引用 4 楼 jameshooo 的回复:
服务程序应该响应SERVICE_CONTROL_STOP指令来执行关闭操作,这样的适应性最强,因为服务不仅仅是在关机或重启时才关闭的,也可能会被用户或者其他程序关闭。

不是很明白。。。
inline void CServiceModule::Handler(DWORD dwOpcode)
{
    switch (dwOpcode)
    {
    case SERVICE_CONTROL_STOP:
        SetServiceStatus(SERVICE_STOP_PENDING);
        PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
        break;
    case SERVICE_CONTROL_PAUSE:
        break;
    case SERVICE_CONTROL_CONTINUE:
        break;
    case SERVICE_CONTROL_INTERROGATE:
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        break;
    default:
        LogEvent(_T("Bad service request"));
    }
}

我这样是不是已经响应了?

#7


HandlerEx是通过RegisterServiceCtrlHandlerEx来设置的,如果用这个函数,就不要用RegisterServiceCtrlHandler了。HandlerEx与Handler基本上是一样的。

#8


如上代码
为什么设置了m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN的情况下

SERVICE_CONTROL_SHUTDOWN收不到呢?

#9


引用 7 楼 cnzdgs 的回复:
HandlerEx是通过RegisterServiceCtrlHandlerEx来设置的,如果用这个函数,就不要用RegisterServiceCtrlHandler了。HandlerEx与Handler基本上是一样的。


但HandlerEx和SERVICE_CONTROL_POWEREVENT在程序里都显示没有定义,需要引用什么文件吗?

#10


HandlerEx是自己定义的函数,用什么名字都可以,在RegisterServiceCtrlHandlerEx时给出名称。
SERVICE_CONTROL_POWEREVENT与其它SERVICE_CONTROL_XXX都是在一起定义的,在Winsvc.h文件中,其值是0xD。

#11



   case SERVICE_CONTROL_STOP:
        SetServiceStatus(SERVICE_STOP_PENDING);
        /*
         * 在这里关闭服务创建的其它进程
        */
        PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
        // 既然用了消息循环,那么还要在消息循环退出后再执行一次 SetServiceStatus(SERVICE_STOPPED);
        // 否则服务管理器会认为服务已经失去响应
        break;

#12


引用 4 楼 jameshooo 的回复:
服务程序应该响应SERVICE_CONTROL_STOP指令来执行关闭操作,这样的适应性最强,因为服务不仅仅是在关机或重启时才关闭的,也可能会被用户或者其他程序关闭。
赞同。

#13


引用 11 楼 jameshooo 的回复:
C/C++ code
   case SERVICE_CONTROL_STOP:
        SetServiceStatus(SERVICE_STOP_PENDING);
        /*
         * 在这里关闭服务创建的其它进程
        */
        PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
        // 既然用了消息循环,那么还要在消息循环退出后再执行一次 SetServiceStatus(SERVICE_STOPPED);
        // 否则服务管理器会认为服务已经失去响应
        break;


这个方法测试了
不能阻止关机

#14


我记得系统关机是不停止服务程序的,也就是不会产生SERVICE_CONTROL_STOP事件。

#15


还是采用交互界面了
虽然问题没有解决还是谢谢各位的关注