![Windows 好像有两个注册表?](https://linux22.com/image/1559047/Windows%20%E5%A5%BD%E5%83%8F%E6%9C%89%E4%B8%A4%E4%B8%AA%E6%B3%A8%E5%86%8C%E8%A1%A8%EF%BC%9F.png)
我们有一个软件,它将其连接信息保存到 Windows 注册表中,位于 下HKLM\Software
。它只是一个 32 位应用程序,而不是 64 位应用程序,我们很清楚它的不同位置 ( WOW6432Node
)。我们 150% 确定我们正在读取和写入完全相同的注册表项 - 我们的软件已有 20 多年的历史了。
在过去的一个月里,有 3 台计算机(其中两台是 Windows 7,第三台是 Windows 10)表现非常奇怪。我们唯一能描述它的方式是,就好像 Windows 注册表被复制了一样!我们在注册表中写入连接信息,以便我们的应用程序连接到服务器。但它读取的是我们很久以前更改过的旧条目!
看来,如果我们以“管理员身份”运行应用程序,他们就会表现得友好。尽管登录的用户是 PC 的本地管理员。例如,我们打开Regedit
并更改其中一个条目。运行我们的应用程序,它会读取更改之前的旧条目,但是当我们以管理员身份运行应用程序时,它突然获得了正确的条目。
这是一个已知问题吗?这是怎么回事?是某个 Windows 更新导致的吗?我可以做些什么来修复它?
答案1
该问题可能与注册表虚拟化有关。
Windows 将注册表写入从没有管理权限的软件重定向到 HKLM,并将其重定向到注册表中其他特定于用户的位置。请查看
HKEY_USERS\<User-SID>_Classes\VirtualStore
来自 Microsoft MSDN 网站注册表虚拟化
在 Windows Vista 之前,应用程序通常由管理员运行。因此,应用程序可以自由访问系统文件和注册表项。如果这些应用程序由标准用户运行,它们会因访问权限不足而失败。Windows Vista 和更高版本的 Windows 通过自动重定向这些操作来提高这些应用程序的应用程序兼容性。例如,对全局存储 (
HKEY_LOCAL_MACHINE\Software
) 的注册表操作被重定向到用户配置文件中称为虚拟存储 (HKEY_USERS\<User SID>_Classes\VirtualStore\Machine\Software
) 的每个用户位置。
答案2
作为一名程序员,我经常遇到这种情况;一家公司会使用为旧版本 Windows 编写的应用程序 20 多年,然后被迫升级,却发现 Windows 安全更新或 Windows 版本本身已经使他们的软件在底层而不是在实践中过时了。
这里可能发生的情况是,你的应用程序遇到了组策略问题。组策略可用于根据登录的用户修改注册表或注册表行为。我会在那里寻找问题的根本原因,但如果你在注册表中添加你正在做的事情以使你的应用程序正常运行,可能会有关于为什么会发生这种情况的新信息。
这带来的一个问题是,由于 Windows 以这种方式工作,开发人员可能会受到网络 IT 团队的摆布,因为他们通常是管理组策略的人。大多数现代开发人员在开发应用程序时都试图远离操作系统的运作,并将配置信息存储在数据库或本地配置文件中。虽然修改组策略可能会导致短期修复,但真正的解决方案可能是更改您的软件解决方案,使其在注册表中所做的一切现在都可以自行处理。任何说“不,我们不应该升级我们 20 年前的软件,因为它会花费太多”的人都只是在拖延问题,直到有一天,一个小小的 IT 变化会彻底和永久地破坏软件,并给组织带来更大的损失。
答案3
由于我还不能以我的声誉发表评论,所以让我在这里列出一些故障排除建议,即使它们不是真正的“答案”:
- 启动后运行程序进程监控(来自 SysInternals 的进程监视器)。您可以放置一个仅包含程序名称(或 PID)的过滤器,它可能会让您了解程序从何处读取,以及/或者过程中是否出现故障。
- 另一个 sysinternals 工具 Process Explorer(或 Handle)也可以为您提供注册表的路径(如果您保持密钥为“打开”)。
- 您的程序是否有可能具有某种逻辑,即当无法从注册表读取时,它会返回到以前的值(存储在磁盘/配置文件等中)?否则,奇怪的是您最终没有得到默认的后备值,而是在某个时候写入注册表的值。
答案4
我请发帖人使用 regedit 搜索旧数据,以便找到它隐藏在注册表中的哪个位置。答案是旧数据不再存在于注册表中,但程序仍在使用它们。
鉴于此,我能想到的唯一解释是,程序“读取”注册表中不再存在的旧值,它根本没有读取这些值。这是一种视觉错觉。
我相信程序必须缓存它读取的值,并在无法从注册表中读取新值时使用其最后一个有效值。 (或者它可能有一些内置的默认值。)
问题肯定是权限问题。这可以解释为什么当它以管理员身份运行时,它确实能够从注册表中读取新值,因为有了管理员权限,它就无法被阻止。
我建议您使用 regedit 和 Explorer 将注册表项的权限与程序文件的权限进行比较.exe
。您可以使用 regedit 将程序运行时的帐户(具有读取权限)添加到相关项。