Added list command to enumerate NSSM services.
authorIain Patterson <me@iain.cx>
Wed, 20 Apr 2016 21:25:36 +0000 (22:25 +0100)
committerIain Patterson <me@iain.cx>
Wed, 20 Apr 2016 21:25:36 +0000 (22:25 +0100)
Use "nssm list" to print all services which are managed by NSSM.

README.txt
nssm.cpp
service.cpp
service.h

index a95ed94..a731a46 100644 (file)
@@ -68,6 +68,8 @@ Since version 2.22, NSSM can manage existing services.
 \r
 Since version 2.25, NSSM can execute commands in response to service events.\r
 \r
 \r
 Since version 2.25, NSSM can execute commands in response to service events.\r
 \r
+Since version 2.25, NSSM can list services it manages.\r
+\r
 \r
 Usage\r
 -----\r
 \r
 Usage\r
 -----\r
@@ -790,6 +792,13 @@ running multiple instances of NSSM from different locations may be confusing if
 they are not all the same version.\r
 \r
 \r
 they are not all the same version.\r
 \r
 \r
+Listing managed services\r
+------------------------\r
+The following command will print the names of all services managed by NSSM:\r
+\r
+    nssm list\r
+\r
+\r
 Example usage\r
 -------------\r
 To install an Unreal Tournament server:\r
 Example usage\r
 -------------\r
 To install an Unreal Tournament server:\r
index 0b586f3..ff9eb52 100644 (file)
--- a/nssm.cpp
+++ b/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));\r
       exit(ret);\r
     }\r
       for (int i = 0; i < argc; i++) SecureZeroMemory(argv[i], _tcslen(argv[i]) * sizeof(TCHAR));\r
       exit(ret);\r
     }\r
+    if (str_equiv(argv[1], _T("list"))) exit(list_nssm_services());\r
     if (str_equiv(argv[1], _T("remove"))) {\r
       if (! is_admin) exit(elevate(argc, argv, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_REMOVE));\r
       exit(pre_remove_service(argc - 2, argv + 2));\r
     if (str_equiv(argv[1], _T("remove"))) {\r
       if (! is_admin) exit(elevate(argc, argv, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_REMOVE));\r
       exit(pre_remove_service(argc - 2, argv + 2));\r
index d864fa2..b3b0c62 100644 (file)
@@ -2115,3 +2115,62 @@ awaited:
 \r
   return ret;\r
 }\r
 \r
   return ret;\r
 }\r
+\r
+int list_nssm_services() {\r
+  /* Open service manager. */\r
+  SC_HANDLE services = open_service_manager(SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);\r
+  if (! services) {\r
+    print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);\r
+    return 1;\r
+  }\r
+\r
+  unsigned long bufsize, required, count, i;\r
+  unsigned long resume = 0;\r
+  EnumServicesStatus(services, SERVICE_WIN32, SERVICE_STATE_ALL, 0, 0, &required, &count, &resume);\r
+  unsigned long error = GetLastError();\r
+  if (error != ERROR_MORE_DATA) {\r
+    print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError()));\r
+    return 2;\r
+  }\r
+\r
+  ENUM_SERVICE_STATUS *status = (ENUM_SERVICE_STATUS *) HeapAlloc(GetProcessHeap(), 0, required);\r
+  if (! status) {\r
+    print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("ENUM_SERVICE_STATUS"), _T("list_nssm_services()"));\r
+    return 3;\r
+  }\r
+\r
+  bufsize = required;\r
+  while (true) {\r
+    int ret = EnumServicesStatus(services, SERVICE_WIN32, SERVICE_STATE_ALL, status, bufsize, &required, &count, &resume);\r
+    if (! ret) {\r
+      error = GetLastError();\r
+      if (error != ERROR_MORE_DATA) {\r
+        HeapFree(GetProcessHeap(), 0, status);\r
+        print_message(stderr, NSSM_MESSAGE_ENUMSERVICESSTATUS_FAILED, error_string(GetLastError()));\r
+        return 4;\r
+      }\r
+    }\r
+\r
+    for (i = 0; i < count; i++) {\r
+      /* Try to get the service parameters. */\r
+      nssm_service_t *service = alloc_nssm_service();\r
+      if (! service) {\r
+        HeapFree(GetProcessHeap(), 0, status);\r
+        print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("nssm_service_t"), _T("list_nssm_services()"));\r
+        return 5;\r
+      }\r
+      _sntprintf_s(service->name, _countof(service->name), _TRUNCATE, _T("%s"), status[i].lpServiceName);\r
+\r
+      get_parameters(service, 0);\r
+      /* We manage the service if we have an Application. */\r
+      if (service->exe[0]) _tprintf(_T("%s\n"), service->name);\r
+\r
+      cleanup_nssm_service(service);\r
+    }\r
+\r
+    if (ret) break;\r
+  }\r
+\r
+  HeapFree(GetProcessHeap(), 0, status);\r
+  return 0;\r
+}\r
index b35edcc..3a80751 100644 (file)
--- a/service.h
+++ b/service.h
@@ -156,5 +156,6 @@ int stop_service(nssm_service_t *, unsigned long, bool, bool);
 void CALLBACK end_service(void *, unsigned char);\r
 void throttle_restart(nssm_service_t *);\r
 int await_single_handle(SERVICE_STATUS_HANDLE, SERVICE_STATUS *, HANDLE, TCHAR *, TCHAR *, unsigned long);\r
 void CALLBACK end_service(void *, unsigned char);\r
 void throttle_restart(nssm_service_t *);\r
 int await_single_handle(SERVICE_STATUS_HANDLE, SERVICE_STATUS *, HANDLE, TCHAR *, TCHAR *, unsigned long);\r
+int list_nssm_services();\r
 \r
 #endif\r
 \r
 #endif\r