* Unqualified path names are now relative to the
application startup directory when redirecting I/O.
+ * NSSM can now set the service display name, description
+ and startup type.
+
Changes since 2.20
------------------
* Services installed from the GUI no longer have incorrect
\r
Since version 2.22, NSSM can rotate existing output files when redirecting I/O.\r
\r
+Since version 2.22, NSSM can set service display name, description and startup\r
+type.\r
+\r
\r
Usage\r
-----\r
#include "nssm.h"\r
\r
-static enum { NSSM_TAB_APPLICATION, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ROTATION, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };\r
+static enum { NSSM_TAB_APPLICATION, NSSM_TAB_DETAILS, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ROTATION, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };\r
static HWND tablist[NSSM_NUM_TABS];\r
static int selected_tab;\r
\r
}\r
}\r
\r
+ /* Get details. */\r
+ if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME), WM_GETTEXTLENGTH, 0, 0)) {\r
+ if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname, _countof(service->displayname))) {\r
+ popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DISPLAYNAME);\r
+ return 5;\r
+ }\r
+ }\r
+\r
+ if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION), WM_GETTEXTLENGTH, 0, 0)) {\r
+ if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description, _countof(service->description))) {\r
+ popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DESCRIPTION);\r
+ return 5;\r
+ }\r
+ }\r
+\r
+ HWND combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);\r
+ service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);\r
+ if (service->startup == CB_ERR) service->startup = 0;\r
+\r
/* Get stop method stuff. */\r
check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);\r
check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);\r
\r
/* Get exit action stuff. */\r
check_method_timeout(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);\r
- HWND combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);\r
+ combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);\r
service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);\r
if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;\r
\r
tablist[NSSM_TAB_APPLICATION] = CreateDialog(0, MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);\r
ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);\r
\r
+ /* Details tab. */\r
+ tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);\r
+ tab.cchTextMax = (int) _tcslen(tab.pszText);\r
+ SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);\r
+ tablist[NSSM_TAB_DETAILS] = CreateDialog(0, MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);\r
+ ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);\r
+\r
+ /* Set defaults. */\r
+ combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);\r
+ SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));\r
+ SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));\r
+ SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));\r
+ SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));\r
+ SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);\r
+\r
/* Shutdown tab. */\r
tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);\r
tab.cchTextMax = (int) _tcslen(tab.pszText);\r
Nessuna opzione valida specificata!
.
+MessageId = +1
+SymbolicName = NSSM_GUI_INVALID_DISPLAYNAME
+Severity = Informational
+Language = English
+Invalid displayname!
+.
+Language = French
+Invalid displayname!
+.
+Language = Italian
+Invalid displayname!
+.
+
+MessageId = +1
+SymbolicName = NSSM_GUI_INVALID_DESCRIPTION
+Severity = Informational
+Language = English
+Invalid description!
+.
+Language = French
+Invalid description!
+.
+Language = Italian
+Invalid description!
+.
+
MessageId = +1
SymbolicName = NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH
Severity = Informational
Applicazione%0
.
+MessageId = +1
+SymbolicName = NSSM_GUI_TAB_DETAILS
+Severity = Informational
+Language = English
+Details%0
+.
+Language = French
+Details%0
+.
+Language = Italian
+Details%0
+.
+
MessageId = +1
SymbolicName = NSSM_GUI_TAB_SHUTDOWN
Severity = Informational
Ambiente%0
.
+MessageId = +1
+SymbolicName = NSSM_GUI_STARTUP_AUTOMATIC
+Severity = Informational
+Language = English
+Automatic%0
+.
+Language = French
+Automatic%0
+.
+Language = Italian
+Automatic%0
+.
+
+MessageId = +1
+SymbolicName = NSSM_GUI_STARTUP_DELAYED
+Severity = Informational
+Language = English
+Automatic (Delayed Start)%0
+.
+Language = French
+Automatic (Delayed Start)%0
+.
+Language = Italian
+Automatic (Delayed Start)%0
+.
+
+MessageId = +1
+SymbolicName = NSSM_GUI_STARTUP_MANUAL
+Severity = Informational
+Language = English
+Manual%0
+.
+Language = French
+Manual%0
+.
+Language = Italian
+Manual%0
+.
+
+MessageId = +1
+SymbolicName = NSSM_GUI_STARTUP_DISABLED
+Severity = Informational
+Language = English
+Disabled%0
+.
+Language = French
+Disabled%0
+.
+Language = Italian
+Disabled%0
+.
+
MessageId = +1
SymbolicName = NSSM_GUI_EXIT_RESTART
Severity = Informational
.
MessageId = +1
-SymbolicName = NSSM_EVENT_CHANGESERVICECONFIG2_FAILED
+SymbolicName = NSSM_EVENT_SERVICE_CONFIG_FAILURE_ACTIONS_FAILED
Severity = Informational
Language = English
Error configuring service failure actions for service %1. The service will not be subject to recovery actions if it exits gracefully with a non-zero exit code.
%3 failed for file %4:
%5
.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_SERVICE_CONFIG_DESCRIPTION_FAILED
+Severity = Informational
+Language = English
+Error setting description for service %1.
+ChangeServiceConfig2() failed:
+%2
+.
+Language = French
+Error setting description for service %1.
+ChangeServiceConfig2() failed:
+%2
+.
+Language = Italian
+Error setting description for service %1.
+ChangeServiceConfig2() failed:
+%2
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_SERVICE_CONFIG_DELAYED_AUTO_START_INFO_FAILED
+Severity = Informational
+Language = English
+Error configuring delayed startup for service %1. The service will start automatically.
+ChangeServiceConfig2() failed:
+%2
+.
+Language = French
+Error configuring delayed startup for service %1. The service will start automatically.
+ChangeServiceConfig2() failed:
+%2
+.
+Language = Italian
+Error configuring delayed startup for service %1. The service will start automatically.
+ChangeServiceConfig2() failed:
+%2
+.
#define NSSM_STOP_METHOD_THREADS (1 << 2)\r
#define NSSM_STOP_METHOD_TERMINATE (1 << 3)\r
\r
+/* Startup types. */\r
+#define NSSM_STARTUP_AUTOMATIC 0\r
+#define NSSM_STARTUP_DELAYED 1\r
+#define NSSM_STARTUP_MANUAL 2\r
+#define NSSM_STARTUP_DISABLED 3\r
+\r
/* Exit actions. */\r
#define NSSM_EXIT_RESTART 0\r
#define NSSM_EXIT_IGNORE 1\r
\r
\r
\r
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r
+IDD_DETAILS DIALOG 9, 20, 261, 75\r
+STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILD | DS_CONTROL\r
+FONT 8, "MS Sans Serif"\r
+{\r
+ GROUPBOX "Details", IDC_STATIC, 7, 7, 251, 68\r
+ LTEXT "Display name:", IDC_STATIC, 13, 18, 45, 8, SS_LEFT\r
+ EDITTEXT IDC_DISPLAYNAME, 70, 16, 184, 12, ES_AUTOHSCROLL\r
+ LTEXT "Description:", IDC_STATIC, 13, 34, 38, 8, SS_LEFT\r
+ EDITTEXT IDC_DESCRIPTION, 70, 32, 184, 22, ES_AUTOHSCROLL, WS_EX_ACCEPTFILES\r
+ LTEXT "Startup type:", IDC_STATIC, 13, 60, 41, 8, SS_LEFT\r
+ COMBOBOX IDC_STARTUP, 70, 58, 100, 120, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_TABSTOP\r
+}\r
+\r
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r
IDD_SHUTDOWN DIALOG 9, 20, 261, 75\r
STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILD | DS_CONTROL\r
#define IDD_INSTALL 102\r
#define IDD_REMOVE 103\r
#define IDD_APPLICATION 104\r
-#define IDD_IO 105\r
-#define IDD_ROTATION 106\r
-#define IDD_APPEXIT 107\r
-#define IDD_SHUTDOWN 108\r
-#define IDD_ENVIRONMENT 109\r
+#define IDD_DETAILS 105\r
+#define IDD_IO 106\r
+#define IDD_ROTATION 107\r
+#define IDD_APPEXIT 108\r
+#define IDD_SHUTDOWN 109\r
+#define IDD_ENVIRONMENT 110\r
#define IDC_PATH 1000\r
#define IDC_TAB1 1001\r
#define IDC_CANCEL 1002\r
#define IDC_ROTATE_SECONDS 1030\r
#define IDC_ROTATE_BYTES_LOW_ENABLED 1031\r
#define IDC_ROTATE_BYTES_LOW 1032\r
+#define IDC_DISPLAYNAME 1033\r
+#define IDC_DESCRIPTION 1034\r
+#define IDC_STARTUP 1035\r
\r
// Next default values for new objects\r
// \r
#ifdef APSTUDIO_INVOKED\r
#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE 110\r
+#define _APS_NEXT_RESOURCE_VALUE 111\r
#define _APS_NEXT_COMMAND_VALUE 40001\r
-#define _APS_NEXT_CONTROL_VALUE 1033\r
+#define _APS_NEXT_CONTROL_VALUE 1036\r
#define _APS_NEXT_SYMED_VALUE 101\r
#endif\r
#endif\r
TCHAR command[MAX_PATH];\r
GetModuleFileName(0, command, _countof(command));\r
\r
+ /* Startup type. */\r
+ unsigned long startup;\r
+ switch (service->startup) {\r
+ case NSSM_STARTUP_MANUAL: startup = SERVICE_DEMAND_START; break;\r
+ case NSSM_STARTUP_DISABLED: startup = SERVICE_DISABLED; break;\r
+ default: startup = SERVICE_AUTO_START;\r
+ }\r
+\r
+ /* Display name. */\r
+ if (! service->displayname[0]) _sntprintf_s(service->displayname, _countof(service->displayname), _TRUNCATE, _T("%s"), service->name);\r
+\r
/* Create the service */\r
- service->handle = CreateService(services, service->name, service->name, SC_MANAGER_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, command, 0, 0, 0, 0, 0);\r
+ service->handle = CreateService(services, service->name, service->displayname, SC_MANAGER_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, startup, SERVICE_ERROR_NORMAL, command, 0, 0, 0, 0, 0);\r
if (! service->handle) {\r
print_message(stderr, NSSM_MESSAGE_CREATESERVICE_FAILED);\r
CloseServiceHandle(services);\r
return 5;\r
}\r
\r
+ if (service->description[0]) {\r
+ SERVICE_DESCRIPTION description;\r
+ ZeroMemory(&description, sizeof(description));\r
+ description.lpDescription = service->description;\r
+ if (! ChangeServiceConfig2(service->handle, SERVICE_CONFIG_DESCRIPTION, &description)) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_DESCRIPTION_FAILED, service->name, error_string(GetLastError()), 0);\r
+ }\r
+ }\r
+\r
+ if (service->startup == NSSM_STARTUP_DELAYED) {\r
+ SERVICE_DELAYED_AUTO_START_INFO delayed;\r
+ ZeroMemory(&delayed, sizeof(delayed));\r
+ delayed.fDelayedAutostart = 1;\r
+ /* Delayed startup isn't supported until Vista. */\r
+ if (! ChangeServiceConfig2(service->handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &delayed)) {\r
+ unsigned long error = GetLastError();\r
+ /* Pre-Vista we expect to fail with ERROR_INVALID_LEVEL */\r
+ if (error != ERROR_INVALID_LEVEL) {\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_DELAYED_AUTO_START_INFO_FAILED, service->name, error_string(error), 0);\r
+ }\r
+ }\r
+ }\r
+\r
/* Now we need to put the parameters into the registry */\r
if (create_parameters(service)) {\r
print_message(stderr, NSSM_MESSAGE_CREATE_PARAMETERS_FAILED);\r
unsigned long error = GetLastError();\r
/* Pre-Vista we expect to fail with ERROR_INVALID_LEVEL */\r
if (error != ERROR_INVALID_LEVEL) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CHANGESERVICECONFIG2_FAILED, service->name, error_string(error), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_FAILURE_ACTIONS_FAILED, service->name, error_string(error), 0);\r
}\r
}\r
}\r
#define KEY_LENGTH 255\r
#define VALUE_LENGTH 16383\r
#define SERVICE_NAME_LENGTH KEY_LENGTH - 55\r
+#define SERVICE_DISPLAYNAME_LENGTH 256\r
\r
#define ACTION_LEN 16\r
\r
typedef struct {\r
TCHAR name[SERVICE_NAME_LENGTH];\r
+ TCHAR displayname[SERVICE_DISPLAYNAME_LENGTH];\r
+ TCHAR description[VALUE_LENGTH];\r
+ unsigned long startup;\r
TCHAR exe[EXE_LENGTH];\r
TCHAR flags[VALUE_LENGTH];\r
TCHAR dir[MAX_PATH];\r