Browse Source

Added list command to enumerate NSSM services.

Use "nssm list" to print all services which are managed by NSSM.
Iain Patterson 6 years ago
parent
commit
1f0b03b38f
4 changed files with 70 additions and 0 deletions
  1. 9 0
      README.txt
  2. 1 0
      nssm.cpp
  3. 59 0
      service.cpp
  4. 1 0
      service.h

+ 9 - 0
README.txt

@@ -68,6 +68,8 @@ Since version 2.22, NSSM can manage existing services.
 
 Since version 2.25, NSSM can execute commands in response to service events.
 
+Since version 2.25, NSSM can list services it manages.
+
 
 Usage
 -----
@@ -790,6 +792,13 @@ running multiple instances of NSSM from different locations may be confusing if
 they are not all the same version.
 
 
+Listing managed services
+------------------------
+The following command will print the names of all services managed by NSSM:
+
+    nssm list
+
+
 Example usage
 -------------
 To install an Unreal Tournament server:

+ 1 - 0
nssm.cpp

@@ -155,6 +155,7 @@ int _tmain(int argc, TCHAR **argv) {
       for (int i = 0; i < argc; i++) SecureZeroMemory(argv[i], _tcslen(argv[i]) * sizeof(TCHAR));
       exit(ret);
     }
+    if (str_equiv(argv[1], _T("list"))) exit(list_nssm_services());
     if (str_equiv(argv[1], _T("remove"))) {
       if (! is_admin) exit(elevate(argc, argv, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_REMOVE));
       exit(pre_remove_service(argc - 2, argv + 2));

+ 59 - 0
service.cpp

@@ -2115,3 +2115,62 @@ awaited:
 
   return ret;
 }
+
+int list_nssm_services() {
+  /* Open service manager. */
+  SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
+  if (! services) {
+    print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
+    return 1;
+  }
+
+  unsigned long bufsize, required, count, i;
+  unsigned long resume = 0;
+  EnumServicesStatus(services, SERVICE_WIN32, SERVICE_STATE_ALL, 0, 0, &required, &count, &resume);
+  unsigned long error = GetLastError();
+  if (error != ERROR_MORE_DATA) {
+    print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError()));
+    return 2;
+  }
+
+  ENUM_SERVICE_STATUS *status = (ENUM_SERVICE_STATUS *) HeapAlloc(GetProcessHeap(), 0, required);
+  if (! status) {
+    print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("ENUM_SERVICE_STATUS"), _T("list_nssm_services()"));
+    return 3;
+  }
+
+  bufsize = required;
+  while (true) {
+    int ret = EnumServicesStatus(services, SERVICE_WIN32, SERVICE_STATE_ALL, status, bufsize, &required, &count, &resume);
+    if (! ret) {
+      error = GetLastError();
+      if (error != ERROR_MORE_DATA) {
+        HeapFree(GetProcessHeap(), 0, status);
+        print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError()));
+        return 4;
+      }
+    }
+
+    for (i = 0; i < count; i++) {
+      /* Try to get the service parameters. */
+      nssm_service_t *service = alloc_nssm_service();
+      if (! service) {
+        HeapFree(GetProcessHeap(), 0, status);
+        print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("nssm_service_t"), _T("list_nssm_services()"));
+        return 5;
+      }
+      _sntprintf_s(service->name, _countof(service->name), _TRUNCATE, _T("%s"), status[i].lpServiceName);
+
+      get_parameters(service, 0);
+      /* We manage the service if we have an Application. */
+      if (service->exe[0]) _tprintf(_T("%s\n"), service->name);
+
+      cleanup_nssm_service(service);
+    }
+
+    if (ret) break;
+  }
+
+  HeapFree(GetProcessHeap(), 0, status);
+  return 0;
+}

+ 1 - 0
service.h

@@ -156,5 +156,6 @@ int stop_service(nssm_service_t *, unsigned long, bool, bool);
 void CALLBACK end_service(void *, unsigned char);
 void throttle_restart(nssm_service_t *);
 int await_single_handle(SERVICE_STATUS_HANDLE, SERVICE_STATUS *, HANDLE, TCHAR *, TCHAR *, unsigned long);
+int list_nssm_services();
 
 #endif