-Changes since 2.21
-------------------
- * Existing services can now be managed using the GUI
- or on the command line.
-
- * NSSM can now set the priority class and processor
- affinity of the managed application.
-
- * NSSM can now apply an unconditional delay before
- restarting the application.
-
- * NSSM can now optionally rotate existing files when
- redirecting I/O.
-
- * Unqualified path names are now relative to the
- application startup directory when redirecting I/O.
-
- * NSSM can now set the service display name, description,
- startup type and log on details.
-
-Changes since 2.20
-------------------
- * Services installed from the GUI no longer have incorrect
- AppParameters set in the registry.
-
-Changes since 2.19
-------------------
- * Services installed from the commandline without using the
- GUI no longer have incorrect AppStopMethod* registry
- entries set.
-
-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
-------------------
- * Timeouts for each shutdown method can be configured in
- the registry.
-
- * The GUI is slightly less sucky.
-
-Changes since 2.16
-------------------
- * NSSM can now redirect the service's I/O streams to any path
- capable of being opened by CreateFile().
-
- * Allow building on Visual Studio Express.
-
- * Silently ignore INTERROGATE control.
-
- * Try to send Control-C events to console applications when
- shutting them down.
-
-Changes since 2.15
-------------------
- * Fixed case where NSSM could kill unrelated processes when
- shutting down.
-
-Changes since 2.14
-------------------
- * NSSM is now translated into Italian.
-
- * Fixed GUI not allowing paths longer than 256 characters.
-
-Changes since 2.13
-------------------
- * Fixed default GUI language being French not English.
-
-Changes since 2.12
-------------------
- * Fixed failure to run on Windows 2000.
-
-Changes since 2.11
-------------------
- * NSSM is now translated into French.
-
- * Really ensure systems recovery actions can happen.
-
- The change supposedly introduced in v2.4 to allow service recovery
- actions to be activated when the application exits gracefully with
- a non-zero error code didn't actually work.
-
-Changes since 2.10
-------------------
- * Support AppEnvironment for compatibility with srvany.
-
-Changes since 2.9
------------------
- * Fixed failure to compile messages.mc in paths containing spaces.
-
- * Fixed edge case with CreateProcess().
-
- Correctly handle the case where the application executable is under
- a path which contains space and an executable sharing the initial
- part of that path (up to a space) exists.
-
-Changes since 2.8
------------------
- * Fixed failure to run on Windows versions prior to Vista.
-
-Changes since 2.7
------------------
- * Read Application, AppDirectory and AppParameters before each restart so
- a change to any one doesn't require restarting NSSM itself.
-
- * Fixed messages not being sent to the event log correctly in some
- cases.
-
- * Try to handle (strictly incorrect) quotes in AppDirectory.
-
- Windows directories aren't allowed to contain quotes so CreateProcess()
- will fail if the AppDirectory is quoted. Note that it succeeds even if
- Application itself is quoted as the application plus parameters are
- interpreted as a command line.
-
- * Fixed failed to write full arguments to AppParameters when
- installing a service.
-
- * Throttle restarts.
-
- Back off from restarting the application immediately if it starts
- successfully but exits too soon. The default value of "too soon" is
- 1500 milliseconds. This can be configured by adding a DWORD value
- AppThrottle to the registry.
-
- Handle resume messages from the service console to restart the
- application immediately even if it is throttled.
-
- * Try to kill the process tree gracefully.
-
- Before calling TerminateProcess() on all processes assocatiated with
- the monitored application, enumerate all windows and threads and
- post appropriate messages to them. If the application bothers to
- listen for such messages it has a chance to shut itself down gracefully.
-
-Changes since 2.6
------------------
- * Handle missing registry values.
-
- Warn if AppParameters is missing. Warn if AppDirectory is missing or
- unset and choose a fallback directory.
- First try to find the parent directory of the application. If that
- fails, eg because the application path is just "notepad" or something,
- start in the Windows directory.
-
- * Kill process tree when stopping service.
-
- Ensure that all child processes of the monitored application are
- killed when the service stops by recursing through all running
- processes and terminating those whose parent is the application
- or one of its descendents.
-
-Changes since 2.5
------------------
- * Removed incorrect ExpandEnvironmentStrings() error.
-
- A log_event() call was inadvertently left in the code causing an error
- to be set to the eventlog saying that ExpandEnvironmentStrings() had
- failed when it had actually succeeded.
-
-Changes since 2.4
------------------
- * Allow use of REG_EXPAND_SZ values in the registry.
-
- * Don't suicide on exit status 0 by default.
-
- Suiciding when the application exits 0 will cause recovery actions to be
- taken. Usually this is inappropriate. Only suicide if there is an
- explicit AppExit value for 0 in the registry.
-
- Technically such behaviour could be abused to do something like run a
- script after successful completion of a service but in most cases a
- suicide is undesirable when no actual failure occurred.
-
- * Don't hang if startup parameters couldn't be determined.
- Instead, signal that the service entered the STOPPED state.
- Set START_PENDING state prior to actual startup.
-
-Changes since 2.3
------------------
- * Ensure systems recovery actions can happen.
-
- In Windows versions earlier than Vista the service manager would only
- consider a service failed (and hence eligible for recovery action) if
- the service exited without setting its state to SERVICE_STOPPED, even if
- it signalled an error exit code.
- In Vista and later the service manager can be configured to treat a
- graceful shutdown with error code as a failure but this is not the
- default behaviour.
-
- Try to configure the service manager to use the new behaviour when
- starting the service so users who set AppExit to Exit can use recovery
- actions as expected.
-
- Also recognise the new AppExit option Suicide for use on pre-Vista
- systems. When AppExit is Suicide don't stop the service but exit
- inelegantly, which should be seen as a failure.
-
-Changes since 2.2
------------------
- * Send properly formatted messages to the event log.
-
- * Fixed truncation of very long path lengths in the registry.
-
-Changes since 2.1
------------------
- * Decide how to handle application exit.
-
- When the service exits with exit code n look in
- HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppExit\<n>,
- falling back to the unnamed value if no such code is listed. Parse the
- (string) value of this entry as follows:
-
- Restart: Start the application again (NSSM default).
- Ignore: Do nothing (srvany default).
- Exit: Stop the service.
-
-Changes since 2.0
------------------
- * Added support for building a 64-bit executable.
-
- * Added project files for newer versions of Visual Studio.
+Changes since 2.21\r
+------------------\r
+ * Existing services can now be managed using the GUI\r
+ or on the command line.\r
+\r
+ * NSSM can now set the priority class and processor\r
+ affinity of the managed application.\r
+\r
+ * NSSM can now apply an unconditional delay before\r
+ restarting the application.\r
+\r
+ * NSSM can now optionally rotate existing files when\r
+ redirecting I/O.\r
+\r
+ * Unqualified path names are now relative to the\r
+ application startup directory when redirecting I/O.\r
+\r
+ * NSSM can now set the service display name, description,\r
+ startup type and log on details.\r
+\r
+ * All services now receive a standard console window,\r
+ allowing them to read input correctly (if running in\r
+ interactive mode).\r
+\r
+Changes since 2.20\r
+------------------\r
+ * Services installed from the GUI no longer have incorrect\r
+ AppParameters set in the registry.\r
+\r
+Changes since 2.19\r
+------------------\r
+ * Services installed from the commandline without using the\r
+ GUI no longer have incorrect AppStopMethod* registry\r
+ entries set.\r
+\r
+Changes since 2.18\r
+------------------\r
+ * Support AppEnvironmentExtra to append to the environment\r
+ instead of replacing it.\r
+\r
+ * The GUI is significantly less sucky.\r
+\r
+Changes since 2.17\r
+------------------\r
+ * Timeouts for each shutdown method can be configured in\r
+ the registry.\r
+\r
+ * The GUI is slightly less sucky.\r
+\r
+Changes since 2.16\r
+------------------\r
+ * NSSM can now redirect the service's I/O streams to any path\r
+ capable of being opened by CreateFile().\r
+\r
+ * Allow building on Visual Studio Express.\r
+\r
+ * Silently ignore INTERROGATE control.\r
+\r
+ * Try to send Control-C events to console applications when\r
+ shutting them down.\r
+\r
+Changes since 2.15\r
+------------------\r
+ * Fixed case where NSSM could kill unrelated processes when\r
+ shutting down.\r
+\r
+Changes since 2.14\r
+------------------\r
+ * NSSM is now translated into Italian.\r
+\r
+ * Fixed GUI not allowing paths longer than 256 characters.\r
+\r
+Changes since 2.13\r
+------------------\r
+ * Fixed default GUI language being French not English.\r
+\r
+Changes since 2.12\r
+------------------\r
+ * Fixed failure to run on Windows 2000.\r
+\r
+Changes since 2.11\r
+------------------\r
+ * NSSM is now translated into French.\r
+\r
+ * Really ensure systems recovery actions can happen.\r
+\r
+ The change supposedly introduced in v2.4 to allow service recovery\r
+ actions to be activated when the application exits gracefully with\r
+ a non-zero error code didn't actually work.\r
+\r
+Changes since 2.10\r
+------------------\r
+ * Support AppEnvironment for compatibility with srvany.\r
+\r
+Changes since 2.9\r
+-----------------\r
+ * Fixed failure to compile messages.mc in paths containing spaces.\r
+\r
+ * Fixed edge case with CreateProcess().\r
+\r
+ Correctly handle the case where the application executable is under\r
+ a path which contains space and an executable sharing the initial\r
+ part of that path (up to a space) exists.\r
+\r
+Changes since 2.8\r
+-----------------\r
+ * Fixed failure to run on Windows versions prior to Vista.\r
+\r
+Changes since 2.7\r
+-----------------\r
+ * Read Application, AppDirectory and AppParameters before each restart so\r
+ a change to any one doesn't require restarting NSSM itself.\r
+\r
+ * Fixed messages not being sent to the event log correctly in some\r
+ cases.\r
+\r
+ * Try to handle (strictly incorrect) quotes in AppDirectory.\r
+\r
+ Windows directories aren't allowed to contain quotes so CreateProcess()\r
+ will fail if the AppDirectory is quoted. Note that it succeeds even if\r
+ Application itself is quoted as the application plus parameters are\r
+ interpreted as a command line.\r
+\r
+ * Fixed failed to write full arguments to AppParameters when\r
+ installing a service.\r
+\r
+ * Throttle restarts.\r
+\r
+ Back off from restarting the application immediately if it starts\r
+ successfully but exits too soon. The default value of "too soon" is\r
+ 1500 milliseconds. This can be configured by adding a DWORD value\r
+ AppThrottle to the registry.\r
+ \r
+ Handle resume messages from the service console to restart the\r
+ application immediately even if it is throttled.\r
+\r
+ * Try to kill the process tree gracefully.\r
+\r
+ Before calling TerminateProcess() on all processes assocatiated with\r
+ the monitored application, enumerate all windows and threads and\r
+ post appropriate messages to them. If the application bothers to\r
+ listen for such messages it has a chance to shut itself down gracefully.\r
+\r
+Changes since 2.6\r
+-----------------\r
+ * Handle missing registry values.\r
+\r
+ Warn if AppParameters is missing. Warn if AppDirectory is missing or\r
+ unset and choose a fallback directory.\r
+ First try to find the parent directory of the application. If that\r
+ fails, eg because the application path is just "notepad" or something,\r
+ start in the Windows directory.\r
+\r
+ * Kill process tree when stopping service.\r
+\r
+ Ensure that all child processes of the monitored application are\r
+ killed when the service stops by recursing through all running\r
+ processes and terminating those whose parent is the application\r
+ or one of its descendents.\r
+\r
+Changes since 2.5\r
+-----------------\r
+ * Removed incorrect ExpandEnvironmentStrings() error.\r
+\r
+ A log_event() call was inadvertently left in the code causing an error\r
+ to be set to the eventlog saying that ExpandEnvironmentStrings() had\r
+ failed when it had actually succeeded.\r
+\r
+Changes since 2.4\r
+-----------------\r
+ * Allow use of REG_EXPAND_SZ values in the registry.\r
+\r
+ * Don't suicide on exit status 0 by default.\r
+\r
+ Suiciding when the application exits 0 will cause recovery actions to be\r
+ taken. Usually this is inappropriate. Only suicide if there is an\r
+ explicit AppExit value for 0 in the registry.\r
+ \r
+ Technically such behaviour could be abused to do something like run a\r
+ script after successful completion of a service but in most cases a\r
+ suicide is undesirable when no actual failure occurred.\r
+\r
+ * Don't hang if startup parameters couldn't be determined.\r
+ Instead, signal that the service entered the STOPPED state.\r
+ Set START_PENDING state prior to actual startup.\r
+\r
+Changes since 2.3\r
+-----------------\r
+ * Ensure systems recovery actions can happen.\r
+\r
+ In Windows versions earlier than Vista the service manager would only\r
+ consider a service failed (and hence eligible for recovery action) if\r
+ the service exited without setting its state to SERVICE_STOPPED, even if\r
+ it signalled an error exit code.\r
+ In Vista and later the service manager can be configured to treat a\r
+ graceful shutdown with error code as a failure but this is not the\r
+ default behaviour.\r
+\r
+ Try to configure the service manager to use the new behaviour when\r
+ starting the service so users who set AppExit to Exit can use recovery\r
+ actions as expected.\r
+\r
+ Also recognise the new AppExit option Suicide for use on pre-Vista\r
+ systems. When AppExit is Suicide don't stop the service but exit\r
+ inelegantly, which should be seen as a failure.\r
+\r
+Changes since 2.2\r
+-----------------\r
+ * Send properly formatted messages to the event log.\r
+\r
+ * Fixed truncation of very long path lengths in the registry.\r
+\r
+Changes since 2.1\r
+-----------------\r
+ * Decide how to handle application exit.\r
+\r
+ When the service exits with exit code n look in\r
+ HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppExit\<n>,\r
+ falling back to the unnamed value if no such code is listed. Parse the\r
+ (string) value of this entry as follows:\r
+\r
+ Restart: Start the application again (NSSM default).\r
+ Ignore: Do nothing (srvany default).\r
+ Exit: Stop the service.\r
+\r
+Changes since 2.0\r
+-----------------\r
+ * Added support for building a 64-bit executable.\r
+\r
+ * Added project files for newer versions of Visual Studio.\r
timeouts if the application spawns multiple subprocesses.\r
\r
\r
+Console window\r
+--------------\r
+By default, NSSM will create a console window so that applications which\r
+are capable of reading user input can do so - subject to the service being\r
+allowed to interact with the desktop.\r
+\r
+Creation of the console can be suppressed by setting the integer (REG_DWORD)\r
+HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppNoConsole\r
+registry value to 1.\r
+\r
+\r
I/O redirection\r
---------------\r
NSSM can redirect the managed application's I/O to any path capable of being\r
}\r
}\r
\r
+ if (service->no_console) {
+ SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);\r
+ }
+
/* Shutdown tab. */\r
if (! (service->stop_method & NSSM_STOP_METHOD_CONSOLE)) {\r
SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);\r
}\r
}\r
\r
+ if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0;
+ else service->no_console = 1;
+
/* 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
SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS));\r
SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0);\r
\r
+ SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);\r
+
list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);\r
n = num_cpus();\r
SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0);\r
}\r
\r
int get_output_handles(nssm_service_t *service, HKEY key, STARTUPINFO *si) {\r
- bool redirect = false;\r
+ /* Allocate a new console so we get a fresh stdin, stdout and stderr. */\r
+ if (si && ! service->no_console) {\r
+ FreeConsole();\r
+ AllocConsole();\r
+ banner();\r
+\r
+ /* Set a title like "[NSSM] Jenkins" */\r
+ TCHAR displayname[SERVICE_NAME_LENGTH];\r
+ unsigned long len = _countof(displayname);\r
+ SC_HANDLE services = open_service_manager();\r
+ if (services) {\r
+ if (! GetServiceDisplayName(services, service->name, displayname, &len)) ZeroMemory(displayname, sizeof(displayname));\r
+ CloseServiceHandle(services);\r
+ }\r
+ if (! displayname[0]) _sntprintf_s(displayname, _countof(displayname), _TRUNCATE, _T("%s"), service->name);\r
+\r
+ TCHAR title[65535];\r
+ _sntprintf_s(title, _countof(title), _TRUNCATE, _T("[%s] %s"), NSSM, displayname);\r
+ SetConsoleTitle(title);\r
+ }\r
\r
/* stdin */\r
if (get_createfile_parameters(key, NSSM_REG_STDIN, service->stdin_path, &service->stdin_sharing, NSSM_STDIN_SHARING, &service->stdin_disposition, NSSM_STDIN_DISPOSITION, &service->stdin_flags, NSSM_STDIN_FLAGS)) {\r
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEFILE_FAILED, service->stdin_path, error_string(GetLastError()), 0);\r
return 2;\r
}\r
-\r
- redirect = true;\r
}\r
\r
/* stdout */\r
}\r
service->rotate_stdout_online = NSSM_ROTATE_OFFLINE;\r
}\r
-\r
- redirect = true;\r
}\r
\r
/* stderr */\r
}\r
service->rotate_stderr_online = NSSM_ROTATE_OFFLINE;\r
}\r
-\r
- redirect = true;\r
}\r
}\r
\r
- if (! redirect || ! si) return 0;\r
-\r
- /* Allocate a new console so we get a fresh stdin, stdout and stderr. */\r
- FreeConsole();\r
- AllocConsole();\r
-\r
- /* Set a title like "[NSSM] Jenkins" */\r
- TCHAR displayname[SERVICE_NAME_LENGTH];\r
- unsigned long len = _countof(displayname);\r
- SC_HANDLE services = open_service_manager();\r
- if (services) {\r
- if (! GetServiceDisplayName(services, service->name, displayname, &len)) _sntprintf_s(displayname, _countof(displayname), _TRUNCATE, _T("%s"), service->name);\r
- CloseServiceHandle(services);\r
- }\r
-\r
- TCHAR title[65535];\r
- _sntprintf_s(title, _countof(title), _TRUNCATE, _T("[%s] %s\n"), NSSM, displayname);\r
- SetConsoleTitle(title);\r
+ if (! si) return 0;\r
\r
/*\r
We need to set the startup_info flags to make the new handles\r
inheritable by the new process.\r
*/\r
- if (si) si->dwFlags |= STARTF_USESTDHANDLES;\r
+ si->dwFlags |= STARTF_USESTDHANDLES;\r
+\r
+ if (service->no_console) return 0;\r
\r
/* Redirect other handles. */\r
if (! si->hStdInput) {\r
return (int) i;\r
}\r
\r
+static inline void block(unsigned int a, short x, short y, unsigned long n) {\r
+ HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);\r
+ TCHAR s = _T(' ');\r
+\r
+ unsigned long out;\r
+ COORD c = { x, y };\r
+ FillConsoleOutputAttribute(h, a, n, c, &out);\r
+ FillConsoleOutputCharacter(h, s, n, c, &out);\r
+}\r
+\r
+static inline void R(short x, short y, unsigned long n) {\r
+ block(BACKGROUND_RED | BACKGROUND_INTENSITY, x, y, n);\r
+}\r
+\r
+static inline void r(short x, short y, unsigned long n) {\r
+ block(BACKGROUND_RED, x, y, n);\r
+}\r
+\r
+static inline void b(short x, short y, unsigned long n) {\r
+ block(0, x, y, n);\r
+}\r
+\r
+void banner() {\r
+ short y = 0;\r
+\r
+ b(0, y, 80);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(18, y, 5); r(28, y, 4); r(41, y, 4); r(68, y, 1);\r
+ R(6, y, 5); R(19, y, 4); R(29, y, 1); R(32, y, 3); R(42, y, 1); R(45, y, 3); R(52, y, 5); R(69, y, 4);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(8, y, 4); r(20, y, 1); r(28, y, 1); r(33, y, 3); r(41, y, 1); r(46, y, 3); r (57, y, 1);\r
+ R(9, y, 2); R(21, y, 1); R(27, y, 1); R(34, y, 1); R(40, y, 1); R(47, y, 1); R(54, y, 3); R(68, y, 3);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(12, y, 1); r(20, y, 1); r(26, y, 1); r(34, y, 2); r(39, y, 1); r(47, y, 2); r(67, y, 2);\r
+ R(9, y, 3); R(21, y, 1); R(27, y, 1); R(40, y, 1); R(54, y, 1); R(56, y, 2); R(67, y, 1); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(20, y, 1); r(26, y, 1); r (35, y, 1); r(39, y, 1); r(48, y, 1); r(58, y, 1);\r
+ R(10, y, 3); R(21, y, 1); R(27, y, 1); R(40, y, 1); R(54, y, 1); R(56, y, 2); R(67, y, 1); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(56, y, 1); r(66, y, 2);\r
+ R(11, y, 3); R(21, y, 1); R(26, y, 2); R(39, y, 2); R(54, y, 1); R(57, y, 2); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(26, y, 1); r(39, y, 1); r(59, y, 1);\r
+ R(12, y, 3); R(21, y, 1); R(27, y, 2); R(40, y, 2); R(54, y, 1); R(57, y, 2); R(66, y, 1); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(12, y, 4); r(30, y, 1); r(43, y, 1); r(57, y, 1); r(65, y, 2);\r
+ R(13, y, 2); R(21, y, 1); R(27, y, 3); R(40, y, 3); R(54, y, 1); R(58, y, 2); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(13, y, 4); r(27, y, 7); r(40, y, 7);\r
+ R(14, y, 2); R(21, y, 1); R(28, y, 5); R(41, y, 5); R(54, y, 1); R(58, y, 2); R(65, y, 1); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(60, y, 1); r(65, y, 1);\r
+ R(14, y, 3); R(21, y, 1); R(29, y, 6); R(42, y, 6); R(54, y, 1); R(58, y, 2); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(31, y, 1); r(44, y, 1); r(58, y, 1); r(64, y, 1);\r
+ R(15, y, 3); R(21, y, 1); R(32, y, 4); R(45, y, 4); R(54, y, 1); R(59, y, 2); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(33, y, 1); r(46, y, 1); r(61, y, 1); r(64, y, 1);\r
+ R(16, y, 3); R(21, y, 1); R(34, y, 2); R(47, y, 2); R(54, y, 1); R(59, y, 2); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(16, y, 4); r(36, y, 1); r(49, y, 1); r(59, y, 1); r(63, y, 1);\r
+ R(17, y, 2); R(21, y, 1); R(34, y, 2); R(47, y, 2); R(54, y, 1); R(60, y, 2); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(9, y, 1); r(17, y, 4); r(26, y, 1); r(36, y, 1); r(39, y, 1); r(49, y, 1);\r
+ R(18, y, 2); R(21, y, 1); R(35, y, 1); R(48, y, 1); R(54, y, 1); R(60, y, 2); R(63, y, 1); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(26, y, 2); r(39, y, 2); r(63, y, 1);\r
+ R(9, y, 1); R(18, y, 4); R(35, y, 1); R(48, y, 1); R(54, y, 1); R(60, y, 3); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(34, y, 1); r(47, y, 1); r(60, y, 1);\r
+ R(9, y, 1); R(19, y, 3); R(26, y, 2); R(35, y, 1); R(39, y, 2); R(48, y, 1); R(54, y, 1); R(61, y, 2); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(8, y, 1); r(35, y, 1); r(48, y, 1); r(62, y, 1); r(71, y, 1);\r
+ R(9, y, 1); R(20, y, 2); R(26, y, 3); R(34, y, 1); R(39, y, 3); R(47, y, 1); R(54, y, 1); R(61, y, 1); R(69, y, 2);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ r(11, y, 1); r(26, y, 1); r(28, y, 5); r(39, y, 1); r(41, y, 5); r(51, y, 7); r(61, y, 1); r(66, y, 8);\r
+ R(7, y, 4); R(21, y, 1); R(29, y, 1); R(33, y, 1); R(42, y, 1); R(46, y, 1); R(52, y, 5); R(67, y, 7);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ y++;\r
+\r
+ b(0, y, 80);\r
+ y++;\r
+}\r
+\r
int _tmain(int argc, TCHAR **argv) {\r
check_console();\r
\r
int str_number(const TCHAR *, unsigned long *);\r
int num_cpus();\r
int usage(int);\r
+void banner();\r
\r
#define NSSM _T("NSSM")\r
#ifdef _WIN64\r
return 2;
case ERROR_ACCESS_DENIED:
- /* Maybe we already allocated a console for output. */
- if (service->stdin_path[0] || service->stdout_path[0] || service->stderr_path[0]) break;
default:
/* We already have a console. */
log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_ATTACHCONSOLE_FAILED, service->name, error_string(ret), 0);
else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE_BYTES_LOW);\r
if (service->rotate_bytes_high) set_number(key, NSSM_REG_ROTATE_BYTES_HIGH, service->rotate_bytes_high);\r
else if (editing) RegDeleteValue(key, NSSM_REG_ROTATE_BYTES_HIGH);\r
+ if (service->no_console) set_number(key, NSSM_REG_NO_CONSOLE, 1);\r
+ else if (editing) RegDeleteValue(key, NSSM_REG_NO_CONSOLE);\r
\r
/* Environment */\r
if (service->env) {\r
if (get_number(key, NSSM_REG_ROTATE_BYTES_LOW, &service->rotate_bytes_low, false) != 1) service->rotate_bytes_low = 0;\r
if (get_number(key, NSSM_REG_ROTATE_BYTES_HIGH, &service->rotate_bytes_high, false) != 1) service->rotate_bytes_high = 0;\r
\r
+ /* Try to get force new console setting - may fail. */\r
+ if (get_number(key, NSSM_REG_NO_CONSOLE, &service->no_console, false) != 1) service->no_console = 0;\r
+\r
/* Change to startup directory in case stdout/stderr are relative paths. */\r
TCHAR cwd[PATH_LENGTH];\r
GetCurrentDirectory(_countof(cwd), cwd);\r
#define NSSM_REG_ROTATE_BYTES_HIGH _T("AppRotateBytesHigh")\r
#define NSSM_REG_PRIORITY _T("AppPriority")\r
#define NSSM_REG_AFFINITY _T("AppAffinity")\r
+#define NSSM_REG_NO_CONSOLE _T("AppNoConsole")\r
#define NSSM_STDIO_LENGTH 29\r
\r
HKEY open_registry(const TCHAR *, const TCHAR *, REGSAM sam);\r
#define IDC_PRIORITY 1042\r
#define IDC_AFFINITY_ALL 1043\r
#define IDC_AFFINITY 1044\r
+#define IDC_CONSOLE 1045\r
\r
// Next default values for new objects\r
// \r
#ifndef APSTUDIO_READONLY_SYMBOLS\r
#define _APS_NEXT_RESOURCE_VALUE 115\r
#define _APS_NEXT_COMMAND_VALUE 40001\r
-#define _APS_NEXT_CONTROL_VALUE 1045\r
+#define _APS_NEXT_CONTROL_VALUE 1046\r
#define _APS_NEXT_SYMED_VALUE 101\r
#endif\r
#endif\r
if (service->pid) kill_process_tree(service, service->pid, exitcode, service->pid);\r
service->pid = 0;\r
\r
+ if (! service->no_console) FreeConsole();\r
+\r
/*\r
The why argument is true if our wait timed out or false otherwise.\r
Our wait is infinite so why will never be true when called by the system.\r
TCHAR *env_extra;\r
unsigned long env_extralen;\r
unsigned long priority;\r
+ unsigned long no_console;\r
TCHAR stdin_path[PATH_LENGTH];\r
unsigned long stdin_sharing;\r
unsigned long stdin_disposition;\r
{ NSSM_REG_AFFINITY, REG_SZ, 0, false, 0, setting_set_affinity, setting_get_affinity },
{ NSSM_REG_ENV, REG_MULTI_SZ, NULL, false, ADDITIONAL_CRLF, setting_set_environment, setting_get_environment },
{ NSSM_REG_ENV_EXTRA, REG_MULTI_SZ, NULL, false, ADDITIONAL_CRLF, setting_set_environment, setting_get_environment },
+ { NSSM_REG_NO_CONSOLE, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number },
{ NSSM_REG_PRIORITY, REG_SZ, (void *) priority_strings[NSSM_NORMAL_PRIORITY], false, 0, setting_set_priority, setting_get_priority },
{ NSSM_REG_RESTART_DELAY, REG_DWORD, 0, false, 0, setting_set_number, setting_get_number },
{ NSSM_REG_STDIN, REG_EXPAND_SZ, NULL, false, 0, setting_set_string, setting_get_string },