как установить флаг REG_KEY_DONT_VIRTUALIZE в c # - PullRequest
1 голос
/ 23 марта 2011

Мой вопрос очень прост, но я не нашел ответа, гуглявшего долгое время.
Как установить флаг REG_KEY_DONT_VIRTUALIZE для ключа реестра, созданного мной (т.е. HKLM\Software\MyApp)? Я хочу, чтобы моя программа была независимой от пользователя. Каждый пользователь, запускающий мое приложение, должен иметь доступ к одинаковым параметрам конфигурации, расположенным в этом месте). Изменение манифеста приложения Я могу отключить виртуализацию реестра, запустив программу от имени администратора, но я хочу, чтобы обычный пользователь мог запускать программу и считывать значения реестра.

Ответы [ 4 ]

0 голосов
/ 16 июня 2016

На сегодняшний день нет C # или C API для установки флагов ключа реестра.

Я предполагаю, что самый безопасный способ - запустить инструмент командной строки REG.exe с помощью CreateProcess.

Но, к сведению, я вставил код 'C' из этого блога , который демонстрирует другой способ использования недокументированного API:

typedef enum _CONTROL_FLAGS {
    RegKeyClearFlags = 0,
    RegKeyDontVirtualize = 2,
    RegKeyDontSilentFail = 4,
    RegKeyRecurseFlag = 8
} CONTROL_FLAGS;

typedef struct _KEY_CONTROL_FLAGS_INFORMATION {
    ULONG   ControlFlags;
} KEY_CONTROL_FLAGS_INFORMATION, *PKEY_CONTROL_FLAGS_INFORMATION;

typedef enum _KEY_SET_INFORMATION_CLASS {
    KeyWriteTimeInformation,
    KeyWow64FlagsInformation,
    KeyControlFlagsInformation,
    KeySetVirtualizationInformation,
    KeySetDebugInformation,
    MaxKeySetInfoClass  // MaxKeySetInfoClass should always be the last enum

} KEY_SET_INFORMATION_CLASS;

NTSYSAPI NTSTATUS NTAPI NtSetInformationKey(
IN HANDLE               KeyHandle,
IN KEY_SET_INFORMATION_CLASS InformationClass,
IN PVOID                KeyInformationData,
IN ULONG                DataLength );

typedef NTSYSAPI NTSTATUS (NTAPI* FuncNtSetInformationKey) (
    HANDLE KeyHandle,
    KEY_SET_INFORMATION_CLASS InformationClass,
    PVOID KeyInformationData,
    ULONG DataLength ); 

BOOL CRegLonMigration::SetDontVirtualizeFlag(LPCTSTR keyPath)
{
    FuncNtSetInformationKey ntsik = (FuncNtSetInformationKey)GetProcAddress(GetModuleHandle( _T("ntdll.dll") ), "NtSetInformationKey" ); 
    KEY_CONTROL_FLAGS_INFORMATION kcfi = {0}; 

    kcfi.ControlFlags = RegKeyDontVirtualize | RegKeyRecurseFlag; 
    HKEY hKey = NULL;
    LSTATUS status;
    if (ERROR_SUCCESS == (status = ::RegOpenKeyEx(ROOT_KEY, keyPath, 0, KEY_ALL_ACCESS, &hKey)))
    {
        NTSTATUS status = ntsik( hKey, KeyControlFlagsInformation, &kcfi, sizeof( KEY_CONTROL_FLAGS_INFORMATION ) ); 
        RegCloseKey( hKey ); 
        return TRUE;
    }

    return FALSE;
}
0 голосов
/ 23 марта 2011

Это довольно неясно, виртуализация включена только для устаревших не UAC-совместимых программ, и чтение всегда разрешено. Я должен предположить, что написание является проблемой. Измените разрешения для ключа, скажем, с помощью вашего установщика или Regedit.exe, чтобы у всех был доступ для записи.

0 голосов
/ 18 марта 2016

Не изменяя и не добавляя ACL к ключу, вы можете убедиться, что ключ, который вы используете программно, просматривает 64-битную часть реестра, используя RegistryKey.OpenBaseKey API с флагом RegistryView.Registry64.

Похоже, что это работает правильно для 32-разрядных приложений независимо от того, включена ли виртуализация реестра для приложения.

private const string MyRegistryKeyPath = "Software\\My Company\\My App";

private static RegistryKey OpenMyAppRegistryKey(bool requireWriteAccess = false)
{
    using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
    {
        return requireWriteAccess
            ? baseKey.CreateSubKey(MyRegistryKeyPath, RegistryKeyPermissionCheck.ReadWriteSubTree)
            : baseKey.OpenSubKey(MyRegistryKeyPath, RegistryKeyPermissionCheck.ReadSubTree);
    }
}

Если requireWriteAccess равно false, этот метод вернет null, если указанный ключ не существует.

Я также должен указать, что этот код потребует повышенных разрешений для открытия ключа для доступа для записи. Но я считаю, что это гарантирует, что нелицензированное чтение с использованием ключей, открытых таким образом, будет происходить только из 64-разрядного представления реестра.

0 голосов
/ 23 марта 2011

Если вы не хотите, чтобы ваше приложение было виртуализировано, вы используете манифест, чтобы указать это. Если вы используете REG_KEY_DONT_VIRTUALIZE для своего ключа, то все, что произойдет, это то, что все операции записи будут неудачными, потому что у ваших пользователей не будет доступа на запись в HKLM.

Если вы хотите, чтобы все ваши пользователи обменивались конфигурацией, вам придется хранить конфигурацию в файле, а не в реестре. В реестре нет нигде подходящего места, которое доступно всем пользователям и предоставляет обычным пользователям доступ на запись.

...