从 C# 应用程序中添加 reg 并从 cmd window 中查询值后值不同的原因是什么?

What is the reason for different value after reg add from within a C# application and query the value from within a cmd window?

我有一个用 C# 编写的程序,它打开一个 cmd 控制台和 adds/modifies 一个注册表值。

控制台输出任务完成后,我用reg query测试注册表值是否真的改变了。没有问题。我得到了我预期的值 0x1

但是当我从当前 cmd window 外部查询此注册表时,就像我作为管理员执行的另一个 cmd 一样,值是 0x0 on reg query

这怎么可能?

这是我的 C# 代码:

string command = @"/K reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock /t REG_DWORD /f /v AllowDevelopmentWithoutDevLicense /d 1";

        Process proc = Process.Start("cmd.exe", command);

从程序执行的cmd里面查询:

reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock
    AllowDevelopmentWithoutDevLicense    REG_DWORD    0x1

从外面:

reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock
    AllowDevelopmentWithoutDevLicense    REG_DWORD    0x0
    AllowAllTrustedApps    REG_DWORD    0x0

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock\AllowDevelopmentWithoutDevLicense
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock\AllowDevelopmentWithoutDevLicense=1

当 64 位 Windows 上的 32 位应用程序访问注册表项时

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock

它被 Windows registry redirector 重定向到

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\AppModelUnlock

64 位应用程序真正访问

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock

两个注册表路径之间的区别是 Wow6432Node 默认情况下仅对 Windows x64 上的 64 位应用程序可见。

请参阅 Microsoft 开发人员文章 Registry Keys Affected by WOW64

为了完整起见,另请参阅:

目录%SystemRoot%\SysWow64中有32位cmd.exereg.exe64位Windows%SystemRoot%\System32 用于 32 位应用程序和 64 位应用程序 cmd.exereg.exe%SystemRoot%\System32.

您的 C# 应用程序很可能被编译为 32 位应用程序,因此调用 32 位 cmd.exe 而调用 32 位 reg.exe.

您可以通过显式调用 %SystemRoot%\Sysnative\cmd.exe.

在 32 位应用程序中解决此问题

但请注意 %SystemRoot%\Sysnative 在 32 位 Windows 上不存在,对于 64 位应用程序在 64 位 Windows 上也不存在。 (Sysnative 是一个特殊的别名,不是硬 link、结点或真实文件夹。)

因此,您的 32 位 C# 应用程序需要首先检查 %SystemRoot%\Sysnative\cmd.exe 是否存在,然后使用此路径使用 64 位 cmdreg 编辑 64 位注册表值.但在 32 位上 Windows %SystemRoot%\System32.exe\cmd.exe 必须由 32 位 C# 应用程序调用。顺便说一句:%SystemRoot%引用了环境变量SystemRoot.

的值

另见答案:

  • Why can a double clicked batch file not find a registry value for deletion?
  • (Java,但同样的问题)

注 1:

运行 cmd.exe 根本不需要。可以直接在32位上运行Windows

%SystemRoot%\System32\reg.exe

或 64 位 Windows

%SystemRoot%\Sysnative\reg.exe

来自 32 位应用程序。

注 2:

最后但同样重要的是,C# 应用程序根本不需要使用 reg.exe,因为 .NET Framework 内置支持访问 Windows 注册表 - Registry.SetValue Method。微软甚至在示例代码块中添加了一些示例。

KEY_WOW64_64KEY 可用于 32 位应用程序以明确访问 64 位注册表项,如 Microsoft 文档页面 Accessing an Alternate Registry View 中所述.