3F/MvsSln

Cannot load UWP projects

mrexodia opened this issue · 9 comments

Thanks a lot for your great library! When going over a rather big solution I found a problem related to UWP project. I worked around the issue by simply ignoring the UWP projects for now.

Project:

https://github.com/mrexodia/ClangPowerToolsUwpTest

Code:

using net.r_eg.MvsSln;
using System;

namespace VsProjectStuff
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var sln = new Sln(@"c:\CodeBlocks\ClangPowerToolsUwpTest\UwpTest.sln", SlnItems.All))
                foreach (var project in sln.Result.ProjectItems)
                    Console.WriteLine($"guid: {project.pGuid}, path: {project.path}");
        }
    }
}

Exception:

Invalid static method invocation syntax: "[Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKDisplayName($(SDKIdentifier), $(SDKVersion))". Method 'Microsoft.Build.Utilities.ToolLocationHelper.GetPlatformSDKDisplayName' not found. Static method invocation should be of the form: $([FullTypeName]::Method()), e.g. $([System.IO.Path]::Combine(`a`, `b`)). 

   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(IElementLocation elementLocation, String resourceName, Object arg0, Object arg1)
   at Microsoft.Build.Evaluation.Expander`2.Function`1.Execute(Object objectInstance, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertyBody(String propertyBody, Object propertyValue, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveTypedAndEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.ExpandIntoStringLeaveEscaped(String expression, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluatePropertyElement(ProjectPropertyElement propertyElement)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluatePropertyGroupElement(ProjectPropertyGroupElement propertyGroupElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate()
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(IEvaluatorData`4 data, ProjectRootElement root, ProjectLoadSettings loadSettings, Int32 maxNodeCount, PropertyDictionary`1 environmentProperties, ILoggingService loggingService, IItemFactory`2 itemFactory, IToolsetProvider toolsetProvider, ProjectRootElementCache projectRootElementCache, BuildEventContext buildEventContext, ProjectInstance projectInstanceIfAnyForDebuggerOnly)
   at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation)
   at Microsoft.Build.Evaluation.Project.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection, ProjectLoadSettings loadSettings)
   at net.r_eg.MvsSln.Core.IsolatedEnv.Load(String path, IDictionary`2 properties) in D:\prg\projects\MvsSln\MvsSln\MvsSln\Core\IsolatedEnv.cs:line 335
   at net.r_eg.MvsSln.Core.IsolatedEnv.GetOrLoadProject(ProjectItem pItem, IDictionary`2 properties) in D:\prg\projects\MvsSln\MvsSln\MvsSln\Core\IsolatedEnv.cs:line 210
   at net.r_eg.MvsSln.Core.IsolatedEnv.Load(IEnumerable`1 pItems) in D:\prg\projects\MvsSln\MvsSln\MvsSln\Core\IsolatedEnv.cs:line 312
   at net.r_eg.MvsSln.Core.IsolatedEnv.LoadProjects(IEnumerable`1 pItems) in D:\prg\projects\MvsSln\MvsSln\MvsSln\Core\IsolatedEnv.cs:line 266
   at net.r_eg.MvsSln.Core.SlnParser.Parse(StreamReader reader, SlnItems type) in D:\prg\projects\MvsSln\MvsSln\MvsSln\Core\SlnParser.cs:line 154
   at net.r_eg.MvsSln.Core.SlnParser.Parse(String sln, SlnItems type) in D:\prg\projects\MvsSln\MvsSln\MvsSln\Core\SlnParser.cs:line 103
   at net.r_eg.MvsSln.Sln..ctor(String file, SlnItems type) in D:\prg\projects\MvsSln\MvsSln\MvsSln\Sln.cs:line 54
   at VsProjectStuff.Program.Main(String[] args) in C:\Users\Admin\Documents\Visual Studio 2017\Projects\VsProjectStuff\VsProjectStuff\Program.cs:line 14
3F commented

Thanks for the report. Temporarily, you can try to use flag:

SlnItems.All &~ SlnItems.LoadDefaultData

this probably will help to get $"guid: {project.pGuid}, path: {project.path}" for your case.

About exception, looks like problem from internal MS logic. I'll check this later to be sure.
You can also try solution with overriding - #4 (comment)

Hi,

That code was just a minimal example I tested, the actual code also used sln.Result.Env.Projects unfortunately...

It turned out that for my use case UWP needed special treatment anyway (converting a big solution from AdditionalLinkLibraries to references). Thanks for the advice though!

3F commented
3F commented

@mrexodia I've checked this problem through other version - Microsoft.Build.dll v15.7.179

Seems it solves most of our other related issues! But unfortunately this requires .netfx 4.6 (4.5 for latest v14.x) and ...

Looks like most of updated MS libraries, today, only for .netfx 4.6+ <_<

For .netfx 4.0 it still uses obsolete logic, and fully don't understand some global changes starting with 15.0

I don't know, ... I really don't want to change platform version for this project.

As for temp solution

Try overriding, as I said before, with this custom build from nuget packages.

Works for me:

  1. Just add an updated Microsoft.Build.dll for your project.

  2. Override loading, for example: https://github.com/3F/MvsSln/wiki/Examples-override-MS-Project

    • Let me know, if you can't apply this examples for your case.
  3. Set AutoGenerateBindingRedirects property for host project because of different Microsoft.Build.dll:

<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  1. Use MvsSln as before.

Hey, thanks for the follow up! For my project I just copied your project to my repository and made the changes required to make it work for me.

Generally I see that lots of projects have multiple targets in their nuget packages. Perhaps you could include a 4.0 target with the old library and a 4.6 target with the updated library. Probably not the best solution, but at least you keep some support for 4.0...

3F commented

Perhaps you could include a 4.0 target with the old library and a 4.6 target with the updated library.

That is, this problems* will be anyway for those who will use 4.0 :)
the all from this tracker at this time, btw :p

I also raised new issue into msbuild project, let's see what they advise.

3F commented

@mrexodia What do you think about dynamic referencing to the new Microsoft.Build.dll implementations? (from GAC, official NuGet packages, custom paths)

I think this is more right way for our case because these problems are directly related to specific MS implementation. I mean, there is not because of target platforms. (mainly)

Unfortunately, they implements Project 'as is' without any abstraction layer. But my idea is still to use an Project type from GAC just for an runtime binding. However, with leaving options for loading new implementation at runtime and without hard class inheritance.

Something similar I was already implementing in my old vssbe projects, but there was through common interface as basic abstraction for all their components.

Also, I did not test this way, but seems the main problem probably will be for an compatibilities of specific Project's implementation (I remember some incompatible changes with their methods from different dlls). But more probably it will help better. Hmm,


tl;dr for end users the question is related to optional requirements for definition path to custom Microsoft.Build.dll (+ all its dependencies).

Probably some of this can be also encapsulated to search from GAC by version, for example from latest netfx 4.7.2 and so on. But mainly, this will require additional user logic for including something other (from nuget, or GAC etc)

Hey,

For me it doesn't matter too much anymore to be honest... I wouldn't be opposed to updating the target framework version, since this stuff is all running on whatever environment I want anyway. However, recently we dropped UWP support so I guess it won't be an issue anymore going forward...

Thanks for the follow up though, your library has been (and is) tremendously useful for us and I will try to get some appreciative donation in your direction 💯

3F commented

@mrexodia I see, thanks for the info. I'm also glad that's still helpful tool :)

Well anyway, I'll consider new way later for future .net core distr etc.