2010-05-26 123 views
4

我使用.NET 4和新的RegistryKey.FromHandle调用,因此我可以从打开a软件注册表文件RegLoadAppKey,并使用现有的托管API对其进行操作。RegLoadAppKey在32位操作系统上工作正常,在64位操作系统上失败,即使这两个进程都是32位

我刚开始认为这只是一个捣乱的DllImport问题,我的调用在参数或缺少的MarshalAs或其他类型中有一个无效类型,但是查看其他注册表函数和它们的DllImport声明(例如,在pinvoke .net),我没有看到还有什么可以尝试的(我有hKey作为int和IntPtr返回,都在32位操作系统上运行,并在64位操作系统上失败)

我懂了尽可能简单地记录一个重复案例 - 它只是试图创建一个“随机”子项,然后为其写入一个值。它在我的Win7 x86机器上运行良好,并且在Win7 x64和2008 R2 x64上失败,即使它仍然是32位进程,甚至可以从32位cmd提示符运行。编辑:如果它是一个64位进程,它也会以同样的方式失败。 编辑:它工作正常,如果文件传入是空的 - 问题情况是现有的软件注册表配置单元。我从2008 r2(x64)和WHS v1(x86)iso提取'裸'软件注册表配置单元文件,两者都有相同的问题。

Win7上的x86

INFO: Running as Admin in 32-bit process on 32-bit OS 
Was able to create Microsoft\Windows\CurrentVersion\RunOnceEx\a95b1bbf-7a04-4707-bcca-6aee6afbfab7 and write a value under it 

上Win7的X64,作为32位:

INFO: Running as Admin in 32-bit process on 64-bit OS 

Unhandled Exception: System.UnauthorizedAccessException: Access to the registry key '\Microsoft\Windows\CurrentVersion\RunOnceEx\ce6d5ff6-c3af-47f7-b3dc-c5a1b9a3cd22' is denied. 
    at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str) 
    at Microsoft.Win32.RegistryKey.CreateSubKeyInternal(String subkey, RegistryKeyPermissionCheck permissionCheck, Object registrySecurityObj, RegistryOptions registryOptions) 
    at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey) 
    at LoadAppKeyAndModify.Program.Main(String[] args) 

上Win7的X64,为64位:

INFO: Running as Admin in 64-bit process on 64-bit OS 

Unhandled Exception: System.UnauthorizedAccessException: Access to the registry key '\Microsoft\Windows\CurrentVersion\RunOnceEx\43bc857d-7d07-499c-8070-574d6732c130' is denied. 
    at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str) 
    at Microsoft.Win32.RegistryKey.CreateSubKeyInternal(String subkey, RegistryKeyPermissionCheck permissionCheck, Object registrySecurityObj, RegistryOptions registryOptions) 
    at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck) 
    at LoadAppKeyAndModify.Program.Main(String[] args) 

源:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("INFO: Running as {0} in {1}-bit process on {2}-bit OS", 
      new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator) ? "Admin" : "Normal User", 
      Environment.Is64BitProcess ? 64 : 32, 
      Environment.Is64BitOperatingSystem ? 64 : 32); 

     if (args.Length != 1) 
     { 
      throw new ApplicationException("Need 1 argument - path to the software hive file on disk"); 
     } 
     string softwareHiveFile = Path.GetFullPath(args[0]); 
     if (File.Exists(softwareHiveFile) == false) 
     { 
      throw new ApplicationException("Specified file does not exist: " + softwareHiveFile); 
     } 

     // pick a random subkey so it doesn't already exist 
     var existingKeyPath = @"Microsoft\Windows\CurrentVersion"; 
     var keyPathToCreate = @"RunOnceEx\" + Guid.NewGuid(); 
     var completeKeyPath = Path.Combine(existingKeyPath, keyPathToCreate); 
     var hKey = RegistryNativeMethods.RegLoadAppKey(softwareHiveFile); 
     using (var safeRegistryHandle = new SafeRegistryHandle(new IntPtr(hKey), true)) 
     using (var appKey = RegistryKey.FromHandle(safeRegistryHandle)) 
     using (var currentVersionKey = appKey.OpenSubKey(existingKeyPath, true)) 
     { 
      if (currentVersionKey == null) 
      { 
       throw new ApplicationException("Specified file is not a well-formed software registry hive: " + softwareHiveFile); 
      } 

      using (var randomSubKey = currentVersionKey.CreateSubKey(keyPathToCreate)) 
      { 
       randomSubKey.SetValue("foo", "bar"); 
       Console.WriteLine("Was able to create {0} and write a value under it", completeKeyPath); 
      } 
     } 
    } 
} 

internal static class RegistryNativeMethods 
{ 
    [Flags] 
    public enum RegSAM 
    { 
     AllAccess = 0x000f003f 
    } 

    private const int REG_PROCESS_APPKEY = 0x00000001; 

    // approximated from pinvoke.net's RegLoadKey and RegOpenKey 
    // NOTE: changed return from long to int so we could do Win32Exception on it 
    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern int RegLoadAppKey(String hiveFile, out int hKey, RegSAM samDesired, int options, int reserved); 

    public static int RegLoadAppKey(String hiveFile) 
    { 
     int hKey; 
     int rc = RegLoadAppKey(hiveFile, out hKey, RegSAM.AllAccess, REG_PROCESS_APPKEY, 0); 

     if (rc != 0) 
     { 
      throw new Win32Exception(rc, "Failed during RegLoadAppKey of file " + hiveFile); 
     } 

     return hKey; 
    } 
} 
+0

不,当你运行它的64位机器上的64位进程工作的呢? – luke 2010-05-27 03:16:57

+0

很好的问题,不,它不是 – 2010-05-27 04:29:45

回答

2

最终以Microsoft支持开放支持案例 - 问题具体针对1)安装介质上为最新版本的Windows提供的配置单元以及2)作为API的RegLoadAppKey。切换到RegLoadKey/RegUnLoadKey对于完全相同的文件(甚至在同一个过程中)工作得很好,并且由于RegLoadAppKey中的错误不太可能得到修复(更不用说很快)来处理这些特定的文件,所以我只是切换到而不是RegLoadKey/RegUnLoadKey。

+0

所以它的某种格式的配置单元仅失败? – paulm 2015-07-13 14:29:01

相关问题