How to create a new command prompt window and redirect user input?

For a game server application, I already have a console that displays some information about the runtime. However, I would like to have another one where the administrator can enter commands (for example, in case of emergency), while the resulting effects of these inputs are still displayed in the main console window.

There are already similar questions about stackoverflow on this topic, however applying the answers did not lead to what I was hoping for. I'm having trouble understanding why, on the one hand, I seem to need to install UseShellExecute = true;in order to get a new window, while this makes it impossible RedirectStandardInput = true;and vice versa. However, the presence of input and output through a new process, but in the same console request, works fine, except for visual clutter (when recording, the output is added to your wirtten but not sent, which is inconvenient).

So, is it possible to use a separate command line for admin input (I think so), or do I need to configure another form of interprocess communication and create a separate program (with Main-function and all)?

Here is my current code related to process generation. Note that it is embedded in a less optimized context if you are interested in setting the overall composition:

bool canExecute = false;

Process consoleProcess;
ProcessStartInfo startInfo = new ProcessStartInfo();

OperatingSystem os = Environment.OSVersion;
switch (os.Platform)
{
    case PlatformID.MacOSX:
        canExecute = false;
        break;
    case PlatformID.Unix:
        canExecute = true;
        startInfo.FileName = "/bin/bash";
        break;
    case PlatformID.Win32NT:
        canExecute = true;
        startInfo.FileName = "cmd.exe";
        break;
    case PlatformID.Win32S:
        canExecute = true;
        startInfo.FileName = "cmd.exe";
        break;
    case PlatformID.Win32Windows:
        canExecute = true;
        startInfo.FileName = "cmd.exe";
        break;
    case PlatformID.WinCE:
        canExecute = true;
        startInfo.FileName = "cmd.exe";
        break;
    case PlatformID.Xbox:
        canExecute = false;
        break;
}

startInfo.RedirectStandardInput = true;
startInfo.UseShellExecute = false;

consoleProcess = new Process();
consoleProcess.StartInfo = startInfo;
consoleProcess.Start();

if (canExecute)
{
    using (StreamWriter sw = consoleProcess.StandardInput)
    {
        String line;

        while ((line = Console.ReadLine()) != null)
        {
            // do something useful with the user input
        }
    }
}

Thank you in advance!

+4
source share
1 answer

You cannot do this only with the built-in .NET class Process. It does not support the correct options.

, Windows . UseShellExecute = true; ( Process), , Process () ShellExecuteEx(). Windows Shell , , . , .

, , -, UseShellExecute = true;. false.

: CreateProcess() p/invoke, Process . CREATE_NEW_CONSOLE. , CreateProcess() .

. MSDN , .

, , Process, -. - . , -, , , , , . ( - , , - stdio), - , API-.


( " Windows", " " ) . , . - , . , , , . .

, , (.. PipeDirection.In PipeDirection.Out ) - StandardInput. , . ( ... , , , , :)).

: (ConsoleProxy.exe)

class Program
{
    static void Main(string[] args)
    {
        NamedPipeClientStream pipe = new NamedPipeClientStream(".", args[1],
            PipeDirection.InOut, PipeOptions.Asynchronous);

        pipe.Connect();

        Process process = new Process();

        process.StartInfo.FileName = args[0];
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.RedirectStandardOutput = true;

        process.Start();

        using (TextReader reader = new StreamReader(pipe))
        using (TextWriter writer = new StreamWriter(pipe))
        {
            Task readerTask = ConsumeReader(process.StandardOutput, writer);
            string line;

            do
            {
                line = reader.ReadLine();
                if (line != "")
                {
                    line = "proxied write: " + line;
                }
                process.StandardInput.WriteLine(line);
                process.StandardInput.Flush();
            } while (line != "");

            readerTask.Wait();
        }
    }

    static async Task ConsumeReader(TextReader reader, TextWriter writer)
    {
        char[] rgch = new char[1024];
        int cch;

        while ((cch = await reader.ReadAsync(rgch, 0, rgch.Length)) > 0)
        {
            writer.Write("proxied read: ");
            writer.Write(rgch, 0, cch);
            writer.Flush();
        }
    }
}

: (ConsoleApplication1.exe)

class Program
{
    static void Main(string[] args)
    {
        Console.Title = "ConsoleApplication1";

        string line;

        while ((line = PromptLine("Enter text: ")) != "")
        {
            Console.WriteLine("    Text entered: \"" + line + "\"");
        }
    }

    static string PromptLine(string prompt)
    {
        Console.Write(prompt);
        return Console.ReadLine();
    }
}

:

class Program
{
    static void Main(string[] args)
    {
        NamedPipeServerStream pipe = new NamedPipeServerStream("ConsoleProxyPipe",
            PipeDirection.InOut, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

        Console.Title = "Main Process";

        Process process = new Process();

        process.StartInfo.FileName = "ConsoleProxy.exe";
        process.StartInfo.Arguments = "ConsoleApplication1.exe ConsoleProxyPipe";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.CreateNoWindow = true;

        process.Start();

        pipe.WaitForConnection();

        using (TextReader reader = new StreamReader(pipe))
        using (TextWriter writer = new StreamWriter(pipe))
        {
            Task readerTask = ConsumeReader(reader);
            string line;

            do
            {
                line = Console.ReadLine();
                writer.WriteLine(line);
                writer.Flush();
            } while (line != "");

            readerTask.Wait();
        }
    }

    static async Task ConsumeReader(TextReader reader)
    {
        char[] rgch = new char[1024];
        int cch;

        while ((cch = await reader.ReadAsync(rgch, 0, rgch.Length)) > 0)
        {
            Console.Write(rgch, 0, cch);
        }
    }
}
+1

Source: https://habr.com/ru/post/1618782/


All Articles