Соединение с командной строкой C# разорваноC#

Место общения программистов C#
Anonymous
Соединение с командной строкой C# разорвано

Сообщение Anonymous »

Я создаю средство запуска сервера в WPF, используя .NET Framework, чтобы избежать каждый раз ручной настройки файлов. В настоящее время я могу взаимодействовать с пакетным файлом сервера из графического интерфейса, но у меня возникают проблемы при переключении представлений. Например, когда я ухожу с экрана консоли (к настройкам, журналам и т. д.), я теряю соединение с работающей командной строкой, а входы и выходы перестают работать, хотя серверный процесс все еще активен.
Вот ключ к моей настройке:
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

Вернуться в «C#»