commandlineparser / commandline

The best C# command line parser that brings standardized *nix getopt style, for .NET. Includes F# support
MIT License
4.53k stars 477 forks source link

TypeLoadException on generating help text #779

Open Flohack74 opened 2 years ago

Flohack74 commented 2 years ago

Hi there,

a customer of ours gets this stack trace when our application is starting, and we are not able to determine whats going on. I traced it back in the source code to the first reflection call to getting a license attribute out of the executing assembly, but since our application is crashing immediately with no output I have to rely on whats event viewer has. And event viewer unfortunately does not tell me which type could not be loaded and why. Any ideas might be helpful:


Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.TypeLoadException
at System.ModuleHandle.ResolveType(System.Reflection.RuntimeModule, Int32, IntPtr*, Int32, IntPtr*, Int32, System.Runtime.CompilerServices.ObjectHandleOnStack)
at System.ModuleHandle.ResolveTypeHandleInternal(System.Reflection.RuntimeModule, Int32, System.RuntimeTypeHandle[], System.RuntimeTypeHandle[])
at System.Reflection.RuntimeModule.ResolveType(Int32, System.Type[], System.Type[])
at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(System.Reflection.CustomAttributeRecord, System.Reflection.MetadataImport, System.Reflection.Assembly ByRef, System.Reflection.RuntimeModule, System.Reflection.MetadataToken, System.RuntimeType, Boolean, System.Object[], System.Collections.IList, System.RuntimeType ByRef, System.IRuntimeMethodInfo ByRef, Boolean ByRef, Boolean ByRef)
at System.Reflection.CustomAttribute.GetCustomAttributes(System.Reflection.RuntimeModule, Int32, Int32, System.RuntimeType, Boolean, System.Collections.IList, Boolean)
at System.Reflection.CustomAttribute.GetCustomAttributes(System.Reflection.RuntimeAssembly, System.RuntimeType)
at System.Reflection.RuntimeAssembly.GetCustomAttributes(System.Type, Boolean)
at System.Attribute.GetCustomAttributes(System.Reflection.Assembly, System.Type, Boolean)
at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.Reflection.Assembly)
at CommandLine.Infrastructure.ReflectionHelper.GetAttribute[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]()
at CommandLine.Text.HelpText.AutoBuild[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](CommandLine.ParserResult`1<System.__Canon>, System.Func`2<CommandLine.Text.HelpText,CommandLine.Text.HelpText>, System.Func`2<CommandLine.Text.Example,CommandLine.Text.Example>, Boolean, Int32)
at CommandLine.Text.HelpText.AutoBuild[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](CommandLine.ParserResult`1<System.__Canon>, Int32)
at CommandLine.Parser+<>c__DisplayClass17_0`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].<DisplayHelp>b__1(System.Collections.Generic.IEnumerable`1<CommandLine.Error>, System.IO.TextWriter)
at CSharpx.MaybeExtensions.Do[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](CSharpx.Maybe`1<System.Tuple`2<System.__Canon,System.__Canon>>, System.Action`2<System.__Canon,System.__Canon>)
at CommandLine.Parser+<>c__DisplayClass17_0`1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].<DisplayHelp>b__0(System.Collections.Generic.IEnumerable`1<CommandLine.Error>)
at CommandLine.ParserResultExtensions.WithNotParsed[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](CommandLine.ParserResult`1<System.__Canon>, System.Action`1<System.Collections.Generic.IEnumerable`1<CommandLine.Error>>)
at CommandLine.Parser.DisplayHelp[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](CommandLine.ParserResult`1<System.__Canon>, System.IO.TextWriter, Int32)
at CommandLine.Parser.MakeParserResult[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](CommandLine.ParserResult`1<System.__Canon>, CommandLine.ParserSettings)
at CommandLine.Parser.ParseArguments[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](System.Collections.Generic.IEnumerable`1<System.String>)
at App.Program.Main(System.String[])```
elgonzo commented 2 years ago

I cannot really help, but i noticed something really odd. Note that the output mentions Framework Version: v4.0.30319. However, the stacktrace contains a call to System.Reflection.CustomAttributeExtensions.GetCustomAttributes<TAttribute>(this Assembly assy). According to the documentation, this method should only be available in .NET framework 4.5 and newer. Still, this call was clearly resolved and being executed, as evidenced by the stack trace, which would make me rather suspicious. [*]

I can't tell what's going on, but perhaps check if by accident the wrong CommandLineParser library has been included with your software. Check if the CommandLineParser library file bundled with your software matches the framework target of your software.

If you look in CommandLineParser's ReflectionHelper.GetAttribute<TAttribute>() method:

https://github.com/commandlineparser/commandline/blob/d443a51aeb3a418425e970542b3b96e9da5f62e2/src/CommandLine/Infrastructure/ReflectionHelper.cs#L56-L60

you will notice that in the library version for framework 4.0 the method Assembly.GetCustomAttributes(Type, Boolean) should be called here instead, further enforcing my suspicion that you might be using the CommandLineParser library version for .NET 4.5 and newer instead of the library version for .NET 4.0.


[*] Weirdly, mscorlib.dll version 4.0.0.0 actually contains the class System.Reflection.CustomAttributeExtensions, but it is not usable/accessible in a C# project targetting .NET 4.0. I speculate, that this version of mscorlib.dll is shared across all .NET 4.x versions installed on a machine, thus -- assuming .NET framework 4.5, 4.7 or 4.8 are installed -- it would also contain types that are not part of .NET 4.0.

Flohack74 commented 2 years ago

Ok thanks will take a look!