Set environment from the GUI at install time.

Added an extra Environment tab to set a newline-separated list of
environment variables to replace or be added to the service environment.

Input is validated by relaunching nssm itself with the proposed
environment set.
master
Iain Patterson 11 years ago
parent 728c4f6eb9
commit 277723e318

@ -1,5 +1,8 @@
Changes since 2.18
-----------------
* Support AppEnvironmentExtra to append to the environment
instead of replacing it.
* The GUI is significantly less sucky.
Changes since 2.17

@ -1,6 +1,6 @@
#include "nssm.h"
static enum { NSSM_TAB_APPLICATION, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_NUM_TABS };
static enum { NSSM_TAB_APPLICATION, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };
static HWND tablist[NSSM_NUM_TABS];
static int selected_tab;
@ -120,7 +120,7 @@ int install(HWND window) {
if (! GetDlgItemText(window, IDC_FLAGS, service->flags, sizeof(service->flags))) {
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);
return 4;
}
}
}
/* Get stop method stuff. */
@ -143,6 +143,80 @@ int install(HWND window) {
check_io("stdin", service->stdin_path, sizeof(service->stdin_path), IDC_STDIN);
check_io("stdout", service->stdout_path, sizeof(service->stdout_path), IDC_STDOUT);
check_io("stderr", service->stderr_path, sizeof(service->stderr_path), IDC_STDERR);
/* Get environment. */
unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
if (envlen) {
char *env = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, envlen + 2);
if (! env) {
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "environment", "install()");
cleanup_nssm_service(service);
return 5;
}
if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
HeapFree(GetProcessHeap(), 0, env);
cleanup_nssm_service(service);
return 5;
}
/* Strip CR and replace LF with NULL. */
unsigned long newlen = 0;
unsigned long i, j;
for (i = 0; i < envlen; i++) if (env[i] != '\r') newlen++;
/* Must end with two NULLs. */
newlen++;
char *newenv = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newlen);
if (! newenv) {
HeapFree(GetProcessHeap(), 0, env);
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "environment", "install()");
cleanup_nssm_service(service);
return 5;
}
for (i = 0, j = 0; i < envlen; i++) {
if (env[i] == '\r') continue;
if (env[i] == '\n') newenv[j] = '\0';
else newenv[j] = env[i];
j++;
}
HeapFree(GetProcessHeap(), 0, env);
env = newenv;
envlen = newlen;
/* Test the environment is valid. */
char path[MAX_PATH];
GetModuleFileName(0, path, sizeof(path));
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
if (! CreateProcess(0, path, 0, 0, 0, CREATE_SUSPENDED, env, 0, &si, &pi)) {
unsigned long error = GetLastError();
if (error == ERROR_INVALID_PARAMETER) {
popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
HeapFree(GetProcessHeap(), 0, env);
envlen = 0;
}
cleanup_nssm_service(service);
return 5;
}
TerminateProcess(pi.hProcess, 0);
if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
service->env = env;
service->envlen = envlen;
}
else {
service->env_extra = env;
service->env_extralen = envlen;
}
}
}
/* See if it works. */
@ -426,6 +500,13 @@ INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
tablist[NSSM_TAB_IO] = CreateDialog(0, MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);
/* Environment tab. */
tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
tab.cchTextMax = (int) strlen(tab.pszText) + 1;
SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
tablist[NSSM_TAB_ENVIRONMENT] = CreateDialog(0, MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
selected_tab = 0;
return 1;

@ -301,6 +301,19 @@ Errore durante la costruzione di ImagePath!\nQesto errore
oppure il mondo sta per finire oppure è accaduto qualcosa di ugualmente grave!
.
MessageId = +1
SymbolicName = NSSM_GUI_INVALID_ENVIRONMENT
Severity = Informational
Language = English
Environment should comprise strings of the form KEY=VALUE.
.
Language = French
L'environnement devrait comprendre des chaînes sous la forme KEY=VALUE.
.
Language = Italian
L'ambiente dovrebbe comprendere stringhe nella forma CHIAVE=VALORE.
.
MessageId = +1
SymbolicName = NSSM_GUI_INSTALL_SERVICE_FAILED
Severity = Informational
@ -485,6 +498,19 @@ Language = Italian
I/O
.
MessageId = +1
SymbolicName = NSSM_GUI_TAB_ENVIRONMENT
Severity = Informational
Language = English
Environment
.
Language = French
Environnement
.
Language = Italian
Ambiente
.
MessageId = +1
SymbolicName = NSSM_GUI_EXIT_RESTART
Severity = Informational

@ -156,6 +156,16 @@ FONT 8, "MS Sans Serif"
DEFPUSHBUTTON "...", IDC_BROWSE_STDERR, 239, 47, 15, 14
}
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_ENVIRONMENT DIALOG 9, 20, 261, 75
STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILD | DS_CONTROL
FONT 8, "MS Sans Serif"
{
GROUPBOX "Environment variables", IDC_STATIC, 7, 7, 251, 68
EDITTEXT IDC_ENVIRONMENT, 13, 18, 238, 36, ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN
AUTOCHECKBOX "Replace default environment (srvany compatible)", IDC_ENVIRONMENT_REPLACE, 13, 60, 238, 8
}
/////////////////////////////////////////////////////////////////////////////
//

@ -72,6 +72,18 @@ int create_parameters(nssm_service_t *service) {
if (service->stdout_path[0]) set_expand_string(key, NSSM_REG_STDOUT, service->stdout_path);
if (service->stderr_path[0]) set_expand_string(key, NSSM_REG_STDERR, service->stderr_path);
/* Environment */
if (service->env) {
if (RegSetValueEx(key, NSSM_REG_ENV, 0, REG_MULTI_SZ, (const unsigned char *) service->env, (unsigned long) service->envlen) != ERROR_SUCCESS) {
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_ENV, error_string(GetLastError()), 0);
}
}
if (service->env_extra) {
if (RegSetValueEx(key, NSSM_REG_ENV_EXTRA, 0, REG_MULTI_SZ, (const unsigned char *) service->env_extra, (unsigned long) service->env_extralen) != ERROR_SUCCESS) {
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_ENV_EXTRA, error_string(GetLastError()), 0);
}
}
/* Close registry. */
RegCloseKey(key);

@ -10,6 +10,7 @@
#define IDD_IO 105
#define IDD_APPEXIT 106
#define IDD_SHUTDOWN 107
#define IDD_ENVIRONMENT 108
#define IDC_PATH 1000
#define IDC_TAB1 1001
#define IDC_CANCEL 1002
@ -34,14 +35,16 @@
#define IDC_APPEXIT 1022
#define IDC_DIR 1023
#define IDC_BROWSE_DIR 1024
#define IDC_ENVIRONMENT 1025
#define IDC_ENVIRONMENT_REPLACE 1026
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1024
#define _APS_NEXT_CONTROL_VALUE 1027
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Loading…
Cancel
Save