Creating a ProjectInstance for a vcxproj file throws the exception "The imported project "C:\Microsoft.Cpp.Default.props" was not found".
The re-create the issue, on a clean PC install VS2019 Community. Create a C# project with the following:
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Execution;
using Microsoft.Build.Evaluation;
namespace MSBuildTest2
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters["Configuration"] = "Debug";
parameters["Platform"] = "x64";
ProjectInstance project = new ProjectInstance(
@"..\..\..\..\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.vcxproj",
parameters,
null,
ProjectCollection.GlobalProjectCollection);
}
}
}
ConsoleApplication1 is a C++ console project created with the default settings.
The ProjectInstance constructor will throw the following exception:
Microsoft.Build.Exceptions.InvalidProjectFileException
HResult=0x80131500
Message=The imported project "C:\Microsoft.Cpp.Default.props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk. C:\Users\Me\Desktop\MSBuildTest2\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.vcxproj
Source=Microsoft.Build
StackTrace:
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)
at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImports(String directoryOfImportingFile, String importExpressionEscaped, ProjectImportElement importElement)
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.Execution.ProjectInstance.Initialize(ProjectRootElement xml, IDictionary`2 globalProperties, String explicitToolsVersion, String explicitSubToolsetVersion, Int32 solutionVersion, BuildParameters buildParameters, ILoggingService loggingService, BuildEventContext buildEventContext)
at Microsoft.Build.Execution.ProjectInstance..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection)
at Microsoft.Build.Execution.ProjectInstance..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, ProjectCollection projectCollection)
at MSBuildTest2.Program.Main(String[] args) in C:\Users\Me\Desktop\MSBuildTest2\MSBuildTest2\MSBuildTest2\Program.cs:line 19
Here are the two projects:
MSBuildTest2.zip
The problem appears to be that the $(VCTargetsPath) is not defined.
Further Info:
The application behaves differently on two machines, PC1 and PC2. PC1 is my main development PC, with multiple version of Visual Studio installed (and a lot more). PC2 is a clean install of Windows 10 with only VS2019 installed. I haven't been able to establish what is causing the different behavour.
On PC1 ProjectInstance will only work is ToolsVersion is set in the vcxproj file. If it isn't set I get the exception listed above. However, if I pass in "14.0" to ProjectInstance it does work.
Trying the same thing on PC2 it doesn't work, but I get a different error:
Microsoft.Build.Exceptions.InvalidProjectFileException
HResult=0x80131500
Message=The tools version "14.0" is unrecognized. Available tools versions are "4.0". C:\Users\Me\Desktop\MSBuildTest2\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.vcxproj
Source=Microsoft.Build
StackTrace:
at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
at Microsoft.Build.Execution.ProjectInstance.Initialize(ProjectRootElement xml, IDictionary`2 globalProperties, String explicitToolsVersion, String explicitSubToolsetVersion, Int32 solutionVersion, BuildParameters buildParameters, ILoggingService loggingService, BuildEventContext buildEventContext)
at Microsoft.Build.Execution.ProjectInstance..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectCollection projectCollection)
at Microsoft.Build.Execution.ProjectInstance..ctor(String projectFile, IDictionary`2 globalProperties, String toolsVersion, ProjectCollection projectCollection)
at MSBuildTest2.Program.Main(String[] args) in C:\Users\Me\Desktop\MSBuildTest2\MSBuildTest2\MSBuildTest2\Program.cs:line 19
On PC1 the available tools are "12.0", "14.0", "2.0", "3.5", "4.0". On PC2 I only have "4.0".
It appears that "4.0" is the tools version for VS2010 and as I said, PC2 is a clean install and only has VS2019 installed. It's as though it's using a very old version of Microsoft.Build.dll. However, on both PCs appear to be referencing and loading the same dll
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\Microsoft.Build.dll
Any help would be greatly appreciated.
If VCTargetsPath is not initialized, it means that VC++ tools CLI initialization hasn't been done. You need to run <VSInstallDir>\VC\Auxiliary\Build\VcVarsAll.bat or <VSInstallDir>\Common7\Tools\VsDevCmd.bat to prepare the environment with VC++ paths and variables such as the one you mentioned.
Note: VSInstallDir is your Visual Studio IDE install path. E.g.: %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community
Thanks for the help. I'm already using VcVars64.bat on both machines, the one that works and the one that doesn't and neither of them seem to set the VCTargetsPath environment variable. As far as I can tell the environment variable isn't set on the machine that works.
I've just checked using VsDevCmd.bat and that doesn't set it either:
**********************************************************************
** Visual Studio 2019 Developer Command Prompt v16.8.6
** Copyright (c) 2020 Microsoft Corporation
**********************************************************************
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community>set VCTargetsPath
Environment variable VCTargetsPath not defined
I found what might be a clue here:
https://github.com/mikefourie-zz/MSBuildExplorer/issues/3
"...the tool is built against the old v4.0 framework that was part of Visual Studio 2010. Because of this, it's using the MSBuild assemblies which define the $(VCTargetsPath) property to point to the directory for VS2010..."
Although I'm building with .Net Framework 4.7.2
I'm guessing the different behavior between the two machines is only having VS2019 installed and not VS2017.
In summary:
PC1: works if ToolsVersion="14.0" is set in the vcxproj file or if I pass "14.0" in to ProjectInstance (but not both)
PC2: doesn't work even if ToolsVesion is set in the vcxproj and complains if "14.0" is passed in to ProjectInstance saying only "4.0" is available (on PC1 I've found that 12.0", "14.0", "2.0", "3.5", "4.0" are available)
PC1 has has VS2012, VS2013, VS2015, VS2017 and VS2019 installed
PC2 only has 2019 installed
Checking if the tools version is not set and passing in "14.0" on PC1 does work but feels like a workaround. Passing in "14.0" doesn't work if it is set in the vcxproj file so I have to actually check the file first which is not ideal. Ideally I'd like it to just check the version in the proj file if I pass in null or just use the latest version by default.
PC2 is a more serious problem because this workaround doesn't work. It's obviously something I haven't installed causing the different behavior but I've no idea what. And I need this to work on customers machines who install my software, so I need to be sure everything is setup correctly. The fact that it says only "4.0" toolset is available is concerning.