Skip to content

Instantly share code, notes, and snippets.

@poiru
Created February 2, 2018 05:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save poiru/d7cedb2c3c4c7aca9dce29d439597cca to your computer and use it in GitHub Desktop.
Save poiru/d7cedb2c3c4c7aca9dce29d439597cca to your computer and use it in GitHub Desktop.
Patch to make Node 8.9.x run silently without popping up the console window and without triggering the spinning feedback cursor. See https://github.com/nodejs/node/issues/556
commit 1d685613e455017043d4371b3124eca997357eaa
Author: Birunthan Mohanathas <birunthan@mohanathas.com>
Date: Fri Feb 2 10:46:54 2018 +0530
node: generate a Windows application instead of a console application
This makes Node run silently without popping up a console window and
without triggering the spinning feedback cursor.
diff --git a/deps/uv/src/win/handle-inl.h b/deps/uv/src/win/handle-inl.h
index 8d0334cc52..2f06c51a94 100644
--- a/deps/uv/src/win/handle-inl.h
+++ b/deps/uv/src/win/handle-inl.h
@@ -168,11 +168,27 @@ INLINE static HANDLE uv__get_osfhandle(int fd)
/* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */
/* for invalid FDs in release builds (or if you let the assert continue). */
/* So this wrapper function disables asserts when calling _get_osfhandle. */
+ /* For the stdin/stdout/stderr handles, we use the Win32 API directly */
+ /* because _get_osfhandle does not work as expected when a console is */
+ /* attached or detached during runtime (with AllocConsole/FreeConsole). */
HANDLE handle;
- UV_BEGIN_DISABLE_CRT_ASSERT();
- handle = (HANDLE) _get_osfhandle(fd);
- UV_END_DISABLE_CRT_ASSERT();
+ switch (fd) {
+ case 0:
+ handle = GetStdHandle(STD_INPUT_HANDLE);
+ break;
+ case 1:
+ handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ break;
+ case 2:
+ handle = GetStdHandle(STD_ERROR_HANDLE);
+ break;
+ default:
+ UV_BEGIN_DISABLE_CRT_ASSERT();
+ handle = (HANDLE) _get_osfhandle(fd);
+ UV_END_DISABLE_CRT_ASSERT();
+ break;
+ }
return handle;
}
diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js
index 48a4588543..f5f3ffa175 100644
--- a/lib/internal/bootstrap_node.js
+++ b/lib/internal/bootstrap_node.js
@@ -18,6 +18,8 @@
EventEmitter.call(process);
+ process.NativeModule = NativeModule;
+
setupProcessObject();
// do this good and early, since it handles errors.
diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js
index 45568ae631..0a597f7d9e 100644
--- a/lib/internal/process/stdio.js
+++ b/lib/internal/process/stdio.js
@@ -86,8 +86,15 @@ function setupStdio() {
break;
default:
- // Probably an error on in uv_guess_handle()
- throw new errors.Error('ERR_UNKNOWN_STDIN_TYPE');
+ if (process.platform === 'win32') {
+ // TODO: We should throw here if we're a console application.
+ stdin = new process.NativeModule.require('stream').Readable();
+ stdin.push(null);
+ } else {
+ // Probably an error on in uv_guess_handle()
+ throw new errors.Error('ERR_UNKNOWN_STDIN_TYPE');
+ }
+ break;
}
// For supporting legacy API we put the FD here.
@@ -170,8 +177,18 @@ function createWritableStdioStream(fd) {
break;
default:
- // Probably an error on in uv_guess_handle()
- throw new errors.Error('ERR_UNKNOWN_STREAM_TYPE');
+ if (process.platform === 'win32') {
+ // TODO: We should throw here if we're a console application.
+ stream = new process.NativeModule.require('stream').Writable();
+ stream.isTTY = false;
+ stream._write = function(chunk, encoding, callback) {
+ process.nextTick(callback);
+ };
+ } else {
+ // Probably an error on in uv_guess_handle()
+ throw new errors.Error('ERR_UNKNOWN_STREAM_TYPE');
+ }
+ break;
}
// For supporting legacy API we put the FD here.
diff --git a/node.gypi b/node.gypi
index 9b37b10a4a..f0adbb5f34 100644
--- a/node.gypi
+++ b/node.gypi
@@ -5,7 +5,25 @@
'VCManifestTool': {
'EmbedManifest': 'true',
'AdditionalManifestFiles': 'src/res/node.exe.extra.manifest'
- }
+ },
+ 'VCLinkerTool': {
+ 'conditions': [
+ ['target_arch=="ia32"', {
+ 'target_conditions': [
+ [ '_type=="executable"', {
+ 'AdditionalOptions': [ '/SubSystem:Windows,"5.01"' ],
+ }],
+ ],
+ }],
+ ['target_arch=="x64"', {
+ 'target_conditions': [
+ [ '_type=="executable"', {
+ 'AdditionalOptions': [ '/SubSystem:Windows,"5.02"' ],
+ }],
+ ],
+ }],
+ ],
+ },
},
}, {
'defines': [
diff --git a/src/node.cc b/src/node.cc
index d16372937d..38f6a62fad 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -4517,6 +4517,10 @@ void ProcessArgv(int* argc,
const char** v8_argv;
ParseArgs(argc, argv, exec_argc, exec_argv, &v8_argc, &v8_argv, is_env);
+ if (force_repl) {
+ AllocConsole();
+ }
+
// TODO(bnoordhuis) Intercept --prof arguments and start the CPU profiler
// manually? That would give us a little more control over its runtime
// behavior but it could also interfere with the user's intentions in ways
diff --git a/src/node_main.cc b/src/node_main.cc
index 2a511b9299..455108f91f 100644
--- a/src/node_main.cc
+++ b/src/node_main.cc
@@ -71,6 +71,19 @@ int wmain(int argc, wchar_t *wargv[]) {
// Now that conversion is done, we can finally start.
return node::Start(argc, argv);
}
+
+int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) {
+ // Windows helpfully displays the spinning feedback cursor for a few seconds
+ // until the first call to GetMessage(). Let's suppress the cursor by
+ // posting a dummy WM_USER message and immediately retrieving it.
+ PostMessage(nullptr, WM_USER, 0, 0);
+ MSG msg;
+ if (GetMessage(&msg, nullptr, WM_USER, WM_USER) <= 0) {
+ return 1;
+ }
+
+ return wmain(__argc, __wargv);
+}
#else
// UNIX
#ifdef __linux__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment