Browse Source

Set the environment before querying the registry.

Handle AppEnvironment and AppEnvironmentExtra before querying registry
parameters.  Doing so allows paths and arguments passed to the service
to reference such environment variables.

Thanks Yuriy Lesiuk.
Iain Patterson 6 years ago
parent
commit
32a1d0fab4
5 changed files with 34 additions and 13 deletions
  1. 5 0
      ChangeLog.txt
  2. 2 0
      README.txt
  3. 8 5
      registry.cpp
  4. 17 8
      service.cpp
  5. 2 0
      service.h

+ 5 - 0
ChangeLog.txt

@@ -9,6 +9,11 @@ Changes since 2.24
     followed by SetEndOfFile(), allowing it to rotate files
     which other processes hold open.
 
+  * NSSM now sets the service environment before querying
+    parameters from the registry, so paths and arguments
+    can reference environment configured in AppEnvironment
+    or AppEnvironmentExtra.
+
 Changes since 2.23
 ------------------
   * NSSM once again calls TerminateProcess() correctly.

+ 2 - 0
README.txt

@@ -820,6 +820,8 @@ Thanks to Sam Townsend for noticing a regression with TerminateProcess().
 Thanks to Barrett Lewis for suggesting the option to skip terminating the
 application's child processes.
 Thanks to Miguel Angel Terrón for suggesting copy/truncate rotation.
+Thanks to Yuriy Lesiuk for suggesting setting the environment before querying
+the registry for parameters.
 
 Licence
 -------

+ 8 - 5
registry.cpp

@@ -531,6 +531,14 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) {
   /* Don't expand parameters when retrieving for the GUI. */
   bool expand = si ? true : false;
 
+  /* Try to get environment variables - may fail */
+  get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen);
+  /* Environment variables to add to existing rather than replace - may fail. */
+  get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen);
+
+  /* Set environment if we are starting the service. */
+  if (si) set_service_environment(service);
+
   /* Try to get executable file - MUST succeed */
   if (get_string(key, NSSM_REG_EXE, service->exe, sizeof(service->exe), expand, false, true)) {
     RegCloseKey(key);
@@ -585,11 +593,6 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) {
     }
   }
 
-  /* Try to get environment variables - may fail */
-  get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen);
-  /* Environment variables to add to existing rather than replace - may fail. */
-  get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen);
-
   /* Try to get priority - may fail. */
   unsigned long priority;
   if (get_number(key, NSSM_REG_PRIORITY, &priority, false) == 1) {

+ 17 - 8
service.cpp

@@ -273,6 +273,17 @@ static inline unsigned long throttle_milliseconds(unsigned long throttle) {
   return ret * 1000;
 }
 
+void set_service_environment(nssm_service_t *service) {
+  if (! service) return;
+  if (service->env) duplicate_environment(service->env);
+  if (service->env_extra) set_environment_block(service->env_extra);
+}
+
+void unset_service_environment(nssm_service_t *service) {
+  if (! service) return;
+  duplicate_environment_strings(service->initial_env);
+}
+
 /*
   Wrapper to be called in a new thread so that we can acknowledge a STOP
   control immediately.
@@ -1684,6 +1695,7 @@ int start_service(nssm_service_t *service) {
   int ret = get_parameters(service, &si);
   if (ret) {
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service->name, 0);
+    unset_service_environment(service);
     return stop_service(service, 2, true, true);
   }
 
@@ -1691,15 +1703,12 @@ int start_service(nssm_service_t *service) {
   TCHAR cmd[CMD_LENGTH];
   if (_sntprintf_s(cmd, _countof(cmd), _TRUNCATE, _T("\"%s\" %s"), service->exe, service->flags) < 0) {
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("command line"), _T("start_service"), 0);
+    unset_service_environment(service);
     return stop_service(service, 2, true, true);
   }
 
   throttle_restart(service);
 
-  /* Set the environment. */
-  if (service->env) duplicate_environment(service->env);
-  if (service->env_extra) set_environment_block(service->env_extra);
-
   service->status.dwCurrentState = SERVICE_START_PENDING;
   service->status.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
   SetServiceStatus(service->status_handle, &service->status);
@@ -1710,7 +1719,7 @@ int start_service(nssm_service_t *service) {
     TCHAR code[16];
     _sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), NSSM_HOOK_STATUS_ABORT);
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PRESTART_HOOK_ABORT, NSSM_HOOK_EVENT_START, NSSM_HOOK_ACTION_PRE, service->name, code, 0);
-    duplicate_environment_strings(service->initial_env);
+    unset_service_environment(service);
     return stop_service(service, 5, true, true);
   }
 
@@ -1721,7 +1730,7 @@ int start_service(nssm_service_t *service) {
       log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0);
       if (! service->no_console) FreeConsole();
       close_output_handles(&si);
-      duplicate_environment_strings(service->initial_env);
+      unset_service_environment(service);
       return stop_service(service, 4, true, true);
     }
 
@@ -1734,7 +1743,7 @@ int start_service(nssm_service_t *service) {
       unsigned long error = GetLastError();
       log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service->name, service->exe, error_string(error), 0);
       close_output_handles(&si);
-      duplicate_environment_strings(service->initial_env);
+      unset_service_environment(service);
       return stop_service(service, exitcode, true, true);
     }
     service->start_count++;
@@ -1778,7 +1787,7 @@ int start_service(nssm_service_t *service) {
   }
 
   /* Restore our environment. */
-  duplicate_environment_strings(service->initial_env);
+  unset_service_environment(service);
 
   /*
     Wait for a clean startup before changing the service status to RUNNING

+ 2 - 0
service.h

@@ -140,6 +140,8 @@ int set_service_description(const TCHAR *, SC_HANDLE, TCHAR *);
 int get_service_description(const TCHAR *, SC_HANDLE, unsigned long, TCHAR *);
 int get_service_startup(const TCHAR *, SC_HANDLE, const QUERY_SERVICE_CONFIG *, unsigned long *);
 int get_service_username(const TCHAR *, const QUERY_SERVICE_CONFIG *, TCHAR **, size_t *);
+int set_service_environment(nssm_service_t *);
+int unset_service_environment(nssm_service_t *);
 int pre_install_service(int, TCHAR **);
 int pre_remove_service(int, TCHAR **);
 int pre_edit_service(int, TCHAR **);