commandline icon indicating copy to clipboard operation
commandline copied to clipboard

Console.Error should not be referenced in a static object

Open fbridger opened this issue 4 years ago • 1 comments

Changing the Console.Error throws System.ObjectDisposedException

Console.Error can be changed using Console.SetError() method, so having this as a static reference prevents using the "newly" assigned TextWriter as it keeps the referenced to the original instance which has been disposed.

"Cannot write to a closed TextWriter." at System.IO.StringWriter.Write(String value) at System.IO.TextWriter.SyncTextWriter.Write(String value) at CommandLine.Parser.<>c__DisplayClass17_01.<DisplayHelp>b__1(IEnumerable1 _, TextWriter writer) at CSharpx.MaybeExtensions.Do[T1,T2](Maybe1 maybe, Action2 action) at CommandLine.Parser.<>c__DisplayClass17_01.<DisplayHelp>b__0(IEnumerable1 errors) at CommandLine.ParserResultExtensions.WithNotParsed[T](ParserResult1 result, Action1 action) at CommandLine.Parser.DisplayHelp[T](ParserResult1 parserResult, TextWriter helpWriter, Int32 maxDisplayWidth) at CommandLine.Parser.MakeParserResult[T](ParserResult1 parserResult, ParserSettings settings) at CommandLine.Parser.ParseArguments(IEnumerable1 args, Type[] types) at TestApp.Program.Main(String[] args) in Program.cs:line 25 at TestApp.Tests.ProgramTest.Main_ShouldExecuteCommandSuccesfully(List1 args) in ProgramTest.cs:line 18

https://github.com/commandlineparser/commandline/blob/d443a51aeb3a418425e970542b3b96e9da5f62e2/src/CommandLine/Parser.cs#L22

private static readonly Lazy<Parser> DefaultParser = new Lazy<Parser>(() => new Parser(new ParserSettings { HelpWriter = Console.Error }));

fbridger avatar Mar 10 '21 23:03 fbridger

I encountered a similar issue while testing a console main function which uses this commandlineparser. The act part of multiple tests defines args and executes this:

        public async Task<ExecutionResult> executeMain(string[] args)
        {
            ExecutionResult result = new();

            using StringWriter stdOutWriter = new();

            using StringWriter stdErrWriter = new();

            TextWriter stdOut = Console.Out;
            TextWriter stdErr = Console.Error;

            Console.SetOut(stdOutWriter);
            Console.SetError(stdErrWriter);

            result.exitCode = await Konfigurator.Main(args);

            Console.SetError(stdErr);
            Console.SetOut(stdOut);

            result.stdOut = stdOutWriter.ToString();
            result.stdErr = stdErrWriter.ToString();

            Console.WriteLine("fin");
            return result;
        }

This works as expected as long as none of the commandline args are declared as 'required'. In that case the second test which runs fails with that 'Cannot write to a closed TextWriter' exeption. It seems to me that the out / error streams are manipulated but not properly restored after displaying the help message on an validation error.

ervinpeters avatar Mar 12 '24 11:03 ervinpeters