#c# #docker #containers
#c# #docker #контейнеры
Вопрос:
Я пытаюсь контейнеризировать консольное приложение .net Framework для тестирования и обучения. Приложение отлично работает вне контейнера.
Однако я получаю эту ошибку для каждой консоли.Вызов Clear():
Unhandled Exception: System.IO.IOException: The handle is invalid.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Booleanamp; succeeded)
at System.Console.Clear()
at project.Program.Main(String[] args) in C:UsersprojectProgram.cs:line xxx
Я могу «разобраться» с этим, заключив консоль в оболочку.Строки Clear() в try-catch, но это было бы беспорядочно и на самом деле не решит проблему, просто спрячьте ее под ковром.
Я хочу понять, почему это происходит и как это решить.
По собственным причинам я не могу опубликовать здесь все решение.
Это файл dockerfile, который я использую:
FROM mcr.microsoft.com/windows/servercore:ltsc2019
ADD "release" "c:/release"
CMD powershell "C:/release/project.exe"
EXPOSE 80 443
Я подозреваю, что это связано с тем, что консоль плохо обрабатывается контейнером, но почему именно метод Clear () консоли падает, а не все остальное?
Почему в контейнере отсутствует обработчик для этого конкретного метода? Это потому, что это ядро Windows?
Комментарии:
1. Неофициальные данные указывают на такие статьи, как эта: andykdocs.de/development/Docker /…
2. Документы для консоли. Очистить обратите внимание, что «Попытка вызвать метод Clear, когда вывод консольного приложения перенаправляется в файл, вызывает исключение IOException». Я подозреваю, что реализация консоли Window в Docker ближе к файлу или каналу, чем к собственной консоли. Не человек Windows, поэтому не знаю.
Ответ №1:
Вы получаете сообщение об ошибке, потому что System.Console.Clear
(наряду с другими методами, которые пытаются управлять / запрашивать консоль, такими как System.Console.[Get|Set]CursorPosition
) требуется консоль / TTY, но ни один из них не подключен к программе.
Чтобы запустить ваш код как есть, вы должны иметь возможность использовать --tty
опцию docker run
для выделения псевдообъекта, например docker run --tty <image>
.
Чтобы изменить свой код так, чтобы он не требовал этого, вы, вероятно, захотите создать свою собственную оболочку для System.Console.Clear
, которая обертывает его в try-catch:
void ClearConsole()
{
try {
System.Console.Clear();
}
catch (System.IO.IOException) {
// do nothing
}
}
Если вы нацелены только на Windows, вы можете в качестве альтернативы выполнить вызов P / Invoke GetConsoleWindow
, чтобы проверить, существует ли консоль перед вызовом System.Console.Clear
:
class Program
{
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern System.IntPtr GetConsoleWindow();
static void ClearConsole()
{
if (GetConsoleWindow() != System.IntPtr.Zero)
{
System.Console.Clear();
}
}
}