NullReferenceException when redirecting output from ScreenView
Given the following program:
public class Program
{
static async Task<int> Main(InvocationContext invocationContext, string[] args)
{
var consoleRenderer = new ConsoleRenderer(
invocationContext.Console,
mode: invocationContext.BindingContext.OutputMode(),
resetAfterRender: true);
var screen = new ScreenView(consoleRenderer, invocationContext.Console) { Child =
new ContentView("Hello World!")
};
screen.Render();
return 0;
}
}
Running as .\bin\Debug\net471\Program.exe
gives the output
Hello World!
However attempting to redirect output to a file with .\bin\Debug\net471\Program.exe > c:\temp\output.txt
throws a NullReferenceException:
Unhandled exception: System.NullReferenceException: Object reference not set to an instance of an object.
at System.CommandLine.Rendering.Views.ScreenView.Render()
at SampleProject.Program.<Main>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Invocation.CommandHandler.<GetResultCodeAsync>d__34.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Invocation.ModelBindingCommandHandler.<InvokeAsync>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Invocation.InvocationPipeline.<>c__DisplayClass4_0.<<BuildInvocationChain>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseErrorReporting>b__20_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass15_0.<<UseHelp>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass24_0.<<UseVersionOption>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass22_0.<<UseTypoCorrections>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseSuggestDirective>b__21_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseParseDirective>b__19_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<UseDebugDirective>b__11_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<<RegisterWithDotnetSuggest>b__10_0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass6_0.<<ConfigureConsole>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass13_0.<<UseExceptionHandler>b__0>d.MoveNext()
Right, this was just a conceptual misunderstanding on my behalf.
I didn't actually need a ScreenView at all but rather should simply have told my View (in this case, a ContentView) to render itself to the console renderer as follows:
new ContentView("Hello World!").Render(consoleRenderer, Region.EntireTerminal);
The NullReferenceException for the incorrect usage probably should be fixed, though
@flakey-bit did you ever get it to render properly? I am glad that my code is no longer throwing NullReferenceExceptions, but the output of a TableView is broken in every terminal:
namespace FileInfoRender;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.CommandLine.Rendering;
using System.CommandLine.Rendering.Views;
using System.IO;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var rootCommand = new RootCommand();
rootCommand.Handler = CommandHandler.Create<InvocationContext>(Print);
rootCommand.Invoke(args);
}
static void Print(InvocationContext context)
{
var consoleRenderer = new ConsoleRenderer(
context.Console,
context.BindingContext.OutputMode(),
true);
var tableView = new TableView<FileInfo>
{
Items = new DirectoryInfo(".").EnumerateFiles().ToList()
};
tableView.AddColumn(f => f.Name, "Name");
tableView.AddColumn(f => f.LastWriteTime, "Modified");
tableView.AddColumn(f => f.Length, "Size");
tableView.Render(consoleRenderer, Region.EntireTerminal);
}
}

With DragonFruit and ScreenView everything works, but I would like to not use DragonFruit:
static void Main(InvocationContext context, DirectoryInfo argument= null)
{
argument ??= new DirectoryInfo(".");
var consoleRenderer = new ConsoleRenderer(
context.Console,
context.BindingContext.OutputMode(),
true);
var tableView = new TableView<FileInfo>
{
Items = argument.EnumerateFiles().ToList()
};
tableView.AddColumn(f => f.Name, "Name");
tableView.AddColumn(f => f.LastWriteTime, "Modified");
tableView.AddColumn(f => f.Length, "Size");
var screen = new ScreenView(consoleRenderer, context.Console) { Child = tableView };
screen.Render();
}
Hello!
We have decided to deprecate the System.CommandLine.Rendering package: https://github.com/dotnet/command-line-api/issues/2576#Deprecating-experimental-projects
We recommend using https://www.nuget.org/packages/Spectre.Console#readme-body-tab which became the golden standard in the .NET Ecosystem