[rider]: patched runnerw.exe mediator to allow create process with new visible console (#RIDER-4160)

This commit is contained in:
vadim.lomshakov
2017-08-21 21:38:43 +03:00
parent 7ea46d3c36
commit 85734f3ed8
7 changed files with 56 additions and 30 deletions
Binary file not shown.
+46 -23
View File
@@ -5,10 +5,12 @@
#include <string>
void PrintUsage() {
printf("Usage: runnerw.exe <app> <args>\n");
printf("where <app> is an executable file and <args> 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)) {
+1
View File
@@ -18,6 +18,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@@ -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);
}
@@ -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;
@@ -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;
}
@@ -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;
}