стандартный ввод не перенаправляется C#

#c# #stdout #stdin #minecraft

#c# #стандартный вывод #стандартный ввод #Minecraft

Вопрос:

Итак, у меня есть процесс (приложение командной строки Java), который скрыт с перенаправлением вывода и ввода. Я могу очень легко прочитать вывод, и это работает, но когда я отправляю команду, это не работает.

Я думаю, что я определил, что ввод не перенаправляется, потому что:

(A) Когда я отправляю WriteLine(//command here); Flush , программа не подтверждает ни одну команду

(B) Когда я показываю окно cmd ( StartInfo.CreateNoWindow = false; ), я могу вводить команды и запускать их (в окне cmd), даже если стандартный ввод перенаправляется ( StartInfo.RedirectStandardInput = true; )

Вот код:

 namespace bukkit
{
    public partial class Form1 : Form
{
    private static StringBuilder _txt = new StringBuilder();
    private static bool _scrolled = false;
    Process mncrft = new Process();

    public Form1()
    {
        InitializeComponent();

        mncrft.StartInfo.WorkingDirectory = Path.GetTempPath();
        mncrft.StartInfo.Arguments = "-Xmx512M -Xms512M -jar C:\mncrft\mncrft.jar";
        mncrft.StartInfo.FileName = "java.exe";
        mncrft.StartInfo.UseShellExecute = false;
        mncrft.StartInfo.RedirectStandardOutput = true;
        mncrft.StartInfo.RedirectStandardError = true;
        mncrft.StartInfo.RedirectStandardInput = true;
        mncrft.StartInfo.CreateNoWindow = false;
        mncrft.ErrorDataReceived  = build_ErrorDataReceived;
        //mncrft.OutputDataReceived  = build_ErrorDataReceived;
        mncrft.EnableRaisingEvents = true;
        //mncrft.StandardInput.NewLine = "rn";
        mncrft.Start();
        mncrft.BeginOutputReadLine();
        mncrft.BeginErrorReadLine();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        _txt.AppendLine("Starting Minecraft...");
    }

    private void Form1_Close(object sender, EventArgs e)
    {
        mncrft.Close();
    }

    static void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        string msg = e.Data;
        if (msg != null amp;amp; msg.Length > 0)
        {
            _txt.AppendLine(msg);
            _scrolled = false;
        }
    }

    private void mainTimer_Tick(object sender, EventArgs e)
    {
        if (_txt.Length > 0)
        {
            txtOutput.Text = _txt.ToString();

            // scroll down
            if (_scrolled == false)
            {
                txtOutput.SelectionStart = txtOutput.Text.Length;
                txtOutput.ScrollToCaret();
                _scrolled = true;
            }
        }
    }

    private void Execute_Click(object sender, EventArgs e)
    {
        if (textBox1.Text.Length > 0)
        {
            mncrft.StandardInput.WriteLine(textBox1.Text);
            mncrft.StandardInput.Flush();
        }
    }
}
}
  

Как я могу перенаправить ввод, чтобы я мог отправлять команды?

Спасибо, Адам

P.S: Если это сбивает с толку, просто оставьте комментарий, и я с удовольствием поясню.

Ответил

Благодаря Тиму, замените следующие строки:

 mncrft.StartInfo.FileName = "java.exe";
mncrft.StartInfo.Arguments = "-Xmx512M -Xms512M -jar C:\mncrft\mncrft.jar";
  

с:

 mncrft.StartInfo.FileName = "java";
mncrft.StartInfo.Arguments = "-Xmx512M -Xms512M -jar C:\mncrft\bukkit.jar -nojline";
  

Комментарии:

1. Это не из-за WinForm, а из-за самого Bukkit. К сожалению, у меня такая же проблема, и я понятия не имею, как ее решить. D: Одна вещь, которую я заметил, это то, что он перехватывает консоль для меня, когда я пытаюсь ее запустить.

2. Если я что-нибудь придумаю, я опубликую это прямо здесь. Знает ли notch что-нибудь об этом?

3. Кстати, это не очень хорошая идея говорить просто java потому что вы можете запустить 32-битную java на 64-битном ПК

Ответ №1:

Хорошо, я возился с этим весь день, и я нашел ответ. При запуске bukkit с вашим приложением вам необходимо включить ‘-nojline’ в аргументы вашего процесса. Это позволяет входным данным bukkit корректно работать со стандартным вводом.

https://github.com/Bukkit/CraftBukkit/commit/22a44d47ac48fb65bb61fb823c84bff9494f5033

Комментарии:

1. Ты мой друг… Великолепны!!!!! Я практически отказался от этого. Большое вам спасибо!!

2. Эй, без проблем, это выбивало меня из колеи, чтобы. Мне повезло с ответом, и я решил поместить его здесь, поскольку я находил эту страницу примерно 800 раз.

3. Спасибо <3 теперь я могу окончательно доработать свой графический интерфейс для tekkit: D

Ответ №2:

Адам, я не знаю наверняка ответа на твой вопрос, но у меня действительно была похожая проблема в прошлом, и я узнал, что приложение winform ведет себя немного по-другому, когда дело доходит до stdin и stdout с консолью. Я решил свою проблему после прочтения некоторых сообщений в Интернете, используя вызов API для AttachConsole (и FreeConsole для его выпуска). Возможно, это будет хорошей отправной точкой для изучения в качестве решения вашей проблемы.

 [DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
  

Комментарии:

1. Спасибо за идею, я попробую и сообщу об этом.

2. Если бы вы могли вкратце рассказать, как это использовать. Я подключил его к процессу нормально, но когда я использую консоль. строка записи командное приглашение, похоже, перехватывается, но не выполняется. Это просто записывается прямо в командную строку

3. Что ж, теперь visual Studio перехватывает его, помещая его в выходные данные

4. Я предложу это как псевдологику. В вашем Execute_Click (1) прикрепите CONSOLE, используя идентификатор процесса, который у вас есть при запуске процесса Java. (2) Запишите в консоль (3) FreeConsole, чтобы освободить его. Если вы выполните поиск по AttachConsole и Winform, вы должны быть в состоянии найти несколько примеров того, как это сделать, в качестве отправной точки

Ответ №3:

Это очень странно, потому что, если входной поток не перенаправлялся (по какой-либо причине), вы получите исключение в тот момент, когда попытаетесь что-либо сделать с процессом.Свойство StandartInput, и если бы оно действительно перенаправляло, то вы не смогли бы вводить команды в окне cmd и выполнять их!

Если проблема в том, что вы создаете приложение WinForms (как упоминал Фадриан), тогда попробуйте сделать его приложением WPF (лично я предпочитаю WPF, а не WinForms), если вы никогда раньше не кодировали приложение WPF, тогда загрузите код, который я ссылал в своем блоге здесь (да, тот, который вы посещали ранее) и измените его так, чтобы он загружал ваш сервер Bukkit вместо обычного сервера Minecraft, если это не сработало, то проблема может быть с сервером Bukkit, в этот момент я рекомендую чтобы вы зашли на форум Буккита и спросили там.

Комментарии:

1. Я бы никогда не подумал перейти на wpf… но это не помогло. Может быть, это мой компьютер? Я просто взял ваш код из коробки и скомпилировал его, но ничего. Я снова обновлю после школы