系统启动时,我有一个Windows服务及其系统和用户进程正在加载。在加载用户进程后(以管理员身份),我立即调用QueryDisplayConfig来检查显示特定信息。问题在于,有时QueryDisplayConfig有时仅返回一个既不是其可能的返回值的值。

解决方法是在调用QueryDisplayConfig打开和关闭Windows注册表之前。这很有趣,但是以某种方式可以解决问题。我想知道regedit.exe会执行什么操作,从而迫使Windows更新注册表。

可能没有针对此问题的解决方案,我不得不诉诸以下解决方案,这也是一种解决方案:

LONG lResult = QueryDisplayConfig(QDC_DATABASE_CURRENT, &PathArraySize, PathArray.data(), &ModeArraySize, ModeArray.data(), &CurrentTopology);
while (lResult != ERROR_SUCCESS &&
       lResult != ERROR_INVALID_PARAMETER &&
       lResult != ERROR_NOT_SUPPORTED &&
       lResult != ERROR_ACCESS_DENIED &&
       lResult != ERROR_GEN_FAILURE &&
       lResult != ERROR_INSUFFICIENT_BUFFER)
{
    Sleep(300);
    lResult = QueryDisplayConfig(QDC_DATABASE_CURRENT, &PathArraySize, PathArray.data(), &ModeArraySize, ModeArray.data(), &CurrentTopology);
}


我宁愿不求助于这种丑陋的解决方法,并让Windows以编程方式更新/刷新注册表。

最佳答案

如果我关闭/重新打开REGEDIT,则通过REGEDIT搜索注册表时,有时会得到不同的结果,而如果不这样做,则会得到不同的结果。这是在WS08R2上。我以为这是REGEDIT本身的问题。现在听起来像是Windows的错误。如果是这种情况,将没有任何不错的解决方法。

基于Windows Internals,注册表在内存中进行操作。因此,对值/键的任何查询都将始终来自内存。如果值/键当前不在内存中,则将首先读取它,但是读取后的代码路径与它已经在内存中相同。不应出现磁盘上的配置单元比内存中的配置单元电流更大的情况。

因此,根据记录在案的设计,“刷新”注册表实际上没有任何意义。因此,我不希望有一个“刷新”的API。

我认为做到这一点的最丑陋的方法(取决于您的审美观念)是尝试模仿REGEDIT的功能。当您关闭它时,它将保存它上次在注册表中浏览的位置,因此,下次您运行REGEDIT时,它将(至少)打开并读取填充REGEDIT窗口所需的任何配置单元,键和值。

因此,下次您从QueryDisplayConfig获取意外值时,可以运行REGEDIT,并查看正在显示的键和值。然后将其编码到您的程序中。当然,您实际上不必显示这些值,而只需打开并阅读它们即可。

10-08 09:15