Since version 2.22, NSSM can set service display name, description, startup\r
type and log on details.\r
\r
-Since version 2.22, NSSM can edit existing services.\r
+Since version 2.22, NSSM can manage existing services.\r
\r
\r
Usage\r
nssm set <servicename> Type SERVICE_INTERACTIVE_PROCESS\r
\r
\r
+Controlling services using the command line\r
+-------------------------------------------\r
+NSSM offers rudimentary service control features.\r
+\r
+ nssm start <servicename>\r
+\r
+ nssm stop <servicename>\r
+\r
+ nssm status <servicename>\r
+\r
+\r
Removing services using the GUI\r
-------------------------------\r
NSSM can also remove services. Run\r
\r
/* Elevate */\r
if (argc > 1) {\r
- /* Valid commands are install, edit, get, set, reset, unset or remove */\r
+ /*\r
+ Valid commands are:\r
+ start, stop, pause, continue, install, edit, get, set, reset, unset, remove\r
+ */\r
+ if (str_equiv(argv[1], _T("start"))) exit(control_service(0, argc - 2, argv + 2));\r
+ if (str_equiv(argv[1], _T("stop"))) exit(control_service(SERVICE_CONTROL_STOP, argc - 2, argv + 2));\r
+ if (str_equiv(argv[1], _T("pause"))) exit(control_service(SERVICE_CONTROL_PAUSE, argc - 2, argv + 2));\r
+ if (str_equiv(argv[1], _T("continue"))) exit(control_service(SERVICE_CONTROL_CONTINUE, argc - 2, argv + 2));\r
+ if (str_equiv(argv[1], _T("status"))) exit(control_service(SERVICE_CONTROL_INTERROGATE, argc - 2, argv + 2));\r
if (str_equiv(argv[1], _T("install"))) {\r
if (! is_admin) {\r
print_message(stderr, NSSM_MESSAGE_NOT_ADMINISTRATOR_CANNOT_INSTALL);\r
return 0;\r
}\r
\r
+/* Control a service. */\r
+int control_service(unsigned long control, int argc, TCHAR **argv) {\r
+ if (argc < 1) return usage(1);\r
+ TCHAR *service_name = argv[0];\r
+\r
+ SC_HANDLE services = open_service_manager();\r
+ if (! services) {\r
+ print_message(stderr, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);\r
+ return 2;\r
+ }\r
+\r
+ SC_HANDLE service_handle = OpenService(services, service_name, SC_MANAGER_ALL_ACCESS);\r
+ if (! service_handle) {\r
+ print_message(stderr, NSSM_MESSAGE_OPENSERVICE_FAILED);\r
+ CloseServiceHandle(services);\r
+ return 3;\r
+ }\r
+\r
+ int ret;\r
+ unsigned long error;\r
+ SERVICE_STATUS service_status;\r
+ if (control == 0) {\r
+ ret = StartService(service_handle, (unsigned long) argc, (const TCHAR **) argv);\r
+ error = GetLastError();\r
+ CloseHandle(service_handle);\r
+ CloseServiceHandle(services);\r
+\r
+ if (ret) {\r
+ _tprintf(_T("%s: %s"), canonical_name, error_string(error));\r
+ return 0;\r
+ }\r
+ else {\r
+ _ftprintf(stderr, _T("%s: %s"), canonical_name, error_string(error));\r
+ return 1;\r
+ }\r
+ }\r
+ else if (control == SERVICE_CONTROL_INTERROGATE) {\r
+ /*\r
+ We could actually send an INTERROGATE control but that won't return\r
+ any information if the service is stopped and we don't care about\r
+ the extra details it might give us in any case. So we'll fake it.\r
+ */\r
+ ret = QueryServiceStatus(service_handle, &service_status);\r
+ error = GetLastError();\r
+\r
+ if (ret) {\r
+ switch (service_status.dwCurrentState) {\r
+ case SERVICE_STOPPED: _tprintf(_T("SERVICE_STOPPED\n")); break;\r
+ case SERVICE_START_PENDING: _tprintf(_T("SERVICE_START_PENDING\n")); break;\r
+ case SERVICE_STOP_PENDING: _tprintf(_T("SERVICE_STOP_PENDING\n")); break;\r
+ case SERVICE_RUNNING: _tprintf(_T("SERVICE_RUNNING\n")); break;\r
+ case SERVICE_CONTINUE_PENDING: _tprintf(_T("SERVICE_CONTINUE_PENDING\n")); break;\r
+ case SERVICE_PAUSE_PENDING: _tprintf(_T("SERVICE_PAUSE_PENDING\n")); break;\r
+ case SERVICE_PAUSED: _tprintf(_T("SERVICE_PAUSED\n")); break;\r
+ default: _tprintf(_T("?\n")); return 1;\r
+ }\r
+ return 0;\r
+ }\r
+ else {\r
+ _ftprintf(stderr, _T("%s: %s\n"), service_name, error_string(error));\r
+ return 1;\r
+ }\r
+ }\r
+ else {\r
+ ret = ControlService(service_handle, control, &service_status);\r
+ error = GetLastError();\r
+ CloseHandle(service_handle);\r
+ CloseServiceHandle(services);\r
+\r
+ if (ret) {\r
+ _tprintf(_T("%s: %s"), canonical_name, error_string(error));\r
+ return 0;\r
+ }\r
+ else {\r
+ _ftprintf(stderr, _T("%s: %s"), canonical_name, error_string(error));\r
+ return 1;\r
+ }\r
+ }\r
+}\r
+\r
/* Remove the service */\r
int remove_service(nssm_service_t *service) {\r
if (! service) return 1;\r