Archive: Service Fail/Recovery Actions


Service Fail/Recovery Actions
I am attempting to install and register a Windows service with some additional configuration. The ServiceLib library is useful for the initial registration, and I've worked out how to set the service's description (As seen in the console), but I am having trouble configuring recovery options.

I've established that the "ChangeServiceConfig2" function (Defined in the "advapi32" library) can be used to set these options, but I'm not sure how to call it and pass the correct values.

When using it to set the description, I called it like this (For all examples, assume that $0 contains the service's handle):

!define _SERVICE_CONFIG_DESCRIPTION 1

System::Call '*(t "Description") i.r1'
System::Call 'advapi32::ChangeServiceConfig2(i r0, i ${_SERVICE_CONFIG_DESCRIPTION}, i r1) i.r2'


However, configuring fail actions requires a much more complicated parameter structure, and I don't really know what I'm doing (I'm ordinarily a C# developer, so the extent of my Windows API knowledge is what I've scrounged from pinvoke, and I have very little understanding of the System plugin).

The call should look something like this:

!define _SERVICE_CONFIG_FAILURE_ACTIONS 0x02

System::Call 'advapi32::ChangeServiceConfig2(i r0, i ${_SERVICE_CONFIG_FAILURE_ACTIONS}, i r3) i.r4'


Where $3 contains a structure matching the following:

typedef struct _SERVICE_FAILURE_ACTIONS {
DWORD dwResetPeriod;
LPTSTR lpRebootMsg;
LPTSTR lpCommand;
DWORD cActions;
SC_ACTION *lpsaActions;
} SERVICE_FAILURE_ACTIONS,
*LPSERVICE_FAILURE_ACTIONS;

typedef struct _SC_ACTION {
SC_ACTION_TYPE Type;
DWORD Delay;
} SC_ACTION,
*LPSC_ACTION;

SC_ACTION_TYPEs
0 - No action
1 - Restart the service
2 - Reboot the computer
3 - Run a command


I've tried a few variations on the following:

; An array of one SC_ACTION with "restart" action
System::Call '*(i 1, i 0) i.r5'
System::Call '*(i r5) i.r6'

; SERVICE_FAILURE_ACTIONS
System::Call '*(i 0, t, t, i 1, i r6) i.r3'


But to no avail...

If anyone can help me with this, it would be greatly appreciated. I've done extensive Googling on the subject, but it doesn't look like anyone's tried to do this via NSIS before.


Someone else may have better info about the DLL calls, but I thought I'd offer this as an alternate solution:

You might have a look at a MS tool called sc.exe.

It's basically a command line service control manager, which you can run with nsExec.

It seems like it *should* work in your situation and might be easier than DLL calls.


Funnily enough I was actually trying to use the API calls so that I wouldn't need to be reliant on an external program (Namely "sc.exe").

I know that it has to be possible for the API calls to work, since that's how Windows (And probably "sc.exe") does it, but I don't really have much experience with the "System" plugin. I'm very likely passing garbage parameters to the function call, and thus doing nothing.


I think "sc.exe" is available for all Windows versions that support services (Windows NT, 2000, XP and later). So depending on that program shouldn't be a problem. You can simply include it into your installer and extract it to $PLUGINSDIR at runtime...


I know this is an old thread, but I am trying to solve the same problem. I want to be able to set the recovery options when installing a service, but I don't want to rely on a separate program like sc.exe. Anyone know if this is possible?


http://nsis.sourceforge.net/NSIS_Simple_Service_Plugin

Stu