所以基本上我有一个服务,它可以作为我的程序更新管理器。这就是我努力制作一个不需要用户登录的自动更新程序。
因此,安装时我的更新管理器会使用以下代码创建一些初始注册表值/结构:
LPCWSTR strInITKeyName = L"SOFTWARE\\InIT\\";
DWORD rtime = 0;
HKEY InITKey;
LONG nInITError;
nInITError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0, 0, &InITKey);
if (ERROR_NO_MATCH == nInITError || ERROR_FILE_NOT_FOUND == nInITError)
{
std::cout << "Registry key not found. Setting up..." << std::endl;
long nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &InITKey, NULL);
if (ERROR_SUCCESS != nError)
std::cout << "Error: Could not create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl;
else
{
std::cout << "Successfully created registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl;
// See https://www.experts-exchange.com/questions/10171094/Using-RegSetKeySecurity.html for example
//SECURITY_DESCRIPTOR sd;
//PACL pDacl = NULL;
//RegSetKeySecurity(InITKey);
}
}
else if (nInITError == ERROR_ACCESS_DENIED)
{
long nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &InITKey, NULL);
if (ERROR_SUCCESS != nError)
std::cout << "Error: Could not create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl;
else
std::cout << "Successfully created registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl;
}
else if (ERROR_SUCCESS != nInITError)
{
std::cout << "Cannot open registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nInITError << std::endl;
rtime = 0;
}
// Generate guid
//
GUID guid;
HRESULT hr = CoCreateGuid(&guid);
// Convert the GUID to a string
OLECHAR* guidString;
StringFromCLSID(guid, &guidString);
// Setup registry values
// Sets clientguid value and ties to strInITKeyName
std::wstring clientguid = guidString; // InITKey
clientguid = clientguid.substr(1, 36);
LONG nClientGUIDError = RegSetValueEx(InITKey, L"clientguid", NULL, REG_SZ, (const BYTE*)clientguid.c_str(), (clientguid.size() + 1) * sizeof(wchar_t));
if (nClientGUIDError)
std::cout << "Error: " << nClientGUIDError << " Could not set registry value: " << "clientguid" << std::endl;
else
std::wcout << "Successfully set InIT clientguid to " << clientguid << std::endl;
// ensure memory is freed
::CoTaskMemFree(guidString);
RegCloseKey(InITKey);
当它被卸载时,它会删除注册表值。我的实际程序是一个Windows服务,它将在已安装的计算机上运行,该计算机需要访问其中一些注册表值。
以前我没有这个更新管理器,而是在实际的程序服务中设置注册表中的值。阅读和写作工作就好了。但是,因为我已经切换到让我的Update Manager设置这些初始值并打算让我的主Windows服务访问它们。
当我尝试这样做时,尽管尝试了各种不同的安全令牌,例如KEY_READ ||,但我每次都会收到ERROR_ACCESS_DENIED错误。 KEY_WOW64_64KEY和其他尝试打开密钥时的组合。如上所述,我在设置令牌时正在键入KEY_ALL_ACCESS。我认为我应该能够很好地访问它,但它不会让我。我可以得出的唯一结论是,我的Update Manager以某种方式对注册表中的键/值拥有所有权。
从我的主Windows服务访问这些注册表文件的正确代码是什么?
我当前访问这些注册表值的代码(我在安装Update Manager时生成的clientguid 参见上面的代码):
// Log a service start message to the Application log.
WriteEventLogEntry(L"InITService Starting in OnStart", EVENTLOG_INFORMATION_TYPE);
this->m_ServiceLogger->info("Initialized logger bruh");
// Query clientguid from registry
HKEY InITKey;
std::wstring valuename;
ULONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\InIT\\", 0, KEY_READ || KEY_WOW64_64KEY, &InITKey);
DWORD dwBufferSize = TOTALBYTES;
DWORD cbData;
WCHAR *wcBuffer = (WCHAR*)malloc(dwBufferSize);
cbData = dwBufferSize;
if (nError == ERROR_SUCCESS)
this->m_ServiceLogger->info("Getting reg");
if (nError == ERROR_SUCCESS)
{
std::wstring clientguid;
clientguid = L"";
valuename = L"clientguid";
nError = RegQueryValueExW(HKEY_LOCAL_MACHINE, valuename.c_str(), 0, NULL, (LPBYTE) wcBuffer, &cbData);
while (nError == ERROR_MORE_DATA) // Get a buffer that is big enough if not already
{
this->m_ServiceLogger->info("Increasing clientguid buffer size");
dwBufferSize += BYTEINCREMENT;
wcBuffer = (WCHAR*) realloc( wcBuffer, dwBufferSize );
cbData = dwBufferSize;
nError = RegQueryValueExW(HKEY_LOCAL_MACHINE, valuename.c_str(), 0, NULL, (LPBYTE)wcBuffer, &cbData);
}
if (ERROR_SUCCESS == nError)
{
clientguid = wcBuffer;
std::string cg(clientguid.begin(), clientguid.end());
this->m_ClientGuid = cg;
this->m_ServiceLogger->info("Clientguid yo: " + cg);
}
else if (nError = ERROR_ACCESS_DENIED)
this->m_ServiceLogger->info("ClientGUID: Access Denied");
if (!this->checkRegistryValues())
{
this->generateRegistry();
}
}
else
{
std::stringstream errstr;
errstr << nError;
this->m_ServiceLogger->info("Error: " + errstr.str() + " RegOpenKeyEx failed");
}
this->setSchedulingUtility(); // Hardcoded to set scheduled update at 1:00 AM
WriteEventLogEntry(L"InITService Initialized Schedule in OnStart", EVENTLOG_INFORMATION_TYPE);
this->m_ServiceLogger->info("Initialized ClientGUID: " + this->m_ClientGuid);
this->m_ServiceLogger->info("Initialized CurrentVersion: " + this->m_CurrentVersion);
this->m_ServiceLogger->info("Initialized WebServerURL: " + this->m_POSTAddress);
this->m_ServiceLogger->flush();
RegCloseKey(InITKey);
// Queue the main service function for execution in a worker thread.
CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);
答案 0 :(得分:1)
调用RegOpenKeyEx()
时,您需要使用BITWISE OR(|
)运算符而不是LOGICAL OR(||
)运算符。变化:
KEY_READ || KEY_WOW64_64KEY
要:
KEY_READ | KEY_WOW64_64KEY
但是,当您的Update Manager调用RegOpenKeyEx()
时,它根本没有指定任何访问权限,它将samDesired
参数设置为0.应该将其设置为至少{{1相反。如果KEY_SET_VALUE
失败,则会调用RegCreateKeyEx()
,并将RegOpenKeyEx()
设置为samDesired
。不要这样做。仅使用您实际需要的访问权限(KEY_ALL_ACCESS
等)。
无论如何,无论如何都不需要同时调用KEY_SET_VALUE
和RegOpenKeyEx()
。只需自己致电RegCreateKeyEx()
即可。它将打开现有密钥,并创建一个不存在的密钥。它的RegCreateKeyEx()
输出参数会告诉你发生了什么。
此代码中还有其他错误。就像将错误的dwDisposition
传递给HKEY
,而不是正确检查RegQueryValueEx()
错误代码(使用ERROR_ACCESS_DENIED
赋值运算符而不是=
比较运算符) 。并且内存泄漏。
尝试更像这样的东西:
更新管理器:
==
计划服务:
LPCWSTR strInITKeyName = L"SOFTWARE\\InIT\\";
HKEY InITKey;
DWORD dwDisposition;
LONG nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_WOW64_64KEY, NULL, &InITKey, &dwDisposition);
if (ERROR_SUCCESS != nError)
{
std::cout << "Error: Could not open/create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl;
}
else
{
std::cout << "Successfully " << ((REG_CREATED_NEW_KEY == dwDisposition) ? "created" : "opened") << " registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl;
// Generate guid and convert to a string
//
std::wstring clientguid;
GUID guid;
HRESULT hr = CoCreateGuid(&guid);
if (FAILED(hr))
{
std::cout << "Error: Could not generate clientguid" << std::endl << "\tERROR: " << (int)hr << std::endl;
}
else
{
WCHAR guidString[40] = {0};
int len = StringFromGUID2(guid, guidString, 40);
if (len > 2)
{
// Sets clientguid value and ties to strInITKeyName
clientguid.assign(&guidString[1], len-2);
}
}
// Setup registry values
nError = RegSetValueEx(InITKey, L"clientguid", NULL, REG_SZ, (const BYTE*) clientguid.c_str(), (clientguid.size() + 1) * sizeof(wchar_t));
if (ERROR_SUCCESS != nError)
std::cout << "Error: Could not set registry value: clientguid" << std::endl << "\tERROR: " << nError << std::endl;
else
std::wcout << "Successfully set InIT clientguid to " << clientguid << std::endl;
RegCloseKey(InITKey);
}