Terminal.Gui: Error Loading Native Library in Docker .NET 6

I am not sure whether this is a supported use case, but it has been working just fine in .NET 5 for us, I ended up updating everything to .NET 6 and gui.cs is breaking on loading native library, strangely it doesn’t seem to mention which library at all. Docker image is just based off mcr.microsoft.com/dotnet/runtime:6.0, nothing added to it.

I have attached the stack trace below, let me know if more information is necessary

Stack Trace:

Curses failed to initialize, the exception is: System.IO.IOException: Error loading native library ""
   at Unix.Terminal.UnmanagedLibrary..ctor(String[] libraryPathAlternatives, Boolean isFullPath)
   at Unix.Terminal.Curses.LoadMethods()
   at Unix.Terminal.Curses.FindNCurses()
   at Unix.Terminal.Curses.initscr()
   at Terminal.Gui.CursesDriver.Init(Action terminalResized)
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at Unix.Terminal.Curses.doupdate()
   at Terminal.Gui.CursesDriver.Init(Action terminalResized)
   at Terminal.Gui.Application.Init(Func`1 topLevelFactory, ConsoleDriver driver, IMainLoopDriver mainLoopDriver)
   at Terminal.Gui.Application.Init(ConsoleDriver driver, IMainLoopDriver mainLoopDriver)
   ....

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 37

Most upvoted comments

Leave off the .so. For Ubuntu the packages are named libncursesw5 and/or libncursesw6.

Like I said, I’ve hardly used this library in Linux, and never with a container.

EDIT: I don’t know if this helps, but it seems to be discussing exactly your problem.

With the original Dockerfile it’s possible get it to work with this modification:

#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/runtime:6.0 AS base
RUN apt-get update && apt-get upgrade -y && apt-get install -y ncurses-dev locales && \
	sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=en_US.UTF-8
ENV LANG=en_US.UTF-8 \
	TERM=xterm-256color
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["RainLispConsole/RainLispConsole.csproj", "RainLispConsole/"]
RUN dotnet restore "RainLispConsole/RainLispConsole.csproj"
COPY . .
WORKDIR "/src/RainLispConsole"
RUN dotnet build "RainLispConsole.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "RainLispConsole.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "RainLispConsole.dll"]

Ah I’m now see that you are using alpine (which I know it work) but with the original Dockerfile you have in your repo, the CodeEditor doesn’t run. Thanks for the fantastic demonstration.

On Linux Ctrl+Enter is not working. Ctrl+Enter generates the exact same sequence in terminal emulators as Enter, so there’s no way for an app to distinguish these two. Maybe you can use Ctrl+F5, which is working well.

@Nutzzz and @BDisp thank you for your help. I managed to run it successfully.

Based on the info you provided, I made just a few modifications to the default docker file that visual studio produces when you enable docker support and it works fine.

I had to also consult #1815 because I had the same problem with bash. One other difference I encountered, is that I could not publish it as a self contained assembly because it’s a tool package.

I can even debug right now, by attaching the debugger to a running container.

One last thing, @BDisp, have you got any idea why one StatusItem key shortcut works and another one doesn’t? This problem only occurs in the container of course. I am confirming by debugging. I wonder if this means that it wouldn’t work in a real Linux box either. Maybe I should set up a VM and test it…

This is how they are declared. Ctrl + F4 that quits works, whereas Ctrl + Enter doesn’t. Evaluate and Quit are methods and only a breakpoint in the latter can be hit.

            var statusBarItems = new StatusItem[]
            {
                _cursorPosStatusItem,
                new(Key.CtrlMask | Key.Enter, Resources.EVALUATE, Evaluate),
                new(Key.CtrlMask | Key.F4, Resources.QUIT, Quit),
            };

@chr1st0scli I dont believe Docker Desktop has the best terminal interface to evaluate whether it works well or not tho. Try Windows terminal instead, it could be your terminal emulator misbehaving and not necessarily the library.

check some previous discussion I had with @BDisp:

https://github.com/gui-cs/Terminal.Gui/issues/1519#issuecomment-977039546

Sorry, so, even without setting setting it somewhat worked for me. I think it might have to do with my terminal emulator, I am using a Bitvise SSH terminal, so that might be where my issue arises. Using Windows built in powershell I get mostly a functional container while only changing TERM and making sure either ncurses is available.

So i’ll be closing this, it is such an edge case and I got it to be functional enough for now, thanks for your help

So I did some basic testing with UICatalog example, to get NET 6.0 binaries I have patched it like so:

diff --git a/Terminal.Gui/Terminal.Gui.csproj b/Terminal.Gui/Terminal.Gui.csproj
index bba15aa..789273d 100644
--- a/Terminal.Gui/Terminal.Gui.csproj
+++ b/Terminal.Gui/Terminal.Gui.csproj
@@ -25,7 +25,7 @@
     <!-- This enables prefixing version tags with v, e.g. v1.0.0 Instead of 1.0.0 -->
     <MinVerTagPrefix>v</MinVerTagPrefix>

-    <TargetFrameworks>net472;netstandard2.0;net5.0</TargetFrameworks>
+    <TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
     <RootNamespace>Terminal.Gui</RootNamespace>
     <AssemblyName>Terminal.Gui</AssemblyName>
     <DocumentationFile>bin\Release\Terminal.Gui.xml</DocumentationFile>
diff --git a/UICatalog/UICatalog.csproj b/UICatalog/UICatalog.csproj
index 530eed7..cf6e128 100644
--- a/UICatalog/UICatalog.csproj
+++ b/UICatalog/UICatalog.csproj
@@ -2,7 +2,7 @@

   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>net5.0</TargetFramework>
+    <TargetFrameworks>net5.0;net6.0</TargetFrameworks>
     <StartupObject>UICatalog.UICatalogApp</StartupObject>
     <AssemblyVersion>1.0.0.1</AssemblyVersion>
     <LangVersion>8.0</LangVersion>

Then I just ran the default dotnet build inside UICatalog folder and had 2 debug binaries built.

I am running docker on windows within a Powershell session (current directory is UICatalog folder), so your mileage may vary slightly to map it. Mapped the binaries to the runtime container:

.NET 5

docker run -v $pwd/bin/Debug/net5.0:/app `
    -it `
    -e "TERM=xterm-256color" `
    mcr.microsoft.com/dotnet/runtime:5.0-buster-slim `
    bash -c "apt-get update && apt-get -y install libncurses5-dev libncursesw5-dev && cd /app && dotnet UICatalog.dll" 

.NET 6

 docker run -v $pwd/bin/Debug/net6.0:/app `
    -it `
    -e "TERM=xterm-256color" `
    mcr.microsoft.com/dotnet/runtime:6.0-bullseye-slim `
    bash -c "apt-get update && apt-get -y install libncurses5-dev libncursesw5-dev && cd /app && dotnet UICatalog.dll"

One example that definitely doesn’t work properly in .NET 6 is the Radio Group (Text Alignment) inside the Buttons demo. Whereas it seems to mostly work for .NET 5 build except the broken glyph.

Not sure if this helps but it shows some of the differences/issues I had. Interestingly I don’t remember having ever installed ncurses in my previous .NET 5 based image, i’ll double check tomorrow

$TERM was xterm, set up an env var with xterm-256color and we have progress, UI is partially rendered using ncurses, still worse than UseSystemConsole.