Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am trying to create a service following the example documented in the link below: http://msdn.microsoft.com/en-us/library/bb540475(v=VS.85).aspx

What I am interested in is to be able to catch user "lock" and "unlock" workstation events.

Using the code on from the example provided, I modified the following:

Line 15:

Original:

VOID WINAPI SvcCtrlHandler( DWORD );

Modified:

DWORD WINAPI SvcCtrlHandler( DWORD, DWORD, LPVOID, LPVOID );

Line 141:

Original:

gSvcStatusHandle = RegisterServiceCtrlHandler( SVCNAME, SvcCtrlHandler);

Modified:

gSvcStatusHandle = RegisterServiceCtrlHandlerEx( SVCNAME, SvcCtrlHandler, NULL);

Line 244:

Original:

gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

Modified:

gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SESSIONCHANGE;

Line 266:

Original:

VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
   // Handle the requested control code. 
   switch(dwCtrl) 
      case SERVICE_CONTROL_STOP: 
         ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
         // Signal the service to stop.
         SetEvent(ghSvcStopEvent);
         ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
         return;
      case SERVICE_CONTROL_INTERROGATE: 
         break; 
      default: 
         break;

Modified:

DWORD WINAPI SvcCtrlHandler( DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext )
   DWORD dwErrorCode = NO_ERROR;
   switch(dwControl) 
      case SERVICE_CONTROL_STOP: 
         ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
         // Signal the service to stop.
         SetEvent(ghSvcStopEvent);
         ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
   break;
      case SERVICE_CONTROL_INTERROGATE: 
         break; 
      case SERVICE_CONTROL_SESSIONCHANGE:
 ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
 break;
      default:
 break;
   return dwErrorCode;   

With the changes above, my service compiled and install fine.

I try starting my service on the windows 7 machine, it would start fine (but I will not be able to stop, pause or do anything to the service as all option will be disabled).

I also tried my service on my Windows 2000 machine, it does not even start(it will be stuck on the "starting" status)

My main objective is getting the service to run properly on the Windows 7 environment, getting it backward compatible in Windows 2000 will be a bonus.

Can anyone please advise? Thank you in advance,

I have a test service here that accepts session change events and runs just fine on Windows 7. It supports all notifications possible and correctly allows stop and pause and deals with the session change events.

Not that helpful, I know, but at least you know that you should be able to get it to work as documented... My service code is considerably more complex than the basic example you have there so I can't see at a glance what mistake you're making.

Since you're not getting seeing stop available as an option I'd check that you are setting the controls accepted correctly, or change just that back to just stop and make sure that you are seeing stop as an option once you start the service...

Thank you for confirming. When I revert back to just accepting the stop command, the service runs fine (starts and stops correctly). It is with the SERVICE_ACCEPT_SESSIONCHANGE that seems to cause the hang. Will you be able to check for me if you have any special code in the handler for the session change event? I am thinking if I am missing some crucial handling calls. Thank you in advance. – Ron Apr 28, 2010 at 13:39 My code doesn't do anything that different from yours; about the only changes are that I completely initialise all elements of the service status structure and I tend to pass 2000 as the wait hint rather than 0 when I 'report status' with nothing to say. I also pass a non null context through to the handler, but I doubt that changes much as I expect it's treated as an opaque handle internally (though the docs don't state explicitly that it can be null). – Len Holgate Apr 28, 2010 at 14:38

MSDN says : SERVICE_ACCEPT_SESSIONCHANGE: "Windows 2000: This value is not supported."

Not sure if that is the actual reason why the service gets stuck in the starting phase.

Edit: Alternative ways to get session events on windows 2000:

  • Winlogon Notification Packages
  • SENS: ISensLogon
  • Hi there, thank you for the quick reply. The reason why I was trying to create a service is because our company is moving to the Windows 7 platform. We used to implement the Winlogon method (but it's unsupported by Win 7) I forgot to mention, I actually tried the service on a Windows 7 machine and was able to get it to start. However, all the operation button will be disabled when I right click on the service afterwards. Any other advice will be greatly appreciated. – Ron Apr 27, 2010 at 17:42 Well, you would only need the Winlogon or SENS codepath on 2000, later platforms supports the sessionchange flag – Anders Apr 27, 2010 at 17:46 Yes you are correct, I modified my original post to clarify my intent. I am trying to get it work with Windows 7. Getting it to be backward compatible with Windows 2000 will be a bonus. – Ron Apr 27, 2010 at 17:50 Hi thank you again for confirming it should work. I rewrite the code from scratch and it seems to be working :O . – Ron Apr 28, 2010 at 20:39

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.