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.
followed by SetEndOfFile(), allowing it to rotate files\r
which other processes hold open.\r
\r
followed by SetEndOfFile(), allowing it to rotate files\r
which other processes hold open.\r
\r
+ * NSSM now sets the service environment before querying\r
+ parameters from the registry, so paths and arguments\r
+ can reference environment configured in AppEnvironment\r
+ or AppEnvironmentExtra.\r
+\r
Changes since 2.23\r
------------------\r
* NSSM once again calls TerminateProcess() correctly.\r
Changes since 2.23\r
------------------\r
* NSSM once again calls TerminateProcess() correctly.\r
Thanks to Barrett Lewis for suggesting the option to skip terminating the\r
application's child processes.\r
Thanks to Miguel Angel Terrón for suggesting copy/truncate rotation.\r
Thanks to Barrett Lewis for suggesting the option to skip terminating the\r
application's child processes.\r
Thanks to Miguel Angel Terrón for suggesting copy/truncate rotation.\r
+Thanks to Yuriy Lesiuk for suggesting setting the environment before querying\r
+the registry for parameters.\r
/* Don't expand parameters when retrieving for the GUI. */\r
bool expand = si ? true : false;\r
\r
/* Don't expand parameters when retrieving for the GUI. */\r
bool expand = si ? true : false;\r
\r
+ /* Try to get environment variables - may fail */\r
+ get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen);\r
+ /* Environment variables to add to existing rather than replace - may fail. */\r
+ get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen);\r
+\r
+ /* Set environment if we are starting the service. */\r
+ if (si) set_service_environment(service);\r
+\r
/* Try to get executable file - MUST succeed */\r
if (get_string(key, NSSM_REG_EXE, service->exe, sizeof(service->exe), expand, false, true)) {\r
RegCloseKey(key);\r
/* Try to get executable file - MUST succeed */\r
if (get_string(key, NSSM_REG_EXE, service->exe, sizeof(service->exe), expand, false, true)) {\r
RegCloseKey(key);\r
- /* Try to get environment variables - may fail */\r
- get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen);\r
- /* Environment variables to add to existing rather than replace - may fail. */\r
- get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen);\r
-\r
/* Try to get priority - may fail. */\r
unsigned long priority;\r
if (get_number(key, NSSM_REG_PRIORITY, &priority, false) == 1) {\r
/* Try to get priority - may fail. */\r
unsigned long priority;\r
if (get_number(key, NSSM_REG_PRIORITY, &priority, false) == 1) {\r
return ret * 1000;\r
}\r
\r
return ret * 1000;\r
}\r
\r
+void set_service_environment(nssm_service_t *service) {\r
+ if (! service) return;\r
+ if (service->env) duplicate_environment(service->env);\r
+ if (service->env_extra) set_environment_block(service->env_extra);\r
+}\r
+\r
+void unset_service_environment(nssm_service_t *service) {\r
+ if (! service) return;\r
+ duplicate_environment_strings(service->initial_env);\r
+}\r
+\r
/*\r
Wrapper to be called in a new thread so that we can acknowledge a STOP\r
control immediately.\r
/*\r
Wrapper to be called in a new thread so that we can acknowledge a STOP\r
control immediately.\r
int ret = get_parameters(service, &si);\r
if (ret) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service->name, 0);\r
int ret = get_parameters(service, &si);\r
if (ret) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service->name, 0);\r
+ unset_service_environment(service);\r
return stop_service(service, 2, true, true);\r
}\r
\r
return stop_service(service, 2, true, true);\r
}\r
\r
TCHAR cmd[CMD_LENGTH];\r
if (_sntprintf_s(cmd, _countof(cmd), _TRUNCATE, _T("\"%s\" %s"), service->exe, service->flags) < 0) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("command line"), _T("start_service"), 0);\r
TCHAR cmd[CMD_LENGTH];\r
if (_sntprintf_s(cmd, _countof(cmd), _TRUNCATE, _T("\"%s\" %s"), service->exe, service->flags) < 0) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("command line"), _T("start_service"), 0);\r
+ unset_service_environment(service);\r
return stop_service(service, 2, true, true);\r
}\r
\r
throttle_restart(service);\r
\r
return stop_service(service, 2, true, true);\r
}\r
\r
throttle_restart(service);\r
\r
- /* Set the environment. */\r
- if (service->env) duplicate_environment(service->env);\r
- if (service->env_extra) set_environment_block(service->env_extra);\r
-\r
service->status.dwCurrentState = SERVICE_START_PENDING;\r
service->status.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;\r
SetServiceStatus(service->status_handle, &service->status);\r
service->status.dwCurrentState = SERVICE_START_PENDING;\r
service->status.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;\r
SetServiceStatus(service->status_handle, &service->status);\r
TCHAR code[16];\r
_sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), NSSM_HOOK_STATUS_ABORT);\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PRESTART_HOOK_ABORT, NSSM_HOOK_EVENT_START, NSSM_HOOK_ACTION_PRE, service->name, code, 0);\r
TCHAR code[16];\r
_sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), NSSM_HOOK_STATUS_ABORT);\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PRESTART_HOOK_ABORT, NSSM_HOOK_EVENT_START, NSSM_HOOK_ACTION_PRE, service->name, code, 0);\r
- duplicate_environment_strings(service->initial_env);\r
+ unset_service_environment(service);\r
return stop_service(service, 5, true, true);\r
}\r
\r
return stop_service(service, 5, true, true);\r
}\r
\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0);\r
if (! service->no_console) FreeConsole();\r
close_output_handles(&si);\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0);\r
if (! service->no_console) FreeConsole();\r
close_output_handles(&si);\r
- duplicate_environment_strings(service->initial_env);\r
+ unset_service_environment(service);\r
return stop_service(service, 4, true, true);\r
}\r
\r
return stop_service(service, 4, true, true);\r
}\r
\r
unsigned long error = GetLastError();\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service->name, service->exe, error_string(error), 0);\r
close_output_handles(&si);\r
unsigned long error = GetLastError();\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service->name, service->exe, error_string(error), 0);\r
close_output_handles(&si);\r
- duplicate_environment_strings(service->initial_env);\r
+ unset_service_environment(service);\r
return stop_service(service, exitcode, true, true);\r
}\r
service->start_count++;\r
return stop_service(service, exitcode, true, true);\r
}\r
service->start_count++;\r
}\r
\r
/* Restore our environment. */\r
}\r
\r
/* Restore our environment. */\r
- duplicate_environment_strings(service->initial_env);\r
+ unset_service_environment(service);\r
\r
/*\r
Wait for a clean startup before changing the service status to RUNNING\r
\r
/*\r
Wait for a clean startup before changing the service status to RUNNING\r
int get_service_description(const TCHAR *, SC_HANDLE, unsigned long, TCHAR *);\r
int get_service_startup(const TCHAR *, SC_HANDLE, const QUERY_SERVICE_CONFIG *, unsigned long *);\r
int get_service_username(const TCHAR *, const QUERY_SERVICE_CONFIG *, TCHAR **, size_t *);\r
int get_service_description(const TCHAR *, SC_HANDLE, unsigned long, TCHAR *);\r
int get_service_startup(const TCHAR *, SC_HANDLE, const QUERY_SERVICE_CONFIG *, unsigned long *);\r
int get_service_username(const TCHAR *, const QUERY_SERVICE_CONFIG *, TCHAR **, size_t *);\r
+int set_service_environment(nssm_service_t *);\r
+int unset_service_environment(nssm_service_t *);\r
int pre_install_service(int, TCHAR **);\r
int pre_remove_service(int, TCHAR **);\r
int pre_edit_service(int, TCHAR **);\r
int pre_install_service(int, TCHAR **);\r
int pre_remove_service(int, TCHAR **);\r
int pre_edit_service(int, TCHAR **);\r