phmonte / Buildalyzer

A utility to perform design-time builds of .NET projects without having to think too hard about it.
MIT License
605 stars 95 forks source link

Attempting to analyse old-style CSProject file - Method initialize in type PipeLogger does not have an implementation #188

Open FraserGreenroyd opened 2 years ago

FraserGreenroyd commented 2 years ago

Hi!

I've been trying to use Buildalyzer to analyse CSProject files for compliance to guidelines with the framework I'm working in. This works well for netstandard2.0 and net5.0 CSProject files, but when trying to analyse older-style CSProject files for net452 and net472, I get the following error:

System.TypeLoadException: Method 'Initialize' in type 'MsBuildPipeLogger.PipeLogger' from assembly 'MsBuildPipeLogger.Logger, Version=1.1.3.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
   at Buildalyzer.ProjectAnalyzer.GetCommand(BuildEnvironment buildEnvironment, String targetFramework, String[] targetsToBuild, String pipeLoggerClientHandle, String& arguments)
   at Buildalyzer.ProjectAnalyzer.BuildTargets(BuildEnvironment buildEnvironment, String targetFramework, String[] targetsToBuild, AnalyzerResults results)
   at Buildalyzer.ProjectAnalyzer.Build(String targetFramework, BuildEnvironment buildEnvironment)
   at BH.Adapter.CSProject.CSProjectAdapter.IRead(Type type, IList indices, ActionConfig actionConfig)

I have tried to set up a custom ILoggerFactory to just ignore this (as I generally am not caring too much for the reports of the logging at this stage) but this didn't work.

I have also tried it with ensuring that the EnvironmentOptions.Preference is set to Framework rather than Core but the same error occurs.

The code I currently have for this is as follows:

ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
StringWriter log = new StringWriter();

AnalyzerManagerOptions opt = new AnalyzerManagerOptions() { LoggerFactory = factory, LogWriter = log };
AnalyzerManager analyzerManager = new AnalyzerManager(opt);
ProjectAnalyzer projectAnalyzer = analyzerManager.GetProject(m_fileSettings.GetFullFileName()) as ProjectAnalyzer;

ProjectFile projectFile = new ProjectFile();
projectFile.TargetNETVersions = projectAnalyzer.ProjectFile.TargetFrameworks.ToList();
projectFile.OutputPaths = ExtractOutputPaths();

try //Code in a try-catch simply to catch the initialize error for old-style csproj files and avoid the app crashing completely
{
    EnvironmentOptions options = new EnvironmentOptions();
    options.DesignTime = true;
    /*options.Preference = EnvironmentPreference.Core; //This if-block wasn't working to fix the problem so currently commented out but included in this snippet in case anyone can point out how I'm using it badly!
    if (!projectFile.TargetNETVersions.Contains("netstandard2.0"))
        options.Preference = EnvironmentPreference.Framework;*/

    AnalyzerResult result = (projectAnalyzer.Build(options) as AnalyzerResults).First() as AnalyzerResult;

    var refs = result.Items.Where(x => x.Key == "Reference").FirstOrDefault();
    if(refs.Value != null) //If the refs.value is null then it means there was no references in the csproject file
        projectFile.References = Convert.ToAssemblyReference(refs.Value.ToList());

    projectFile.TargetNETVersions = projectAnalyzer.ProjectFile.TargetFrameworks.ToList();
}
catch(Exception e)
{
    projectFile.AnalysisErrors = e.ToString();
}

Any help with this will be gratefully received! Thanks in advance :smile:

daveaglick commented 2 years ago

Interesting, I haven't seen this particular error before. It's almost like your app has a reference to MsBuildPipeLogger but the logger isn't being loaded into your assembly context. What happens if you add a direct reference to https://www.nuget.org/packages/MsBuildPipeLogger.Logger/? I'm also wondering if there's a version mismatch - what's your full set of referenced packages in the app that's using Buildalyzer (not the app being analyzed)?

FraserGreenroyd commented 2 years ago

Hiya, so I appeared to have a MsBuildPipeLogger.Logger.dll file in my build folder, I'm presuming that comes in via one of the dependencies to Buildalyzer itself, but have added MsBuildPipeLogger.Logger and copied all DLLs I can find to the execution folder but still the same error.

For the app using Buildalyzer I have the following packages installed now:

There are then DLL dependencies to the parts of BHoM the project is building on top of too.

I have also found that if I try to run the analyser on a .NetFramework472 project file (which throws the above error) and then try to run it on a .netstandard20 project file, the second attempt throws the same error still. However, if I boot cleanly and run the .netstandard20 project file first, then it works.

I did also try building both the Buildalyzer and MsBuildPipeLogger projects from source just to debug through and make sure I was using the absolutely latest up to date versions of the code though that did not yield any positive results.