如何让msbuild /restore在独立/非SDK项目文件中生效?
我完全懂你的困扰——你想用MSBuild的/restore命令还原PackageReference,但你的项目是编排多个构建的脚本,引入Microsoft.NET.Sdk会带来奇怪的错误,可不用SDK的话,/restore又会被直接忽略,最终导致RoslynCodeTaskFactory包没被下载,触发MSB4036任务找不到的错误。
核心问题在于:非SDK风格的MSBuild项目默认没有内置NuGet还原逻辑,所以必须手动添加还原相关的目标配置,才能让/restore命令生效。下面是具体的解决方案:
修改后的项目文件
我们只需要导入NuGet还原的核心目标文件,并调整任务的引用路径即可:
<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <!-- 导入NuGet还原目标,激活/restore命令功能 --> <Import Project="$(MSBuildExtensionsPath)\Microsoft\NuGet\Microsoft.PackageRestore.targets" Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\NuGet\Microsoft.PackageRestore.targets')" /> <PropertyGroup> <!-- 明确启用包还原开关 --> <RestorePackages>true</RestorePackages> </PropertyGroup> <ItemGroup> <PackageReference Include="RoslynCodeTaskFactory" Version="2.0.7" /> </ItemGroup> <Target Name="Build"> <HelloWorld/> </Target> <!-- 直接指向NuGet缓存中的DLL,非SDK项目不会自动生成包路径属性 --> <UsingTask AssemblyFile="$(NuGetPackageRoot)roslyncodetaskfactory\2.0.7\tools\RoslynCodeTaskFactory.dll" TaskFactory="CodeTaskFactory" TaskName="HelloWorld"> <Task> <Code Type="Fragment" Language="cs"> <![CDATA[ Console.WriteLine("Hello, world!"); ]]> </Code> </Task> </UsingTask> </Project>
关键改动说明
导入还原目标文件:
Microsoft.PackageRestore.targets是MSBuild官方提供的NuGet还原核心配置,导入它之后,/restore命令就会触发包下载流程,把PackageReference中的包同步到本地NuGet缓存。调整任务引用路径:
非SDK项目不会自动为PackageReference生成类似$(RoslynCodeTaskFactory)的属性,所以我们直接用$(NuGetPackageRoot)(默认指向用户目录下的.nuget\packages)构建DLL的完整路径,确保任务能找到正确的程序集。启用还原开关:
设置<RestorePackages>true</RestorePackages>确保还原逻辑不会被默认配置跳过,保证/restore命令能正常执行。
验证步骤
先执行还原命令:
"\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\MSBuild.exe" /restore helloworld.proj此时会看到MSBuild开始下载
RoslynCodeTaskFactory包的日志。再执行构建命令:
"\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\MSBuild.exe" helloworld.proj这次就能成功输出
Hello, world!,不会再出现MSB4036错误。
内容的提问来源于stack exchange,提问作者binki

