Browse Source

Command to exit with state code.

Use "nssm statuscode <servicename>" to set the exit code to the value of
dwCurrentState, eg 4 for running.  An exit code of 0 implies an error.

Thanks Meang Akira Tanaka.
Iain Patterson 5 years ago
parent
commit
a2f02c89be
5 changed files with 36 additions and 2 deletions
  1. 16 0
      README.txt
  2. BIN
      messages.mc
  3. 1 0
      nssm.cpp
  4. 18 2
      service.cpp
  5. 1 0
      service.h

+ 16 - 0
README.txt

@@ -848,6 +848,20 @@ NSSM offers rudimentary service control features.
 
     nssm status <servicename>
 
+    nssm statuscode <servicename>
+
+The output of "nssm status" and "nssm statuscode" is a string
+representing the service state, eg SERVICE_RUNNING.
+
+The exit code of "nssm status" will be 0 if the status was
+succesfully retrieved.  If the exit code is not zero there was
+an error.
+
+The exit code of "nssm statuscode" will be the numeric value
+of the service state, eg 4 for SERVICE_RUNNING.  Zero is not a
+valid service state code.  If the exit code is zero there was
+an error.
+
 
 Removing services using the GUI
 -------------------------------
@@ -1022,6 +1036,8 @@ Thanks to Bader Aldurai for suggesting the process tree.
 Thanks to Christian Long for suggesting virtual accounts.
 Thanks to Marcin Lewandowski for spotting a bug appending to large files.
 Thanks to Nicolas Ducrocq for suggesting timestamping redirected output.
+Thanks to Meang Akira Tanaka for suggestion and initial implementation of
+the statuscode command.
 
 Licence
 -------

BIN
messages.mc


+ 1 - 0
nssm.cpp

@@ -256,6 +256,7 @@ int _tmain(int argc, TCHAR **argv) {
     if (str_equiv(argv[1], _T("pause"))) nssm_exit(control_service(SERVICE_CONTROL_PAUSE, argc - 2, argv + 2));
     if (str_equiv(argv[1], _T("continue"))) nssm_exit(control_service(SERVICE_CONTROL_CONTINUE, argc - 2, argv + 2));
     if (str_equiv(argv[1], _T("status"))) nssm_exit(control_service(SERVICE_CONTROL_INTERROGATE, argc - 2, argv + 2));
+    if (str_equiv(argv[1], _T("statuscode"))) nssm_exit(control_service(SERVICE_CONTROL_INTERROGATE, argc - 2, argv + 2, true));
     if (str_equiv(argv[1], _T("rotate"))) nssm_exit(control_service(NSSM_SERVICE_CONTROL_ROTATE, argc - 2, argv + 2));
     if (str_equiv(argv[1], _T("install"))) {
       if (! is_admin) nssm_exit(elevate(argc, argv, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_INSTALL));

+ 18 - 2
service.cpp

@@ -1360,7 +1360,7 @@ int edit_service(nssm_service_t *service, bool editing) {
 }
 
 /* Control a service. */
-int control_service(unsigned long control, int argc, TCHAR **argv) {
+int control_service(unsigned long control, int argc, TCHAR **argv, bool return_status) {
   if (argc < 1) return usage(1);
   TCHAR *service_name = argv[0];
   TCHAR canonical_name[SERVICE_NAME_LENGTH];
@@ -1368,6 +1368,7 @@ int control_service(unsigned long control, int argc, TCHAR **argv) {
   SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
   if (! services) {
     print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
+    if (return_status) return 0;
     return 2;
   }
 
@@ -1394,6 +1395,7 @@ int control_service(unsigned long control, int argc, TCHAR **argv) {
   SC_HANDLE service_handle = open_service(services, service_name, access, canonical_name, _countof(canonical_name));
   if (! service_handle) {
     CloseServiceHandle(services);
+    if (return_status) return 0;
     return 3;
   }
 
@@ -1431,6 +1433,7 @@ int control_service(unsigned long control, int argc, TCHAR **argv) {
 
       if (response) {
         print_message(stderr, NSSM_MESSAGE_BAD_CONTROL_RESPONSE, canonical_name, service_status_text(service_status.dwCurrentState), service_control_text(control));
+        if (return_status) return 0;
         return 1;
       }
       else _tprintf(_T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));
@@ -1439,6 +1442,7 @@ int control_service(unsigned long control, int argc, TCHAR **argv) {
     else {
       CloseServiceHandle(service_handle);
       _ftprintf(stderr, _T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));
+      if (return_status) return 0;
       return 1;
     }
   }
@@ -1453,10 +1457,12 @@ int control_service(unsigned long control, int argc, TCHAR **argv) {
 
     if (ret) {
       _tprintf(_T("%s\n"), service_status_text(service_status.dwCurrentState));
+      if (return_status) return service_status.dwCurrentState;
       return 0;
     }
     else {
       _ftprintf(stderr, _T("%s: %s\n"), canonical_name, error_string(error));
+      if (return_status) return 0;
       return 1;
     }
   }
@@ -1477,22 +1483,32 @@ int control_service(unsigned long control, int argc, TCHAR **argv) {
 
       if (response) {
         print_message(stderr, NSSM_MESSAGE_BAD_CONTROL_RESPONSE, canonical_name, service_status_text(service_status.dwCurrentState), service_control_text(control));
+        if (return_status) return 0;
         return 1;
       }
       else _tprintf(_T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));
+      if (return_status) return service_status.dwCurrentState;
       return 0;
     }
     else {
       CloseServiceHandle(service_handle);
       _ftprintf(stderr, _T("%s: %s: %s"), canonical_name, service_control_text(control), error_string(error));
       if (error == ERROR_SERVICE_NOT_ACTIVE) {
-        if (control == SERVICE_CONTROL_SHUTDOWN || control == SERVICE_CONTROL_STOP) return 0;
+        if (control == SERVICE_CONTROL_SHUTDOWN || control == SERVICE_CONTROL_STOP) {
+          if (return_status) return SERVICE_STOPPED;
+          return 0;
+        }
       }
+      if (return_status) return 0;
       return 1;
     }
   }
 }
 
+int control_service(unsigned long control, int argc, TCHAR **argv) {
+  return control_service(control, argc, argv, false);
+}
+
 /* Remove the service */
 int remove_service(nssm_service_t *service) {
   if (! service) return 1;

+ 1 - 0
service.h

@@ -156,6 +156,7 @@ int pre_edit_service(int, TCHAR **);
 int install_service(nssm_service_t *);
 int remove_service(nssm_service_t *);
 int edit_service(nssm_service_t *, bool);
+int control_service(unsigned long, int, TCHAR **, bool);
 int control_service(unsigned long, int, TCHAR **);
 void set_service_recovery(nssm_service_t *);
 int monitor_service(nssm_service_t *);