MSBuild执行.targets自定义代码报找不到Microsoft.Win32.Registry引用
问题描述
大家好,祝各位一切顺利。
我在.targets文件中执行自定义RoslynCodeTaskFactory代码时出现报错,当前项目使用的目标框架为net6.0-windows。
脱敏后的简化自定义任务代码如下:
<UsingTask TaskName="CommonFilesDirPath" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll"> <ParameterGroup> <CommonFilesDir ParameterType="System.String" Output="true" /> </ParameterGroup> <Task> <Reference Include="Microsoft.Win32.Registry"/> <Using Namespace="Microsoft.Win32.Registry"/> <Code Type="Fragment" Language="cs"> <![CDATA[ CommonFilesDir = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "CommonFilesDir"); Success = true; ]]> </Code> </Task> </UsingTask>
提取属性的Target配置如下:
<Target Name="FindInstallDir" BeforeTargets="Build"> <CommonFilesDirPath> <Output TaskParameter="CommonFilesDir" PropertyName="CommonFilesDir" /> </CommonFilesDirPath> </Target>
执行dotnet build时抛出如下错误:
PS C:\git\Extension> dotnet build Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET Copyright (C) Microsoft Corporation. All rights reserved. Determining projects to restore... All projects are up-to-date for restore. Extension -> C:\git\Extension\src\Extension\bin\Debug\net6.0-windows\Extension.dll C:\git\Extension\src\Extension\Extension.csproj_Custom.targets(301,5): error MSB3755: Could not find reference "Microsoft.Win32.Registry". If this reference is required by your code, you may get compilation errors. [C:\git\Extension\src\Extension\Extension.csproj] C:\git\Extension\src\Extension\Extension.csproj_Custom.targets(301,5): error MSB4175: The task factory "RoslynCodeTaskFactory" could not be loaded from the assembly "C:\Program Files\dotnet\sdk\6.0.302\Microsoft.Build.Tasks.Core.dll". The task factory must return a value for the "TaskType" property. [C:\git\Extension\src\Extension\Extension.csproj] Build FAILED.
解决方案
两个报错的核心诱因共三个,按优先级修复即可:
- 优先使用内置属性替代自定义任务:你要读取的
CommonFilesDir是Windows系统公共配置,MSBuild已经提供开箱即用的内置属性,完全不需要写自定义任务读注册表:- 64位系统下64位程序的公共文件目录直接用
$(CommonProgramFiles),默认值为C:\Program Files\Common Files - 32位程序的公共文件目录直接用
$(CommonProgramFiles(x86)),默认值为C:\Program Files (x86)\Common Files
直接删除自定义任务和对应Target,在构建逻辑中直接引用上述属性即可,从根源避免所有自定义任务的编译问题。
- 64位系统下64位程序的公共文件目录直接用
- 如果必须使用自定义Registry逻辑读值,先修复命名空间引用错误:代码中写的
<Using Namespace="Microsoft.Win32.Registry"/>是错误的,Microsoft.Win32.Registry是类的全限定名,正确的命名空间是Microsoft.Win32,需要修改为:<Using Namespace="Microsoft.Win32"/> - 修复程序集引用找不到的问题:RoslynCodeTaskFactory编译内联任务时运行在MSBuild进程上下文,不会自动加载项目的NuGet依赖,直接写
<Reference Include="Microsoft.Win32.Registry"/>无法定位到程序集:- 先在
.csproj文件中添加对应包引用,设置为构建时私有资产,不会输出到最终生成产物:<PackageReference Include="Microsoft.Win32.Registry" Version="6.0.0" PrivateAssets="All" /> - 修改
.targets中的Reference节点,通过NuGet包根路径指定程序集的完整位置:<Reference Include="Microsoft.Win32.Registry" HintPath="$(NuGetPackageRoot)microsoft.win32.registry\6.0.0\lib\net6.0\Microsoft.Win32.Registry.dll" />
- 先在
- MSB4175是前序问题导致的连锁报错:内联任务因为引用缺失、命名空间错误编译失败时,任务工厂无法返回合法的TaskType,只要修复上述问题,这个错误会自动消失,不需要单独处理MSBuild或SDK的安装。
内容的提问来源于stack exchange,提问作者Trushar Mistry
相关产品推荐
相关产品推荐

