65.9K
CodeProject 正在变化。 阅读更多。
Home

快速注册表导航

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.66/5 (12投票s)

2005 年 12 月 29 日

2分钟阅读

viewsIcon

84318

downloadIcon

379

一个工具,可以快速导航到使用 Regedit 的特定键/值。

引言

你多少次在 CP 或互联网上的其他地方看到一篇包含长注册表键引用的文章,并想如果可以直接跳转到该键而无需在 regedit 中输入它该有多好?我想我找到了一个解决方案。

查找和打开 Regedit

要查找 Regedit 的窗口,我们搜索和/或创建“RegEdit_RegEdit”窗口类。

CWnd *pWndRegeditMain = CWnd::FindWindow(_T("RegEdit_RegEdit"), NULL);
if (NULL == pWndRegeditMain)
{
    rShellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    rShellExecuteInfo.fMask  = SEE_MASK_NOCLOSEPROCESS; 
    rShellExecuteInfo.lpVerb = _T("open"); 
    rShellExecuteInfo.lpFile = _T("regedit.exe"); 
    rShellExecuteInfo.nShow  = SW_SHOWNORMAL; 

    ShellExecuteEx(&rShellExecuteInfo);
    WaitForInputIdle(rShellExecuteInfo.hProcess, INFINITE);

    pWndRegeditMain = CWnd::FindWindow(_T("RegEdit_RegEdit"), NULL);
}

此时,pWndRegeditMain 应该具有非 NULL 值。接下来,我们需要显示 Regedit 的窗口并将其置于前景。

pWndRegeditMain->ShowWindow(SW_SHOW);
pWndRegeditMain->SetForegroundWindow();

TreeView

由于 Regedit 维护上次访问的键(参见 补充说明),我们必须确保一个已知的起始点:根节点。为此,我们只需“发送”左箭头键几十次即可。

CWnd WndRegeditTreeview;
WndRegeditTreeview.Attach(FindWindowEx(pWndRegeditMain->GetSafeHwnd(), 
                                       NULL, _T("SysTreeView32"), NULL));
WndRegeditTreeview.SetForegroundWindow();
WndRegeditTreeview.SetFocus();

// close it up so we have a known starting point

for (int nDepth = 0; nDepth < 30; nDepth++)
    WndRegeditTreeview.SendMessage(WM_KEYDOWN, VK_LEFT, 0);

现在我们位于根节点,可以开始向下导航到所需的键。对于这段代码而言,键可以以两种方式形成

key\ 
key\value

为了区分两者,我们使用

CString strRegistryPath(argv[1]);

// the path must begin with a backslash

if (strRegistryPath.Left(1) != _T('\\'))
    strRegistryPath = _T('\\') + strRegistryPath;

int nIndex       = strRegistryPath.ReverseFind(_T('\\'));
CString strValue = strRegistryPath.Mid(nIndex + 1);
strRegistryPath  = strRegistryPath.Left(nIndex);

请注意,当遇到反斜杠字符时,我们会“发送”右箭头键。

for (nIndex = 0; nIndex < strRegistryPath.GetLength(); nIndex++)
{
    UINT uVirtualKey = strRegistryPath[nIndex];

    if (_T('\\') == uVirtualKey)  
        WndRegeditTreeview.SendMessage(WM_KEYDOWN, VK_RIGHT, 0);
    else
    {
        uVirtualKey = toupper(uVirtualKey);
        WndRegeditTreeview.SendMessage(WM_CHAR, uVirtualKey, 0);
    }
}

此时,我们应该位于左窗格中的所需键。

ListView

现在,如果也指定了一个值,我们必须切换到列表视图并选择它。

CWnd WndRegeditListview;
WndRegeditListview.Attach(FindWindowEx(pWndRegeditMain->GetSafeHwnd(), 
                                       NULL, _T("SysListView32"), NULL));
WndRegeditListview.SetForegroundWindow();
WndRegeditListview.SetFocus();

// have to wait for Regedit to update the listview

Sleep(1000); 

// select the value

WndRegeditListview.SendMessage(WM_KEYDOWN, VK_HOME, 0);

for (nIndex = 0; nIndex < strValue.GetLength(); nIndex++)
{
    UINT uVirtualKey = toupper(strValue[nIndex]);
    WndRegeditListview.SendMessage(WM_CHAR, uVirtualKey, 0);
}

我们的值现在应该被选中。我们可以分离临时视图对象并退出程序。

用法

从命令行提示符,只需键入 regeditgo,后跟所需的键\值。如果键和/或值包含任何空格,则需要用双引号将其括起来。

一旦 Regedit 完成向下导航到所需的键,你应该会看到类似于以下内容

附加功能

我喜欢的一个功能是 Regedit 自动选择上次访问的键。该键的名称存储在以下值中

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit\LastKey

你可以通过删除对 Regedit 键的写入权限来阻止 Regedit 维护上次访问的键。但是,有一个权衡。通过这样做,你也会禁止 Regedit 更新 FindFlagsView 值。

© . All rights reserved.