读取注册表项失败,MSBuild扩展包4.0

读取注册表项失败,MSBuild扩展包4.0,msbuild,registry,msbuild-4.0,Msbuild,Registry,Msbuild 4.0,我正在使用MSBuild扩展包4.0进行本地开发部署。使用类MSBuild.ExtensionPack.Computer.Registry读取注册表项(以获取安装目录)时,指出路径无效失败。我认为这是由于msbuild是一个32位进程,因此它只能看到: HKEY_LOCAL_MACHINE\Software\SysWow6432\* 而不是 HKEY_LOCAL_MACHINE\Software\* 有没有人找到了一种方法来解决这个问题,而不必重新开发自定义工具 我的实际剧本: <MS

我正在使用MSBuild扩展包4.0进行本地开发部署。使用类MSBuild.ExtensionPack.Computer.Registry读取注册表项(以获取安装目录)时,指出路径无效失败。我认为这是由于msbuild是一个32位进程,因此它只能看到:

HKEY_LOCAL_MACHINE\Software\SysWow6432\*
而不是

HKEY_LOCAL_MACHINE\Software\*
有没有人找到了一种方法来解决这个问题,而不必重新开发自定义工具

我的实际剧本:

<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\MSCRM" Value="CRM_Server_InstallDir">
  <Output PropertyName="CrmPath" TaskParameter="Data"/>
</MSBuild.ExtensionPack.Computer.Registry>

您是否已尝试使用MSBuilds内置支持读取注册表

<PropertyGroup>
    <CrmPath>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM@CRM_Server_InstallDir</CrmPath>
</PropertyGroup>


编辑

即使您正在处理一个多目标环境,您也可以使用内置方法解决这个问题

<!-- MSBuild 3.5 x86 / AnyCPU -->
<PropertyGroup Condition=" '$(MSBuildToolsPath)' == '$(windir)\Microsoft.NET\Framework\v3.5' AND '$(Platform)' == 'AnyCPU' ">
    <CrmPath>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\SysWow64\*)</CrmPath>
</PropertyGroup>

<!-- MSBuild 3.5 x64 -->
<PropertyGroup Condition=" '$(MSBuildToolsPath)' == '$(windir)\Microsoft.NET\Framework64\v3.5' AND '$(PLatform)' == 'x64' ">
    <CrmPath>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\*)</CrmPath>
</PropertyGroup>

$(注册表:HKEY\U LOCAL\U MACHINE\SOFTWARE\SysWow64\*)
$(注册表:HKEY\U LOCAL\U MACHINE\SOFTWARE\*)

MSBuild通常能够判断它所处理的环境,因此您可以满足各种可能的组合,并在所有类型的计算机上使用相同的脚本。

我通过查看.NET 4.0的新功能解决了这个问题(如此处所建议的:)

现在,如果需要32位或64位值,我可以在查找中指定:

<GetWindowsRegistryValue Key="SOFTWARE\Microsoft\MSCRM" Value="CRM_Server_InstallDir" Hive="LocalMachine" View="Registry64">
  <Output PropertyName="CrmPath" TaskParameter="Setting"/>
</GetWindowsRegistryValue>

以及自定义(快速和肮脏)任务:

namespace Utilities.CustomBuildTasks
{
使用制度;
使用Microsoft.Build.Framework;
使用Microsoft.Win32;
/// 
///定义用于检索注册表值的自定义任务。
/// 
公共类GetWindowsRegistryValue:ITask
{
/// 
///获取或设置与任务关联的生成引擎。
/// 
/// 
///与任务关联的生成引擎。
公共IBuildEngine构建引擎
{
得到;
设置
}
/// 
///获取或设置与任务关联的任何主机对象。
/// 
/// 
///与任务关联的主机对象。
公共ITaskHost主机对象
{
得到;
设置
}
/// 
///获取或设置密钥。
/// 
///注册表项。
[必需]
公共字符串密钥
{
得到;
设置
}
/// 
///获取或设置该值。
/// 
///价值。
[必需]
公共字符串值
{
得到;
设置
}
/// 
///获取或设置配置单元。
/// 
///注册表配置单元。
[必需]
公共字符串蜂箱
{
得到
{
返回此.hive.ToString();
}
设置
{
this.hive=(RegistryHive)Enum.Parse(typeof(RegistryHive),value);
}
}
/// 
///配置单元枚举值。
/// 
专用注册蜂箱;
/// 
///获取或设置视图。
/// 
///视图(64位/32位)。
[必需]
公共字符串视图
{
得到
{
返回此.view.ToString();
}
设置
{
this.view=(RegistryView)Enum.Parse(typeof(RegistryView),value);
}
}
/// 
///视图枚举值。
/// 
私有注册视图;
/// 
///获取或设置设置。
/// 
///背景。
[输出]
公共字符串设置
{
得到;
设置
}
/// 
///执行任务。
/// 
/// 
///如果任务成功执行,则为true;否则为false。
/// 
公共bool Execute()
{
尝试
{
var baseKey=RegistryKey.OpenBaseKey(this.hive,this.view);
var subKey=baseKey.OpenSubKey(this.Key);
if(子键==null)
{
返回false;
}
this.Setting=subKey.GetValue(this.Value.ToString();
返回true;
}
捕获(例外)
{
返回false;
}
}
}
}

如果您使用的是MSBuild 4.0,还可以使用内置属性函数GetRegistryValueFromView(记录在)。 此函数允许指定64位或32位视图(或两者)

您的电话如下所示:

<PropertyGroup>
    <CrmPath>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM', 'CRM_Server_InstallDir', null, RegistryView.Registry64, RegistryView.Registry32))</CrmPath>
</PropertyGroup>

$([MSBuild]::GetRegistryValueFromView('HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft\MSCRM','CRM\U Server\U InstallDir',null,RegistryView.Registry64,RegistryView.Registry32))

使用MSBuild扩展包4.0,您还可以创建、修改和删除注册表项和值。但如果你只打算阅读,你可以先看一下@Thierry answer

对于x64注册表节点视图

<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryView="Registry64" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\MSCRM" Value="CRM_Server_InstallDir">
    <Output PropertyName="CrmPath" TaskParameter="Data"/>
</MSBuild.ExtensionPack.Computer.Registry>
<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryView="Registry32" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\MSCRM" Value="CRM_Server_InstallDir">
    <Output PropertyName="CrmPath" TaskParameter="Data"/>
</MSBuild.ExtensionPack.Computer.Registry>

对于x86注册表节点视图

<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryView="Registry64" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\MSCRM" Value="CRM_Server_InstallDir">
    <Output PropertyName="CrmPath" TaskParameter="Data"/>
</MSBuild.ExtensionPack.Computer.Registry>
<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryView="Registry32" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\MSCRM" Value="CRM_Server_InstallDir">
    <Output PropertyName="CrmPath" TaskParameter="Data"/>
</MSBuild.ExtensionPack.Computer.Registry>


有关更多信息,请参阅。

谢谢。这让我走上了正确的道路,@Henrik:不客气。。。但是我认为你为这个创建一个自定义任务有点过分了。我完全同意,如果我控制了在开发人员机器上运行的msbuild版本,那么这是过度设计的。不幸的是,我还没有,所以这似乎是最快和最兼容的方式。谢谢Thierry,这个项目不再运行,但很高兴知道有内置的方式可以访问64位和32位版本的注册表。我还没有测试过这个问题,但是改变我接受的解决方案,因为这是一个更好的解决方法。
<MSBuild.ExtensionPack.Computer.Registry TaskAction="Get" RegistryView="Registry32" RegistryHive="LocalMachine" Key="SOFTWARE\Microsoft\MSCRM" Value="CRM_Server_InstallDir">
    <Output PropertyName="CrmPath" TaskParameter="Data"/>
</MSBuild.ExtensionPack.Computer.Registry>