您的位置:3983金沙网站在线平台 > 母婴 > C# 32位程序访问64位系统注册表

C# 32位程序访问64位系统注册表

发布时间:2019-10-07 14:39编辑:母婴浏览(117)

          获得操作Key值的句柄

    WOW64简介

    WOW64(Windows 32-bit On Windows 64-bit)是x64平台上运转win32应用程序的模拟器,它在系统层提供了中间层,将win32的系统调用调换来x64举行调用,并且将x64再次回到的结果调换到win32款式再次来到给win32顺序。下图描述了win32前后相继怎么着在x64系统上运维的。

    图片 1

    How a 32-bit process runs on 64-bit Windows

    WOW64局限性:

    • 地址空间暗许是2G,使用/LA奥迪Q5GEADDRESSAWARE按钮能够直达4G。
    • 叁十二个人进程不恐怕加载63个人DLL(除了钦点的体系DLL)。
    • 不扶助15人进度的运作。
    • 爱莫能助使用DOS设想机(VDM, Vitrual DOS Machine)。
    • 英特尔安腾类别管理器不接济 AWE.aspx), Vectored I/O, PAE.aspx) 以及DirectX硬件加快API。

            关闭注册表转向(禁绝特定项的注册表反射)

    注册表机制

    引人注目,注册表是windows系统的数据库,系统本身以及安装的前后相继都信任注册表。当Windows进化到陆拾陆人,还要合作大批量的32人应用程序,便蒙受了注册表冲突的主题素材。

    登记表树最大可以有512级深度,通过注册表API三遍能够创立32级深的键值。

    为了消除61人系统的包容性难题,Windows使用了三套方案,分享(Shared)、注册表重定向(Registry Redirector.aspx))和注册表反射(Registry Reflection.aspx))。

      那么要完结32为顺序访谈六16人注册表音信,还要驾驭如下概念:1:文件系统转向。2:注册表重定向(转向)。3:注册表反射。

    文本与变量的援引

    应用程序必得确定保障对文本名与变量(包蕴系统变量,情况变量,系统特别路线.aspx)等)的引用适用于前段时间的操作系统,不然会滋生如下难题:

    1. 稍许变量只适用于陆拾位操作系统,举例:%ProgramW6432%和FOLDEENCOREID_ProgramFilesX64。
    2. 有一点变量只适用于31位操作系统,举个例子:%windir%Sysnative。
    3. 稍加变量在分裂位数的操作系统下数值差别,例如:%ProgramFiles%和FOLDEKoleosID_ProgramFiles。

    小心:咱们在选取上述变量时必得先推断当前系统的位数音讯以担保援用正确。

    同理,注册表消息中包括碰到变量时也会并发就如主题材料。举个例子REG_EXPAND_SZ指向包罗情形变量的注册表音讯,系统会活动分析键值中蕴涵的%xxx%情状变量。而REG_SZ键值中的%xxx%不会被活动剖析。不过能够通过ExpandEnvironmentStrings.aspx)等系统API进行扩充。当程序调用RegGetValue.aspx)获取注册表键值的时候,系统会依据方今操作系统的位数新闻对蒙受变量进行扩充,不过应用程序也得以覆盖这种扩张格局。
    之所以,在六二十人操作系统中我们要制止使用31位和陆拾四人系统不通用的变量,比方:

    1. %ProgramFiles%, FOLDERID_ProgramFiles(CSIDL_PROGRAM_FILES), FOLDERID_ProgramFilesCommon(CSIDL_PROGRAM_FILES_COMMON)
    2. FOLDERID_ProgramFilesX64, FOLDERID_ProgramFilesCommonX64

    下面对上述的文书与变量的引用以及文件目录重定向举办简易总计。

    图片 2

    Summary of Rules for Referencing Files and Variables

    图片 3

    Summary of Defaults for Variables and Paths

     

    1. 共享

    封存能够被32个人和陆十四个人合伙选拔的注册表。

        重定向截获位级其余注册表调用。注册表重定向还足以保险登记表调用被定向到在注册表中国科高校学的支行。

    2. 注册表反射

    注册表反射是在六12人注册表视图和三十两个人注册表视图之间复制有个别特定的登记表项和项值。一言以蔽之便是备份和一齐,把同一份注册表保存到七个大要地点,分别被叁15人或六17个人程序选择。保存爆发在RegCloseKey调用结束。
    使用RegDisableReflectionKey.aspx)和RegEnableReflectionKey.aspx)方法可以禁止使用/启用反射机制。
    该方案只用于Windows Server 2010, Windows Vista, Windows Server 二零零一 和 Windows XP,从 Windows 7 和 Windows Server 二零一零 安德拉2 伊始被移除。

    比方来讲:在X64系统中安装六12个人Microsoft Office后,陆拾位的winword.exe将注册.doc这一个扩张名并把这些扩充名涉嫌到winword.exe程序,依据X64的运维机制,63个人程序修改的是69个人的登记表键值,可是WOW64会自动的把那一个修改会同步到三十人的注册表键上边,那样叁十五位和六10位的应用程序都足以应用六18人winword.exe张开.doc文件。

    不过,并不是兼具的键值都会遭到注册表反射机制的影响。实验注解,假诺我们应用三十一个人的注册表编辑器在HKEY_LOCAL_MACHINE/Software下新建三个项,然后接纳60个人的注册表编辑器查看,会意识这么些项只会产出在HKEY_LOCAL_MACHINE/Software/Wow6432Node键下而不会出现在HKEY_LOCAL_MACHINE/Software键下,因为HKEY_LOCAL_MACHINE/Software键是特地用于寄放64人程序所利用的注册表数据的,而HKEY_LOCAL_MACHINE/Software/Wow6432Node键是专程用于贮存31人程序所使用的注册表数据的。

    注册表中饱受反射机制影响的有:

    HKEY_LOCAL_MACHINE/Software/Classes
    HKEY_LOCAL_MACHINE/Software/COM3
    HKEY_LOCAL_MACHINE/Software/EventSystem
    HKEY_LOCAL_MACHINE/Software/Ole
    HKEY_LOCAL_MACHINE/Software/Rpc
    HKEY_USERS/*/Software/Classes
    HKEY_USERS/*_Classes
    

      大家曾经清楚:

    文件系统重定向

    与注册表类似,系统为了缓慢解决文件争执的主题材料,引进了文件系统重定向的编写制定,文件系统重定向使叁十四人程序和63个人程序的公文与数码分开存放,%systemroot%/system32 目录被保留给六15人文件使用,而三十一个人文件会被重定向到%systemroot%/SysWOW64目录。任何叁拾三人程序试图访问%systemroot%/system32 目录都会被重定向到%systemroot%/SysWOW64目录。这是系统私下认可行为,除非程序的线程显著的指明供给关闭文件系统重定向机制。

        注册表重定向无需程序代码修改,和此进程是对客商透明。

    应用程序如何访谈注册表

    下边临33位与陆拾伍个人应用程序分别拜谒注册表举办简要总括:

    1. 陆14个人程序如何访问六十几个人的注册表(HKLM/Software)
    • 陆11位程序访问六十六位的注册表,直接到 HKLM/Software。
    1. 32个人程序怎样访谈三十八人的注册表(HKLM/Software/Wow6432Node)
    • 三贰拾壹位程序访谈叁11个人的注册表,WOW64将会截取对HKLM/Software访谈,等量齐观定向到HKLM/Software/Wow6432Node。
    1. 三拾贰个人程序怎样访谈62个人的注册表(HKLM/Software)
    • 在调用函数RegCreateKeyEx.aspx)成立注册表项时,对第四个参数REGSAM samDesired设置中加上参数KEY_WOW64_64KEY,那样能够兑现对63个人注册表的拜望;
    • 在调用函数RegOpenKeyEx.aspx)展开注册表项时,对第多少个参数REGSAM samDesired设置中加上参数KEY_WOW64_64KEY,那样能够兑现对陆拾一人注册表的访谈;
    1. 陆十个人程序如何访问叁12个人的注册表(HKLM/Software/Wow6432Node)
    • 在调用函数RegCreateKeyEx.aspx)创立注册表项时,对第四个参数REGSAM samDesired设置中丰裕参数KEY_WOW64_32KEY,这样可以达成对叁拾位注册表的拜访;
    • 在调用函数RegOpenKeyEx.aspx)张开注册表项时,对第七个参数REGSAM samDesired设置中加上参数KEY_WOW64_32KEY,这样能够兑现对33个人注册表的访谈;

            Wow64DisableWow64FsRedirection(关闭系统转 向),

    应用程序安装与开发银行

    六拾壹位操作系统上的应用程序分为二种:

    1. 三十一个人应用程序
      安装目录:C:Program Files (x86)

    2. 65人应用程序
      设置目录:C:Program Files

    3. 重复版本应用程序(Dual-bitness application)
      设置目录:参谋上述目录
      这种方法必需保险31位版本与陆拾壹人版本包容。

    图片 4

    Behavior of Applications and Interpreted Files at Process Startup

    补给表达:

    • 本着文件重定向,独有叁十二人程序访谈六拾一个人目录时才会被重定向,比方34位程序访谈六19个人目录C:Windowssystem32;而六20个人程序则足以一向访谈三15位目录,不设有重定向,比方六十四人程序能够直接访问C:Windowssyswow64
    • 文件系统重定向只是存在system32和systemWOW64的重定向,而不设有program files和ProgramFiles(x86)的重定向一说,直接硬编码相对路线就可以。

            Wow64RevertWow64FsRedirection(张开系统转向),

    注册表重定向机制对系统的熏陶

    1. 下列程序调用未有失常态:
    • 三九个人应用程序A调用叁十三个人应用程序B并访谈B的注册表音讯。由于挂号表重定向机制,叁十一人应用程序B的登记音信在HKLM/Software/Wow6432Node中,而叁十个人应用程序A访谈注册表也会被重定向到HKLM/Software/Wow6432Node中,所以访谈平常。

    • 陆九人应用程序A调用62人应用程序B并访谈B的注册表消息。陆拾壹个人应用程序B的挂号消息在HKLM/Software,62位应用程序A访谈注册表时直接访问HKLM/Software,所以访问符合规律。

    1. 在下列情形时会出现难点:
    • 61个人应用程序调用叁十六个人应用程序并访谈其注册表音讯。因为三拾人应用程序的登记音信在HKLM/Software/Wow6432Node中,而六13个人应用程序访谈注册表时直接限制HKLM/Software,所以访谈十三分。

      不留余地方案:在写注册表时,三14位应用程序要将该注册新闻写到62位程序的注册表项中,即HKLM/Software下。

    • 31人应用程序调用六十几个人应用程序并访谈其注册表音讯。同上。

        转向到%windir%syswow64上边。这种转化对于各样叁12人应用程序暗许都是开发的。但是这种转化对于大家来讲并不一连要求的。那么大家能够在

    收获系统消息代码片段

    // 判断应用程序是否运行在X64系统下
    BOOL IsX64System()  
    {  
        BOOL bIsWow64 = FALSE;  
        typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);  
        LPFN_ISWOW64PROCESS pfnIsWow64 = NULL;  
        // 32位系统的kernel32没有IsWow64Process导出函数,直接使用会有问题
        pfnIsWow64 = (LPFN_ISWOW64PROCESS)GetProcAddress(
            GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");  
        if (pfnIsWow64)  
        {  
            if (!pfnIsWow64(GetCurrentProcess(), &bIsWow64))  
            {  
                // handle error  
            }  
        }  
    
        return bIsWow64;  
    } 
    
    // 获取系统信息
    BOOL GetSystemInfoEx(SYSTEM_INFO *pSystemInfo)  
    {  
        BOOL bRet = FALSE;  
        if (!pSystemInfo) 
        {
            goto Exit0;  
        }
    
        typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);  
        PGNSI pfnGNSI = NULL;
        ZeroMemory(pSystemInfo, sizeof(SYSTEM_INFO));  
        if (IsX64System())  
        {  
            // x64下要调用这个API  
            pfnGNSI = (PGNSI)GetProcAddress(  
                GetModuleHandle(_T("kernel32.dll")), "GetNativeSystemInfo");  
            if (!pfnGNSI)
            {       
                goto Exit0;  
            }
            pfnGNSI(pSystemInfo);  
        }  
        else  
        {  
            // 32位系统调用下面的API  
            GetSystemInfo(pSystemInfo);  
        }  
    
        bRet = TRUE;  
    Exit0:  
        return bRet;  
    }  
    

      小编的上一篇小说已经解说了“33位程序和陆十一个人程序在陆16位平台上读写注册表的界别”,那么接下去就要回答上篇所留下来的二个难题:30位程序如何访谈六12位系统注册表(即:六11个人程序所拜谒的注册表地点)。

    Bibliography

    1. Windows Hardware Dev Center Archive
    2. Windows Driver Kit (WDK).aspx)
    3. Registry Redirector.aspx)
    4. Removal of Windows Registry Reflection.aspx)
    5. File System Redirector.aspx)
    6. WOW64 Implementation Details.aspx)
    7. KNOWNFOLDERID.aspx)
    8. 登记表重定向

        可是Wow64EnableWow64FsRedirection在嵌套使用的时候不可靠,所以普通用地点的 Wow64RevertWow64FsRedirection来开拓文件系统转向

    文件系统重定向按键

    针对%windir%system32,要是我们用33人程序去访谈%windir%system32,不管大家用硬编码照旧其余的法子,系统都会活动地给大家转向到%windir%syswow64目录。这种转化对于种种叁15个人应用程序暗许都是开发的,不过这种转化并不总是必要的。由此,系统提供了连带的API来调控文件重定向的开荒与关闭。常用的函数有3个,如下所示

    • 关闭系统重定向: Wow64DisableWow64FsRedirection.aspx)
    • 展开系统重定向: Wow64RevertWow64FsRedirection.aspx)
    • 开采系统重定向: Wow64EnableWow64FsRedirection.aspx)

    留意:Wow64EnableWow64FsRedirection在嵌套使用的时候不可靠,所以日常用地方的 Wow64RevertWow64FsRedirection来打开文件系统转向功效。

        它应该被分成给64人应用程序的目录和给三13个人应用程序的目录。假诺不那样,我们就无法区分30位和六拾陆人的Dll文件。对于陆十一位应用程序,其 文件常常被

    3. 挂号表重定向

    挂号表重定向为34位和陆十二位程序分别提供分化的注册表物理存款和储蓄地点,但会映射成同三个逻辑视图,这几个进度对前后相继自个儿是晶莹剔透的。也正是说,四个33位程序可以像在31位系统中同样来接纳注册表,固然它们在六十人系统上被寄放在不相同的物理地点。

    三12位程序重定向的挂号表贮存在Wow6432Node下,举个例子, HKEY_LOCAL_MACHINESoftware 会被重定向到 HKEY_LOCAL_MACHINESoftwareWow6432Node。

    内需重定向的注册表项如下所示:

    // 64位程序的注册信息存储键
    HKLM/Software
    HKEY_CLASSES_ROOT 
    HKEY_CURRENT_USER/Software/Classes 
    HKEY_LOCAL_MACHINE/Software 
    HKEY_USERS/*/Software/Classes 
    HKEY_USERS/*_Classes
    //32位程序的注册信息重定向存储键
    HKLM/Software/WOW6432node 
    HKEY_CLASSES_ROOT/WOW6432node 
    HKEY_CURRENT_USER/Software/Classes/WOW6432node 
    HKEY_LOCAL_MACHINE/Software/WOW6432node 
    HKEY_USERS/*/Software/Classes/WOW6432node 
    HKEY_USERS/*_Classes/WOW6432node
    

        当我们设置新程序或 Windows x64 版的微管理器上运营程序时,所做的 64 位程序的注册表调用访谈HKEY_LOCAL_MACHINESoftware 注册表子键

        不重定向。WOW64 截获由 30人程序的挂号表调用到 HKEY_LOCAL_MACHINESoftware,然后将它们重定向到

      

        C#内部调用相关的API来关闭和开辟这种转化。常用的函数有3个:

        32人进程不能够加载63位Dll,六二十一位进度也不能够加载三12位Dll。Windows的系统目录包涵了颇有安装的应用程序和它们的Dll文件,依据我们所述 的法则,

        放在%windir%system32和%programfiles%(比如:c:program files)。对于三拾一位应用程序,其文件平日在%windir%syswow64和

        功能。在C#中,大家得以选取DllImport直接调用那多少个函数。

        ②:32 位程序运转在 WOW64 形式下,并且访问键和值存款和储蓄在偏下注册表子项中:HKEY_LOCAL_MACHINESoftwareWOW6432nod

        HKEY_LOCAL_MACHINESoftwareWOW6432node 子键。 通过重定向仅 32 位程序调用,WOW64 可保证程序始终写入相应的注册表子键。

        开启陆十六位(文件系统)的操作转向

        ②:注册表重定向(转向)

    Get64BitRegistryKey函数的多少个参数分别表示:主键名(如:HKEY_LOCAL_MACHINE等),子键名,Key名,再次回到的是Key的Value(六10位系统注册表的键值),通过上边包车型地铁主意就完全能够兑现用32主次访谈陆16个人系统注册表(即:陆十一人程序所访谈的注册表地方)。

      【注:由于大家在程序中用了DllImport,所以要引进命名空间:System.Runtime.InteropServices】

        反射使七个一律的注册表,以支撑同有的时候候开展的本机和 WOW64 操作的情理副本的存在,

        ③:注册表反射

      下边请看代码示例

        ①:文件系统转向

      using System;  
      using System.Collections.Generic;  
      using System.Linq;  
      using System.Text;  
      using Microsoft.Win32;  
      using System.Runtime.InteropServices;  
    
      namespace OperateRegistrationTable  
     { 
         class Programe 
         { 
             static void Main(string[] args) 
             { 
                 string myParentKeyName = "HKEY_LOCAL_MACHINE"; 
                 string mySubKeyName = @"SOFTWAREEricSunMyTestKey"; 
                 string myKeyName = "MyKeyName"; 
    
                 string value = string.Empty; 
                 value = Utility.Get64BitRegistryKey(myParentKeyName, mySubKeyName, myKeyName); 
                 Console.WriteLine("The Value is: {0}", value); 
             } 
         } 
    
         public class Utility 
         { 
             #region 32位程序读写64注册表 
    
             static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)0x80000000; 
             static UIntPtr HKEY_CURRENT_USER = (UIntPtr)0x80000001; 
             static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; 
             static UIntPtr HKEY_USERS = (UIntPtr)0x80000003; 
             static UIntPtr HKEY_CURRENT_CONFIG = (UIntPtr)0x80000005; 
    
             // 关闭64位(文件系统)的操作转向 
              [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
             public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr); 
             // 开启64位(文件系统)的操作转向 
              [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
             public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);     
    
             // 获取操作Key值句柄 
              [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
             public static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out IntPtr phkResult); 
             //关闭注册表转向(禁用特定项的注册表反射) 
             [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
             public static extern long RegDisableReflectionKey(IntPtr hKey); 
             //使能注册表转向(开启特定项的注册表反射) 
             [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
             public static extern long RegEnableReflectionKey(IntPtr hKey); 
             //获取Key值(即:Key值句柄所标志的Key对象的值) 
             [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
             private static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int lpReserved, 
                                                       out uint lpType, System.Text.StringBuilder lpData, 
                                                       ref uint lpcbData); 
    
             private static UIntPtr TransferKeyName(string keyName) 
             { 
                 switch (keyName) 
                 { 
                     case "HKEY_CLASSES_ROOT": 
                         return HKEY_CLASSES_ROOT; 
                     case "HKEY_CURRENT_USER": 
                         return HKEY_CURRENT_USER; 
                     case "HKEY_LOCAL_MACHINE": 
                         return HKEY_LOCAL_MACHINE; 
                     case "HKEY_USERS": 
                         return HKEY_USERS; 
                     case "HKEY_CURRENT_CONFIG": 
                         return HKEY_CURRENT_CONFIG; 
                 } 
    
                 return HKEY_CLASSES_ROOT; 
             } 
    
             public static string Get64BitRegistryKey(string parentKeyName, string subKeyName, string keyName) 
             { 
                 int KEY_QUERY_VALUE = (0x0001); 
                 int KEY_WOW64_64KEY = (0x0100); 
                 int KEY_ALL_WOW64 = (KEY_QUERY_VALUE | KEY_WOW64_64KEY); 
    
                 try 
                 { 
                     //将Windows注册表主键名转化成为不带正负号的整形句柄(与平台是32或者64位有关) 
                     UIntPtr hKey = TransferKeyName(parentKeyName); 
    
                     //声明将要获取Key值的句柄 
                     IntPtr pHKey = IntPtr.Zero; 
    
                     //记录读取到的Key值 
                     StringBuilder result = new StringBuilder("".PadLeft(1024)); 
                     uint resultSize = 1024; 
                     uint lpType = 0; 
    
                     //关闭文件系统转向  
                     IntPtr oldWOW64State = new IntPtr(); 
                     if (Wow64DisableWow64FsRedirection(ref oldWOW64State)) 
                     { 
                         //获得操作Key值的句柄 
                         RegOpenKeyEx(hKey, subKeyName, 0, KEY_ALL_WOW64, out pHKey);
    
                         //关闭注册表转向(禁止特定项的注册表反射)
                         RegDisableReflectionKey(pHKey);
    
                         //获取访问的Key值
                         RegQueryValueEx(pHKey, keyName, 0, out lpType, result, ref resultSize);
    
                         //打开注册表转向(开启特定项的注册表反射)
                         RegEnableReflectionKey(pHKey);
                     }
    
                     //打开文件系统转向
                     Wow64RevertWow64FsRedirection(oldWOW64State);
    
                     //返回Key值
                     return result.ToString().Trim();
                 }
                 catch (Exception ex)
                 {
                     return null;
                 }
             }
    
             #endregion
         }
     }
    

          获取访问的Key值

            张开注册表转向(开启特定项的注册表反射)

        张开注册表的 六11人节在具不常间和注册表反射提供了一种容纳 32 位的实时方法。

      简单的摸底了那些,下边说一下实际的金镶玉裹福禄双全步骤:

        关闭60人(文件系统)的操作转向

        若要扶助的 32 位和 64 位 COM 注册和次序共存状态,WOW64 子系统提供 33人程序行使的注册表的另二个视图。在 WOW64 子系统选取注册表

        C:program files (x86)下边。假使大家用叁十个人程序去访谈%windir%system32,不管我们用硬编码如故别的的艺术,系统都会自动地给我们

        ①:本机形式 六12位程序运维在纯格局下,并且访问键和存款和储蓄在偏下注册表子键中的值:HKEY_LOCAL_MACHINESoftware

            Wow64EnableWow64FsRedirection(展开系统转向)。

    本文由3983金沙网站在线平台发布于母婴,转载请注明出处:C# 32位程序访问64位系统注册表

    关键词:

上一篇:为什么我做的设计总是不耐看

下一篇:没有了