Using Console.Clear() in a Windows Docker Image?

Viewed 332

I'm trying to containerize a .net framework console application for testing and learning. The application works just fine outside the container.

However, I'm getting this error for every Console.Clear() call:

Unhandled Exception: System.IO.IOException: The handle is invalid.

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
   at System.Console.Clear()
   at project.Program.Main(String[] args) in C:\Users\project\Program.cs:line xxx

I can "sort" this out by encasing the Console.Clear() lines in try-catch, but that would be a mess and won't really solve the issue, just hide it under the carpet. I want to understand why is this happening and how to solve it. For propietary reasons I can't post the entire solution here.

This is the dockerfile i'm using:

FROM mcr.microsoft.com/windows/servercore:ltsc2019

ADD "release" "c:/release"

CMD powershell "C:/release/project.exe"

EXPOSE 80 443

I suspect this is because a console is not well handled by a container, but why exactly is the Clear() method of Console falling and not everything else? Why does the container lacks the handler for that particular method? Is it because it's windows core?

1 Answers

You are getting an error because System.Console.Clear (along with other methods that attempt to control/query the console such as System.Console.[Get|Set]CursorPosition) requires a console/TTY but none is attached to the program.

To run your code as-is, you should be able to use the --tty option to docker run to allocate a pseudo-TTY, e.g. docker run --tty <image>.

To modify your code to not require this, you'd probably want to create your own wrapper for System.Console.Clear that wraps it in a try-catch:

void ClearConsole()
{
  try {
    System.Console.Clear();
  }
  catch (System.IO.IOException) {
    // do nothing
  }
}

If only targeting Windows, you can alternatively do a P/Invoke call to GetConsoleWindow to check whether a console exists before calling 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();
    }
  }
}
Related