diff --git a/bin/win/runnerw.exe b/bin/win/runnerw.exe index 0fc194cc49b4..a4f4a81400b1 100644 Binary files a/bin/win/runnerw.exe and b/bin/win/runnerw.exe differ diff --git a/native/runner/runnerw/runnerw.cpp b/native/runner/runnerw/runnerw.cpp index d5a59f40ba52..e277101ed310 100644 --- a/native/runner/runnerw/runnerw.cpp +++ b/native/runner/runnerw/runnerw.cpp @@ -5,10 +5,12 @@ #include void PrintUsage() { - printf("Usage: runnerw.exe \n"); - printf("where is an executable file and are its arguments.\n"); + printf("Usage: runnerw.exe [/C] app [args]\n"); + printf("app [args] Specifies executable file, arguments.\n"); + printf("/C Creates a child process with new visible console.\n"); printf("\n"); - printf("Creates a child process with inherited input, output, and error streams.\n"); + printf("If '/C' option is specified, creates a child process with inherited input, output, and error streams.\n"); + printf("If not, creates a child with a new visible console and attaches to this console.\n"); printf("The input stream is scanned for the presence of the 2-char control sequences:\n"); printf(" ENQ(5) and ETX(3) => a CTRL+BREAK signal is sent to the child process;\n"); printf(" ENQ(5) and ENQ(5) => a CTRL+C signal is sent to the child process.\n"); @@ -151,11 +153,6 @@ BOOL attachChildConsole(PROCESS_INFORMATION const &childProcessInfo) { if (AttachConsole(childProcessInfo.dwProcessId)) { return TRUE; } - // ERROR_GEN_FAILURE means "the specified process does not exist" - // Seems it also means that the console hasn't been fully initialized. - if (GetLastError() != ERROR_GEN_FAILURE) { - break; - } } ErrorMessage("AttachConsole"); return FALSE; @@ -166,11 +163,23 @@ int main(int argc, char * argv[]) { PrintUsage(); } - std::string app(argv[1]); + std::string app(""); std::string args(""); - + BOOL createConsoleFlag = FALSE; for (int i = 1; i < argc; i++) { - if (i>1) { + if (i == 1) { + std::string flag(argv[1]); + if (flag == "/C" || flag == "/c") { + createConsoleFlag = TRUE; + if (argc < 3) { + PrintUsage(); + } + app = argv[2]; + continue; + } + app = argv[1]; + } + if (args.length() > 0) { args += " "; } if (strchr(argv[i], ' ')) { @@ -195,7 +204,9 @@ int main(int argc, char * argv[]) { sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = true; + + BOOL inheritHandles = !createConsoleFlag; + sa.bInheritHandle = inheritHandles; if (!CreatePipe(&newstdin, &write_stdin, &sa, 0)) { ErrorMessage("CreatePipe"); @@ -204,11 +215,24 @@ int main(int argc, char * argv[]) { GetStartupInfo(&si); - si.dwFlags = STARTF_USESTDHANDLES; - si.wShowWindow = SW_HIDE; - si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - si.hStdInput = newstdin; + DWORD processFlag = CREATE_DEFAULT_ERROR_MODE; + BOOL hasConsoleWindow = GetConsoleWindow() != NULL; + if (hasConsoleWindow && !createConsoleFlag) { + processFlag |= CREATE_NO_WINDOW; + } + + if (createConsoleFlag) + { + processFlag |= CREATE_NEW_CONSOLE; + } + + if (inheritHandles) { + si.dwFlags = STARTF_USESTDHANDLES; + si.wShowWindow = SW_HIDE; + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.hStdInput = newstdin; + } if (hasEnding(app, std::string(".bat"))) { // in MSDN it is said to do so, but actually that doesn't work @@ -230,10 +254,9 @@ int main(int argc, char * argv[]) { char* c_args = new char[args.size() + 1]; strcpy(c_args, args.c_str()); - DWORD processFlag = CREATE_DEFAULT_ERROR_MODE; - BOOL hasConsoleWindow = GetConsoleWindow() != NULL; - if (hasConsoleWindow) { - processFlag |= CREATE_NO_WINDOW; + if (createConsoleFlag) + { + si.lpTitle = c_args; } if (!SetConsoleCtrlHandler(NULL, FALSE)) { @@ -244,7 +267,7 @@ int main(int argc, char * argv[]) { c_args, NULL, NULL, - TRUE, + inheritHandles, processFlag, NULL, NULL, @@ -255,7 +278,7 @@ int main(int argc, char * argv[]) { CloseHandle(write_stdin); exit(0); } - if (hasConsoleWindow) { + if (hasConsoleWindow || createConsoleFlag) { attachChildConsole(pi); } if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) { diff --git a/native/runner/runnerw/runnerw.vcxproj b/native/runner/runnerw/runnerw.vcxproj index 766404cf8631..13553072edc4 100644 --- a/native/runner/runnerw/runnerw.vcxproj +++ b/native/runner/runnerw/runnerw.vcxproj @@ -18,6 +18,7 @@ Application true + v140_xp Application diff --git a/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java b/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java index 68d8556b2e22..af2b3bd7bc4a 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java +++ b/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java @@ -35,7 +35,7 @@ public class KillableColoredProcessHandler extends ColoredProcessHandler impleme * Starts a process with a {@link RunnerMediator mediator} when {@code withMediator} is set to {@code true} and the platform is Windows. */ public KillableColoredProcessHandler(@NotNull GeneralCommandLine commandLine, boolean withMediator) throws ExecutionException { - super(mediate(commandLine, withMediator)); + super(mediate(commandLine, withMediator, false)); setShouldKillProcessSoftly(true); } diff --git a/platform/platform-impl/src/com/intellij/execution/process/KillableProcessHandler.java b/platform/platform-impl/src/com/intellij/execution/process/KillableProcessHandler.java index 6df11cfe8e05..d79ed39f2641 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/KillableProcessHandler.java +++ b/platform/platform-impl/src/com/intellij/execution/process/KillableProcessHandler.java @@ -49,7 +49,7 @@ public class KillableProcessHandler extends OSProcessHandler implements Killable * Starts a process with a {@link RunnerMediator mediator} when {@code withMediator} is set to {@code true} and the platform is Windows. */ public KillableProcessHandler(@NotNull GeneralCommandLine commandLine, boolean withMediator) throws ExecutionException { - this(mediate(commandLine, withMediator)); + this(mediate(commandLine, withMediator, false)); } /** @@ -69,9 +69,9 @@ public class KillableProcessHandler extends OSProcessHandler implements Killable } @NotNull - protected static GeneralCommandLine mediate(@NotNull GeneralCommandLine commandLine, boolean withMediator) { + protected static GeneralCommandLine mediate(@NotNull GeneralCommandLine commandLine, boolean withMediator, boolean showConsole) { if (withMediator && SystemInfo.isWindows && MEDIATOR_KEY.get(commandLine) == null) { - boolean mediatorInjected = RunnerMediator.injectRunnerCommand(commandLine); + boolean mediatorInjected = RunnerMediator.injectRunnerCommand(commandLine, showConsole); MEDIATOR_KEY.set(commandLine, mediatorInjected); } return commandLine; diff --git a/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java b/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java index bed914c41a74..7e8bae188c69 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java +++ b/platform/platform-impl/src/com/intellij/execution/process/RunnerMediator.java @@ -75,7 +75,7 @@ public class RunnerMediator { public ProcessHandler createProcess(@NotNull final GeneralCommandLine commandLine, final boolean useSoftKill) throws ExecutionException { if (SystemInfo.isWindows) { - injectRunnerCommand(commandLine); + injectRunnerCommand(commandLine, false); } return new CustomDestroyProcessHandler(commandLine, useSoftKill); @@ -104,10 +104,12 @@ public class RunnerMediator { return null; } - static boolean injectRunnerCommand(@NotNull GeneralCommandLine commandLine) { + static boolean injectRunnerCommand(@NotNull GeneralCommandLine commandLine, boolean showConsole) { final String path = getRunnerPath(); if (path != null) { commandLine.getParametersList().addAt(0, commandLine.getExePath()); + if (showConsole) + commandLine.getParametersList().addAt(0, "/C"); commandLine.setExePath(path); return true; } diff --git a/platform/platform-impl/src/com/intellij/execution/process/RunnerWinProcess.java b/platform/platform-impl/src/com/intellij/execution/process/RunnerWinProcess.java index 30910579ad0a..0c5f1260b881 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/RunnerWinProcess.java +++ b/platform/platform-impl/src/com/intellij/execution/process/RunnerWinProcess.java @@ -41,7 +41,7 @@ public class RunnerWinProcess extends ProcessWrapper { if (!SystemInfo.isWindows) { throw new RuntimeException("RunnerWinProcess works on Windows only!"); } - boolean success = RunnerMediator.injectRunnerCommand(commandLine); + boolean success = RunnerMediator.injectRunnerCommand(commandLine, false); Process process = commandLine.createProcess(); return success ? new RunnerWinProcess(process) : process; }