我正在尝试加载一个项目并构建它,但是每次我尝试加载它时都会抛出此错误:
Microsoft.Build.Exceptions.InvalidProjectFileException: 'The default XML namespace of the project must be the MSBuild XML namespace. If the project is authored in the MSBuild 2003 format, please add xmlns="http://schemas.microsoft.com/developer/msbuild/2003" to the <Project> element. If the project has been authored in the old 1.0 or 1.2 format, please convert it to MSBuild 2003 format. C:\Users\mega\source\repos\Logger Builder\Logger Builder\bin\Debug\net472\git\discord-token-logger-zip\logger\logger.csproj'
我的代码是:
var collection = new ProjectCollection();
var project = collection.LoadProject(@"./git\logger-zip\logger\logger.csproj");
project.Build();
.Net Framework 项目通常使用“遗留”项目样式。 (在 Visual Studio 2022 中,创建新的 .Net Framework 项目将创建旧样式项目。)
旧式项目需要在
Project
元素上使用特定的命名空间:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ...>
您尝试加载的项目是“SDK”样式的项目。在 SDK 风格的项目中,命名空间是可选的。
<Project Sdk="Microsoft.NET.Sdk">
SDK 风格于 2017 年左右引入,以支持 .Net Core/.Net 5 及更高版本。
我的猜测是,包含失败的
collection.LoadProject()
调用的项目正在使用本地安装的 .Net Framework 版本的 Microsoft.Build 程序集,该版本可能是 4.0.0.0。该版本早于 SDK 样式项目格式的创建。 (MSBuild 4 大约是 2010 年。)
如果您使用的是旧库,请将其替换为 Microsoft.Build NuGet 包。
查看Roslyn如何加载解决方案和项目,我发现这可能是因为您没有事先设置这些环境变量:
如果您尝试加载 Microsoft.NET.Sdk.* 类型项目,您可以尝试使用
MSBuildLocator
包中的 Microsoft.Build.Locator
类来确定这些环境变量的值。
以下代码从您最新的 Visual Studio 版本中提取它们。
using Microsoft.Build.Construction; // Package: Microsoft.Build
using Microsoft.Build.Evaluation; // Package: Microsoft.Build
using Microsoft.Build.Locator; // Package: Microsoft.Build.Locator
var solutionFilePath = @"PATH TO YOUR SOLUTION FILE";
if (!MSBuildLocator.IsRegistered)
{
// Locate the right SDK for this particular project; MSBuildLocator ensures in this case the first one is the preferred one.
var options = new VisualStudioInstanceQueryOptions
{
DiscoveryTypes = DiscoveryType.DotNetSdk,
WorkingDirectory = Path.GetDirectoryName(solutionFilePath)
};
VisualStudioInstance instance =
MSBuildLocator.QueryVisualStudioInstances(options)
.OrderByDescending(o => o.Version)
.First();
string dotNetSdkPath = instance.MSBuildPath;
foreach (KeyValuePair<string, string> item in new Dictionary<string, string>
{
["MSBUILD_EXE_PATH"] = Path.Combine(dotNetSdkPath, "MSBuild.dll"),
["MSBuildExtensionsPath"] = dotNetSdkPath,
["MSBuildSDKsPath"] = Path.Combine(dotNetSdkPath, "Sdks")
})
{
Environment.SetEnvironmentVariable(item.Key, item.Value);
}
}
SolutionFile solutionFile = SolutionFile.Parse(solutionFilePath);
ProjectCollection projects = new ProjectCollection();
foreach (ProjectInSolution projectInSolution in solutionFile
.ProjectsInOrder
.Where(pr => pr.ProjectType is SolutionProjectType.KnownToBeMSBuildFormat))
{
projects.LoadProject(projectInSolution.AbsolutePath);
}
此答案假设您没有使用 Mono 或 .NET Framework 或其他版本的 MSBuild。如果您这样做,只需参考上面链接的 Roslyn 存储库即可。