jzabroski / Home

My technology radar
17 stars 0 forks source link

.NET Assembly Load Customer service script #5

Open jzabroski opened 4 years ago

jzabroski commented 4 years ago
  1. Ask for vsconfig export
  2. Ask for environment variables
  3. Ask for runtimeconfig.json
  4. Ask for deps.json
  5. Ask for global.json
  6. Is the problem with Azure Functions?
    1. Did they try <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>?
  7. Is the problem with a .NET Core CLI Tool?
    1. Did they install the tool globally?
    2. Did they install the tool locally via tool manifest (.NET Core 3.0+)?
  8. Mention DirtyAssemblyResolveHelper workaround used by MSBuild, Fody and BenchmarkDotNet. Would this solve the problem?

See also: https://github.com/dotnet/runtime/issues/29223#issuecomment-483342626

See also: https://github.com/dotnet/standard/issues/481 for how Microsoft approached this in 2017

jzabroski commented 3 years ago

See: https://github.com/peters/assemblyinfo

This small library uses cecil to inspect MSIL code found in .NET assemblies instead of Assembly.Load which ensures that you do not have to load it's dependencies beforehand. This is particularly useful if you just want to know what .NET target framework an assembly is targeting without running the risk of catching an exception from Assembly.Load because of a missing dependency.

jzabroski commented 3 years ago

Stephen Cleary gave me the following examples:

How do you know what runtime dependencies you have if your runtime version is a moving target?

Yes. This is a problem.

As an function app writer, I stay up-to-date, with a GitHub Action that updates all my dependencies nightly. This seems to be working well enough, and will do so until breaking changes occur (like this issue, which was added a few Functions.Sdk patch-versions ago). I minimize my library usage to minimize the number of breaking changes. I would expect most Functions apps are very simple and only depend on a handful of libraries.

As a library author, I'm not sure what the best approach would be. Currently my libraries all just take dependencies of "whatever version was current at the time I wrote them", which is less than ideal. I've been thinking of auto-updating all of them, too with autogenerated semver updates, but that can cause a lot of downstream churn. I have no idea what the best answer is there.

jzabroski commented 3 years ago

See: https://github.com/dotnet/docs/issues/9202#issuecomment-469378999

There's still a general problem with de-centralized assembly loaders like Powershell. If cmdlet A relies on functionality from version 1.1.3 of some assembly, but cmdlet B runs first and loads version 1.1.0 the assembly, then cmdlet A may fail to run. For a traditional EXE a binding redirect would work, but one can't edit powershell's config like that.

-- David Shiflet @shueybubbles

jzabroski commented 3 years ago

Sometimes, prior to run-time assembly loading, you can get Nuget package conflicts:

CS1705 C# Assembly with identity uses which has a higher version than referenced assembly with identity

The fix for this is to forcibly delete all bin and obj folders in your solution, and possibly restart Visual Studio.

However, when you do this, you get a clue as to what went wrong:

D:\Users\John.Zabroski\source\Core.targets(32,5): error MSB3231: Unable to remove directory " D:\Users\John.Zabroski\source\source\packages". Access to the path 'DotNetCompilerPlatformTasks.dll' is denied. [D:\Users\John.Zabroski\source\build.targets]

See: https://github.com/dotnet/msbuild/issues/2478#issuecomment-769824024

jzabroski commented 2 years ago

See also: https://docs.microsoft.com/en-us/nuget/concepts/dependency-resolution