Specify the registry uninstall key location/hive via [Code]

前端 未结 2 943
旧时难觅i
旧时难觅i 2020-12-18 13:33

Inno Setup by default looks at the PrivilegesRequired setup variable, if this is set to admin or poweruser, the installer installs the

2条回答
  •  长情又很酷
    2020-12-18 14:10

    The PrivilegesRequired=none solution was not what I wanted. In some cases, it still prompts for elevation on administrator accounts and also the registry destination was still not reflective of the users selection.

    Since I was already using a native helper DLL in my Inno Setup project, I coded this in C++ as I'm more comfortable there. I'm calling this method is called in CurStepChanged where CurPage=ssDoneInstall. Just call this method with the [Setup] AppId and whether or not the registry keys should be installed locally or not.

    #include 
    extern "C" __declspec(dllexport)
    bool DetectAndMoveRegKeyW(LPCWSTR app_id, bool install_local)
    {
        std::wstring s_app = app_id;
        std::wstring path =
            L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + s_app + L"_is1";
        LPCWSTR c_path = path.c_str();
    
        LRESULT res;
        HKEY source = nullptr, subKey = nullptr;
    
        // try to find source in HKLM
        source = HKEY_LOCAL_MACHINE;
        res = RegOpenKeyExW(source, c_path, 0, KEY_READ, &subKey);
        if (subKey != nullptr)
            RegCloseKey(subKey);
    
        // try to find source in HKCU
        if (res != ERROR_SUCCESS)
        {
            subKey = nullptr;
            source = HKEY_CURRENT_USER;
            res = RegOpenKeyExW(source, c_path, 0, KEY_READ, &subKey);
            if (subKey != nullptr)
                RegCloseKey(subKey);
        }
    
        if (res != ERROR_SUCCESS)
            return false; // cant find the registry key
    
        HKEY dest = install_local ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
        if (source == dest)
            return true; // registry already in the right place
    
    
        // copy registry key to correct destination
        HKEY hOldKey;
        HKEY hNewKey;
        bool bResult = false;
        if (RegOpenKeyW(source, c_path, &hOldKey) == 0)
        {
            if (RegCreateKeyW(dest, c_path, &hNewKey) == 0)
            {
                bResult = (SHCopyKeyW(hOldKey, nullptr, hNewKey, 0) == 0);
                RegCloseKey(hNewKey);
            }
            RegCloseKey(hOldKey);
    
            if (bResult)
            {
                RegDeleteKeyW(source, c_path);
            }
        }
    
        return bResult;
    }
    

    I'm exporting this method as cdecl instead of stdcall, this is because VC++ ignores the C extern and mangles method names anyways when using stdcall. You'll need to import this as cdecl in inno (see inno docs for this). Also, of course this is the Unicode-only implementation, if you require an Ansi version it should be simple enough.

    IMPORTANT NOTICE:
    This code is incomplete, it doesn't account for 64bit registry redirection. Inno-Setup completely ignores windows registry redirection and this code doesn't search the 64 bit registry at all since Inno and itself are running in 32bit.

提交回复
热议问题