簡體   English   中英

如何讀取/更改另一個 Windows 服務創建的注冊表值?

[英]How do I read/change the registry values that another windows service created?

所以基本上我有一個服務,它旨在充當我的程序更新管理器。 這一切都是為了制作一個不需要用戶登錄的自動更新程序。

因此,我的更新管理器在安裝時會使用以下代碼創建一些初始注冊表值/結構:

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 服務,它將在需要訪問其中一些注冊表值的已安裝計算機上運行。

以前我沒有這個更新管理器,而是在實際程序服務中設置注冊表中的值。 那時閱讀和寫作工作得很好。 但是因為我已經切換到讓我的更新管理器設置這些初始值並打算讓我的主 Windows 服務訪問它們。

當我嘗試這樣做時,盡管嘗試了各種不同的安全令牌(如 KEY_READ ||),但每次都收到 ERROR_ACCESS_DENIED 錯誤。 KEY_WOW64_64KEY 和其他在嘗試打開密鑰時的多種組合。 正如您在上面看到的,我在設置令牌時正在使用 KEY_ALL_ACCESS。 我認為我應該能夠很好地訪問它,但它不允許我。 我能得出的唯一結論是我的更新管理器以某種方式擁有注冊表中的鍵/值的所有權。

從我的主 Windows 服務訪問這些注冊表文件的正確代碼是什么?

我當前用於訪問這些注冊表值的代碼(我在安裝更新管理器時生成的 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);

調用RegOpenKeyEx() ,您需要使用 BITWISE OR ( | ) 運算符而不是 LOGICAL OR ( || ) 運算符。 改變:

KEY_READ || KEY_WOW64_64KEY

到:

KEY_READ | KEY_WOW64_64KEY

但是,當您的更新管理器調用RegOpenKeyEx() ,它根本沒有指定任何訪問權限,而是將samDesired參數設置為 0。它應該至少將其設置為KEY_SET_VALUE 如果RegOpenKeyEx()失敗,當它調用RegCreateKeyEx()時,它會將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);
}

節目服務:

...

// Query clientguid from registry
HKEY InITKey;

LONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\InIT\\", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &InITKey);

if (ERROR_SUCCESS != nError)
{
    std::stringstream errstr;
    errstr << nError;
    this->m_ServiceLogger->info("Error: " + errstr.str() + " RegOpenKeyEx failed");
}
else
{
    this->m_ServiceLogger->info("Getting reg");

    std::vector<BYTE> buffer(TOTALBYTES + sizeof(wchar_t), 0); // extra room for a null terminator, in case it is missing in the Registry data
    DWORD cbData = TOTALBYTES;

    do
    {
        nError = RegQueryValueExW(InITKey, L"clientguid", 0, NULL, &buffer[0], &cbData);

        if (ERROR_MORE_DATA != nError)
            break;

        // Get a buffer that is big enough if not already
        this->m_ServiceLogger->info("Resizing clientguid buffer");

        buffer.resize(cbData + sizeof(wchar_t));
    }
    while (true);

    if (ERROR_SUCCESS == nError)
    {
        std::wstring clientguid = (WCHAR*) &buffer[0];
        std::string cg(clientguid.begin(), clientguid.end());

        this->m_ClientGuid = cg;
        this->m_ServiceLogger->info("Clientguid yo: " + cg);
    }
    else if (ERROR_ACCESS_DENIED == nError)
    {
        this->m_ServiceLogger->info("ClientGUID: Access Denied");
    }
    else
    {
        std::stringstream errstr;
        errstr << nError;
        this->m_ServiceLogger->info("Error: " + errstr.str() + " RegQueryValueEx failed");
    }

    RegCloseKey(InITKey);

    if (!this->checkRegistryValues())
    {
        this->generateRegistry();
    }
}

...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM