My goal is to get the current SetupPath of the installed Outlook Version.
I use the following code in order to achieve that:
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);
But however this won't work. It fails at opening the Key.
EDIT
I found that the "open key failed" Output was simply an Acces Denied caused by non admin rights. But however if i run it in Admin mode the output is a Hexadecimal Value which will change everytime.
First, since you are using C++, consider making your coding life simpler, defining a simple class that automatically calls RegCloseKey()
on the open key.
Then, when you open the key, consider the minimum flag you need for access: in particular, this sounds like KEY_READ
in your case.
Moreover, I would call RegGetValue()
instead of RegQueryValueEx()
, as the former makes sure that the returned string is NUL-terminated (simplifying your code a little bit).
Moreover, when you print the CString
, consider calling its GetString()
method, to get the const wchar_t*
C-style string pointer, instead of passing the CString
object to cout
.
Finally, I've simplified your code using wchar_t
instead of TCHAR
.
Compilable code follows (I used VS2015 and tested it on 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;
}
Output:
Path = [C:\Program Files (x86)\Microsoft Office\Root\Office16\]
In addition, you can even use RegGetValue()
to automatically open (and close) the registry key for you, e.g.:
#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;
}