0

我创建了一个将在启动时自动运行的服务 exe。

我正在使用这个例子来创建服务: http ://www.cromis.net/blog/2011/04/how-to-make-a-very-small-windows-service-executable/

效果很好。该服务需要“监控”PC 的状态,例如检查 PC 是否连接到电源。如果发生更改,例如从连接电源到电池或电池电量不足状态,它将发送有关设备临界状态的紧急电子邮件。

当作为普通 exe 而不是作为服务运行时,这非常有效。目标是能够在 PC 的任何状态(登录或未登录)下执行此操作,因此必须作为服务运行。

我创建了一个窗口句柄来接收 WM_POWERBROADCAST 消息,例如:

procedure TEventAlerter.wndProc(var Msg : TMessage);
var
  handled: Boolean;

begin
  log( 'wndProc processed - '+intToStr( Msg.Msg ));
  // Assume we handle message
  handled := TRUE;
  case( Msg.Msg ) of
    WM_POWERBROADCAST : begin
                         case( Msg.WParam ) of
                           PBT_APMPOWERSTATUSCHANGE : powerChangeEvent(Msg.WParam);
                           PBT_APMBATTERYLOW        : powerLowEvent(Msg.WParam);
                          else powerEvent(Msg.WParam);
                         end;
                        end;
    else handled:= FALSE;
  end;

  if( handled ) then
   begin
    // We handled message - record in message result
    Msg.Result := 0
   end
  else
   begin
    // We didn't handle message
    // pass to DefWindowProc and record result
    Msg.Result := DefWindowProc(fHWnd, Msg.Msg, Msg.WParam, Msg.LParam);
   end;
end; 

要初始化我正在使用这个:

FHwnd:=AllocateHWnd(wndProc);

因为我在作为服务运行时知道 0 隔离状态,所以我更改了 RegisterService() 函数的一些示例代码:

ServiceStatus.dwServiceType := SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS;
ServiceStatus.dwCurrentState := SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted := SERVICE_ACCEPT_STOP or
                                    SERVICE_ACCEPT_PAUSE_CONTINUE or
                                    SERVICE_ACCEPT_POWEREVENT;

但没有任何成功。我还使用线程getMessage()从窗口中使用 Windows API 函数轮询消息,但结果是相同的。

我能做些什么来捕捉 powerstate 事件?服务无法对电源状态更改做出反应,这有点奇怪?

4

1 回答 1

6

当服务使用SERVICE_ACCEPT_POWEREVENT时,服务必须使用HandlerEx()回调 viaRegisterServiceCtrlHandlerEx()来接收SERVICE_CONTROL_POWEREVENT来自 SCM 的通知。但是,您链接到的示例代码(以及 Delphi 自己的TService框架)使用过时的Handler()回调 viaRegisterServiceCtrlHandler()代替,它不会收到此类通知。因此,您需要更新代码以改用HandlerEx()回调。

或者,要在不使用 SCM 回调的情况下接收电源通知,请查看RegisterPowerSettingNotification()PowerSettingRegisterNotification(),它可以分别将电源通知发送到 HWND 或回调函数。

于 2015-03-08T16:47:04.580 回答