Использование консоли.Очистить () в образе Windows Docker?

#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();
    }
  }
}