我的目标是获取已安装的Outlook版本的当前SetupPath。
我使用以下代码来实现:
HKEY hKey;
LONG lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE"),
0L,
KEY_ALL_ACCESS,
&hKey);
if (lReturn == ERROR_SUCCESS)
{
CString strData;
DWORD dwSize = 1024;
DWORD dwType;
lReturn = RegQueryValueEx(hKey,
_T("Path"),
0L,
&dwType,
(BYTE *)strData.GetBufferSetLength((int)dwSize),
&dwSize);
if (lReturn == ERROR_SUCCESS)
{
cout << strData;
}
else {
cout << "Read DWORD failed";
}
}
else {
cout << "Open Key failed";
}
RegCloseKey(hKey);
但是这不起作用。它无法打开钥匙。
修改的
我发现“打开密钥失败”输出只是由非管理员权限导致的被拒绝的。但是,如果我在管理模式下运行它,输出是一个十六进制值,每次都会改变。
答案 0 :(得分:0)
首先,由于您使用的是C ++,因此请考虑使编码生活更简单,定义一个简单的类,自动在开放键上调用RegCloseKey()
。
然后,当您打开密钥时,请考虑访问所需的最小标记:特别是,在您的情况下,这听起来像KEY_READ
。
此外,我会调用RegGetValue()
而不是RegQueryValueEx()
,因为前者确保返回的字符串是NUL终止的(稍微简化了代码)。
此外,当您打印CString
时,请考虑调用其GetString()
方法,以获取const wchar_t*
C风格的字符串指针,而不是将CString
对象传递给cout
。
最后,我使用wchar_t
代替TCHAR
简化了代码。
随后是可编译代码(我使用的是VS2015并在Windows 10上测试过):
#include <Windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
using namespace std;
class ScopedKey
{
public:
explicit ScopedKey(HKEY hKey)
: m_hKey(hKey)
{
}
~ScopedKey()
{
::RegCloseKey(m_hKey);
}
HKEY Get() const
{
return m_hKey;
}
// Ban copy
ScopedKey(const ScopedKey&) = delete;
ScopedKey& operator=(const ScopedKey&) = delete;
private:
HKEY m_hKey;
};
int main()
{
constexpr int kExitOk = 0;
constexpr int kExitError = 1;
//
// Open the registry key
//
HKEY hKey;
LONG retCode = ::RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE",
0,
KEY_READ,
&hKey
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegOpenKeyEx() failed; error code = " << retCode << '\n';
return kExitError;
}
// Auto-close the registry key
ScopedKey key(hKey);
//
// Get the size of the path string
//
const wchar_t* valueName = L"Path";
DWORD dataSizeInBytes = 0;
retCode = ::RegGetValue(
hKey,
nullptr,
valueName,
RRF_RT_REG_SZ,
nullptr,
nullptr,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
//
// Read the path string from the registry
//
const DWORD sizeInWchars = dataSizeInBytes / sizeof(wchar_t);
CStringW str;
wchar_t* buffer = str.GetBuffer(sizeInWchars);
retCode = ::RegGetValue(
hKey,
nullptr,
valueName,
RRF_RT_REG_SZ,
nullptr,
buffer,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
str.ReleaseBuffer();
wcout << L"Path = [" << str.GetString() << L"]\n";
// Auto-closed at end of scope
// ::RegCloseKey(hKey);
return kExitOk;
}
输出
Path = [C:\Program Files (x86)\Microsoft Office\Root\Office16\]
此外,您甚至可以使用RegGetValue()
为您自动打开(和关闭)注册表项,例如:
#include <Windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
using namespace std;
int main()
{
constexpr int kExitOk = 0;
constexpr int kExitError = 1;
//
// Get the size of the path string
//
const wchar_t* subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE";
const wchar_t* valueName = L"Path";
DWORD dataSizeInBytes = 0;
LONG retCode = ::RegGetValue(
HKEY_LOCAL_MACHINE,
subKey,
valueName,
RRF_RT_REG_SZ,
nullptr,
nullptr,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
//
// Read the path string from the registry
//
const DWORD sizeInWchars = dataSizeInBytes / sizeof(wchar_t);
CStringW str;
wchar_t* buffer = str.GetBuffer(sizeInWchars);
retCode = ::RegGetValue(
HKEY_LOCAL_MACHINE,
subKey,
valueName,
RRF_RT_REG_SZ,
nullptr,
buffer,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
str.ReleaseBuffer();
wcout << L"Path = [" << str.GetString() << L"]\n";
return kExitOk;
}