RegLoadAppKey отлично работает на 32-битной ОС, сбой на 64-битной ОС, даже если оба процесса 32-битные - PullRequest
4 голосов
/ 27 мая 2010

Я использую .NET 4 и новый вызов RegistryKey.FromHandle , поэтому я могу взять ключ, полученный при открытии файла реестра программного обеспечения с помощью RegLoadAppKey , и работать с ним с помощью существующий управляемый API.

Сначала я подумал, что это просто перебор DllImport, и мой вызов имел недопустимый тип в params или отсутствовал MarshalAs или что-то еще, но смотрел на другие функции реестра и их объявления DllImport (например, на pinvoke. нет), я не вижу, что еще попробовать (мне вернули hKey как int и IntPtr, оба работали на 32-битной ОС и терпели неудачу на 64-битной ОС)

Я объяснил это настолько простым делом репро, как только смогу - он просто пытается создать «случайный» подраздел, а затем записать в него значение. Он отлично работает на моем Win7 x86 box и дает сбой на 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;
    }
}

Ответы [ 2 ]

2 голосов
/ 19 июля 2010

Закончилось открытием обращения в службу поддержки Microsoft. Проблема связана с 1) кустами, которые поставляются на установочном носителе для последних версий Windows, и 2) RegLoadAppKey в качестве API. Переключение на RegLoadKey / RegUnLoadKey вместо этого работало нормально для тех же самых файлов (в том же процессе, даже), и поскольку ошибка в RegLoadAppKey вряд ли будет исправлена ​​(не говоря уже о том, что скоро), чтобы справиться с этими конкретными файлами, я просто переключился на Вместо RegLoadKey / RegUnLoadKey.

0 голосов
/ 04 мая 2011

Следующая ссылка должна быть полезной в этом сценарии:

http://msdn.microsoft.com/en-us/library/ms973190.aspx#64mig_topic5

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...