Browse Source

Set service details in the GUI.

The GUI can now set the service display name, description and startup
type.
Iain Patterson 10 năm trước cách đây
mục cha
commit
a02019297d
9 tập tin đã thay đổi với 243 bổ sung12 xóa
  1. 3 0
      ChangeLog.txt
  2. 3 0
      README.txt
  3. 36 2
      gui.cpp
  4. 130 1
      messages.mc
  5. 6 0
      nssm.h
  6. 14 0
      nssm.rc
  7. 11 7
      resource.h
  8. 36 2
      service.cpp
  9. 4 0
      service.h

+ 3 - 0
ChangeLog.txt

@@ -6,6 +6,9 @@ Changes since 2.21
   * 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

+ 3 - 0
README.txt

@@ -55,6 +55,9 @@ AppEnvironment.
 
 Since version 2.22, NSSM can rotate existing output files when redirecting I/O.
 
+Since version 2.22, NSSM can set service display name, description and startup
+type.
+
 
 Usage
 -----

+ 36 - 2
gui.cpp

@@ -1,6 +1,6 @@
 #include "nssm.h"
 
-static enum { NSSM_TAB_APPLICATION, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ROTATION, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };
+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 };
 static HWND tablist[NSSM_NUM_TABS];
 static int selected_tab;
 
@@ -116,6 +116,25 @@ int install(HWND window) {
       }
     }
 
+    /* Get details. */
+    if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME), WM_GETTEXTLENGTH, 0, 0)) {
+      if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname, _countof(service->displayname))) {
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DISPLAYNAME);
+        return 5;
+      }
+    }
+
+    if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION), WM_GETTEXTLENGTH, 0, 0)) {
+      if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description, _countof(service->description))) {
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DESCRIPTION);
+        return 5;
+      }
+    }
+
+    HWND combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
+    service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
+    if (service->startup == CB_ERR) service->startup = 0;
+
     /* Get stop method stuff. */
     check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
     check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
@@ -127,7 +146,7 @@ int install(HWND window) {
 
     /* Get exit action stuff. */
     check_method_timeout(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);
-    HWND combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
+    combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
     service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
     if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;
 
@@ -471,6 +490,21 @@ INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
       tablist[NSSM_TAB_APPLICATION] = CreateDialog(0, MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
       ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);
 
+      /* Details tab. */
+      tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);
+      tab.cchTextMax = (int) _tcslen(tab.pszText);
+      SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);
+      tablist[NSSM_TAB_DETAILS] = CreateDialog(0, MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);
+      ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);
+
+      /* Set defaults. */
+      combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
+      SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));
+      SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));
+      SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));
+      SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
+      SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
+
       /* Shutdown tab. */
       tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
       tab.cchTextMax = (int) _tcslen(tab.pszText);

+ 130 - 1
messages.mc

@@ -296,6 +296,32 @@ Language = Italian
 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
@@ -471,6 +497,19 @@ Language = Italian
 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
@@ -536,6 +575,58 @@ Language = Italian
 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
@@ -1239,7 +1330,7 @@ Il servizio %1 ha ricevuto un messaggio di controllo di servizio sconosciuto %2,
 .
 
 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.
@@ -1578,3 +1669,41 @@ Failed to rotate output file %2 for service %1.
 %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
+.

+ 6 - 0
nssm.h

@@ -55,6 +55,12 @@ void strip_basename(TCHAR *);
 #define NSSM_STOP_METHOD_THREADS (1 << 2)
 #define NSSM_STOP_METHOD_TERMINATE (1 << 3)
 
+/* Startup types. */
+#define NSSM_STARTUP_AUTOMATIC 0
+#define NSSM_STARTUP_DELAYED 1
+#define NSSM_STARTUP_MANUAL 2
+#define NSSM_STARTUP_DISABLED 3
+
 /* Exit actions. */
 #define NSSM_EXIT_RESTART 0
 #define NSSM_EXIT_IGNORE 1

+ 14 - 0
nssm.rc

@@ -104,6 +104,20 @@ FONT 8, "MS Sans Serif"
 
 
 
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_DETAILS DIALOG 9, 20, 261, 75
+STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILD | DS_CONTROL
+FONT 8, "MS Sans Serif"
+{
+    GROUPBOX        "Details", IDC_STATIC, 7, 7, 251, 68
+    LTEXT           "Display name:", IDC_STATIC, 13, 18, 45, 8, SS_LEFT
+    EDITTEXT        IDC_DISPLAYNAME, 70, 16, 184, 12, ES_AUTOHSCROLL
+    LTEXT           "Description:", IDC_STATIC, 13, 34, 38, 8, SS_LEFT
+    EDITTEXT        IDC_DESCRIPTION, 70, 32, 184, 22, ES_AUTOHSCROLL, WS_EX_ACCEPTFILES
+    LTEXT           "Startup type:", IDC_STATIC, 13, 60, 41, 8, SS_LEFT
+    COMBOBOX        IDC_STARTUP, 70, 58, 100, 120, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_TABSTOP
+}
+
 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
 IDD_SHUTDOWN DIALOG 9, 20, 261, 75
 STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILD | DS_CONTROL

+ 11 - 7
resource.h

@@ -7,11 +7,12 @@
 #define IDD_INSTALL                   102
 #define IDD_REMOVE            103
 #define IDD_APPLICATION            104
-#define IDD_IO            105
-#define IDD_ROTATION        106
-#define IDD_APPEXIT            107
-#define IDD_SHUTDOWN            108
-#define IDD_ENVIRONMENT            109
+#define IDD_DETAILS            105
+#define IDD_IO            106
+#define IDD_ROTATION        107
+#define IDD_APPEXIT            108
+#define IDD_SHUTDOWN            109
+#define IDD_ENVIRONMENT            110
 #define IDC_PATH                        1000
 #define IDC_TAB1                        1001
 #define IDC_CANCEL                      1002
@@ -44,14 +45,17 @@
 #define IDC_ROTATE_SECONDS              1030
 #define IDC_ROTATE_BYTES_LOW_ENABLED    1031
 #define IDC_ROTATE_BYTES_LOW            1032
+#define IDC_DISPLAYNAME                 1033
+#define IDC_DESCRIPTION                 1034
+#define IDC_STARTUP                     1035
 
 // Next default values for new objects
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        110
+#define _APS_NEXT_RESOURCE_VALUE        111
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1033
+#define _APS_NEXT_CONTROL_VALUE         1036
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

+ 36 - 2
service.cpp

@@ -145,14 +145,48 @@ int install_service(nssm_service_t *service) {
   TCHAR command[MAX_PATH];
   GetModuleFileName(0, command, _countof(command));
 
+  /* Startup type. */
+  unsigned long startup;
+  switch (service->startup) {
+    case NSSM_STARTUP_MANUAL: startup = SERVICE_DEMAND_START; break;
+    case NSSM_STARTUP_DISABLED: startup = SERVICE_DISABLED; break;
+    default: startup = SERVICE_AUTO_START;
+  }
+
+  /* Display name. */
+  if (! service->displayname[0]) _sntprintf_s(service->displayname, _countof(service->displayname), _TRUNCATE, _T("%s"), service->name);
+
   /* Create the service */
-  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);
+  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);
   if (! service->handle) {
     print_message(stderr, NSSM_MESSAGE_CREATESERVICE_FAILED);
     CloseServiceHandle(services);
     return 5;
   }
 
+  if (service->description[0]) {
+    SERVICE_DESCRIPTION description;
+    ZeroMemory(&description, sizeof(description));
+    description.lpDescription = service->description;
+    if (! ChangeServiceConfig2(service->handle, SERVICE_CONFIG_DESCRIPTION, &description)) {
+      log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_DESCRIPTION_FAILED, service->name, error_string(GetLastError()), 0);
+    }
+  }
+
+  if (service->startup == NSSM_STARTUP_DELAYED) {
+    SERVICE_DELAYED_AUTO_START_INFO delayed;
+    ZeroMemory(&delayed, sizeof(delayed));
+    delayed.fDelayedAutostart = 1;
+    /* Delayed startup isn't supported until Vista. */
+    if (! ChangeServiceConfig2(service->handle, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &delayed)) {
+      unsigned long error = GetLastError();
+      /* Pre-Vista we expect to fail with ERROR_INVALID_LEVEL */
+      if (error != ERROR_INVALID_LEVEL) {
+        log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_DELAYED_AUTO_START_INFO_FAILED, service->name, error_string(error), 0);
+      }
+    }
+  }
+
   /* Now we need to put the parameters into the registry */
   if (create_parameters(service)) {
     print_message(stderr, NSSM_MESSAGE_CREATE_PARAMETERS_FAILED);
@@ -282,7 +316,7 @@ void set_service_recovery(nssm_service_t *service) {
     unsigned long error = GetLastError();
     /* Pre-Vista we expect to fail with ERROR_INVALID_LEVEL */
     if (error != ERROR_INVALID_LEVEL) {
-      log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CHANGESERVICECONFIG2_FAILED, service->name, error_string(error), 0);
+      log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SERVICE_CONFIG_FAILURE_ACTIONS_FAILED, service->name, error_string(error), 0);
     }
   }
 }

+ 4 - 0
service.h

@@ -13,11 +13,15 @@
 #define KEY_LENGTH 255
 #define VALUE_LENGTH 16383
 #define SERVICE_NAME_LENGTH KEY_LENGTH - 55
+#define SERVICE_DISPLAYNAME_LENGTH 256
 
 #define ACTION_LEN 16
 
 typedef struct {
   TCHAR name[SERVICE_NAME_LENGTH];
+  TCHAR displayname[SERVICE_DISPLAYNAME_LENGTH];
+  TCHAR description[VALUE_LENGTH];
+  unsigned long startup;
   TCHAR exe[EXE_LENGTH];
   TCHAR flags[VALUE_LENGTH];
   TCHAR dir[MAX_PATH];