Вот ключ к моей настройке:
tb: текстовое поле для ввода команд
lb: метка для отображения состояния сервера
CurrentServer: представляет выбранный экземпляр сервера в различных элементах управления
Я попробовал несколько решений (см. ниже), но пока ничего не помогло. Есть ли лучший способ поддерживать взаимодействие с запущенной командной строкой сервера после переключения представлений?
Похожая ссылка на проблему - но мне нужно поддерживать ввод/вывод в режиме реального времени.
( Как передать команды в уже запущенную командную строку на C#?)
Код: Выделить всё
private Process cmdProcess;
private bool isServerOnline = false;
public void ComandPromptRun()
{
MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
// Check if the process for the current server already exists
if (mainWindow.MinecraftJavaCmdProcesses.ContainsKey(mainWindow.CurrentServer) && mainWindow.MinecraftJavaCmdProcesses[mainWindow.CurrentServer] != null)
{
cmdProcess = mainWindow.MinecraftJavaCmdProcesses[mainWindow.CurrentServer];
if (cmdProcess != null && !cmdProcess.HasExited)
{
// Reattach output event handler
cmdProcess.OutputDataReceived -= CmdProcess_OutputDataReceived;
cmdProcess.OutputDataReceived += CmdProcess_OutputDataReceived;
// Ensure the process is still reading output
if (cmdProcess.StandardOutput.BaseStream.CanRead)
{
cmdProcess.BeginOutputReadLine(); // Reattach reading
}
else
{
MessageBox.Show("The output stream is unavailable. Please restart the process.");
}
// Load previous logs if any
foreach (var log in mainWindow.MinecraftJavaLogs[mainWindow.CurrentServer])
{
Dispatcher.Invoke(() =>
{
TB_ComandPromptOutput.AppendText(log + Environment.NewLine);
});
}
return; // Avoid starting a new process
}
else
{
MessageBox.Show("Process has exited or is unavailable. You will need to restart the server.");
mainWindow.MinecraftJavaCmdProcesses[mainWindow.CurrentServer] = null;
}
}
// Start a new process if it doesn't exist
StartNewMinecraftProcess(mainWindow);
}
private void StartNewMinecraftProcess(MainWindow mainWindow)
{
string selectedServerPath = mainWindow.MinecraftJavaServers[mainWindow.CurrentServer];
// Start a new thread to run the server process
new Thread(() =>
{
try
{
MessageBox.Show($"Starting server at: {selectedServerPath}");
Thread.CurrentThread.IsBackground = true;
cmdProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = $@"{selectedServerPath}\Run.bat",
WorkingDirectory = selectedServerPath,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = true
}
};
cmdProcess.OutputDataReceived += CmdProcess_OutputDataReceived;
cmdProcess.Start();
cmdProcess.BeginOutputReadLine();
// Store the new process in the dictionary
mainWindow.MinecraftJavaCmdProcesses[mainWindow.CurrentServer] = cmdProcess;
}
catch (Exception ex)
{
Dispatcher.Invoke(() => MessageBox.Show($"Failed to start server: {ex.Message}"));
}
}).Start();
}
private void CmdProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Data))
{
Dispatcher.Invoke(() =>
{
// Append to TextBox
TB_ComandPromptOutput.AppendText(e.Data + Environment.NewLine);
// Store log in the MainWindow dictionary
MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
if (!mainWindow.MinecraftJavaLogs.ContainsKey(mainWindow.CurrentServer))
{
mainWindow.MinecraftJavaLogs[mainWindow.CurrentServer] = new List();
}
mainWindow.MinecraftJavaLogs[mainWindow.CurrentServer].Add(e.Data);
});
}
}
public void CmdProcess_IncomeDataSent(string inputData)
{
if (!string.IsNullOrEmpty(inputData))
{
Dispatcher.Invoke(() =>
{
if (cmdProcess != null && !cmdProcess.HasExited)
{
if (cmdProcess.StandardInput != null && !cmdProcess.StandardInput.BaseStream.CanWrite)
{
MessageBox.Show("The input stream is closed or unavailable.");
return;
}
cmdProcess.StandardInput.WriteLine(inputData);
cmdProcess.StandardInput.Flush();
}
else
{
MessageBox.Show("Command prompt process is not running or has exited.");
}
});
}
}
private void TB_ComandPromptInput_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
CmdProcess_IncomeDataSent(TB_ComandPromptInput.Text);
if (TB_ComandPromptInput.Text.ToLower() == "stop")
{
lb_IsServerOnline.Content = "Offline";
lb_IsServerOnline.Foreground = new SolidColorBrush(Colors.Red);
TB_ComandPromptInput.IsEnabled = false;
isServerOnline = false;
}
TB_ComandPromptInput.Text = string.Empty;
}
}
Переключение на PowerShell с аналогичным кодом.
Запуск процесса в разных потоках.
Запуск процесса без пакетного файла использование аргументов непосредственно в коде.
Хранение командных процессоров в главном окне.
Запуск всего через Dispatcher.Invoke.
ChatGPT и другие инструменты на основе искусственного интеллекта для помощи.
Подробнее здесь: https://stackoverflow.com/questions/791 ... ion-broken