【问题标题】:InstallShield: new Basic MSI major upgrade from older InstallScript MSI leaves old ARP entryInstallShield:从旧的 InstallScript MSI 进行新的基本 MSI 主要升级会留下旧的 ARP 条目
【发布时间】:2016-09-26 08:36:03
【问题描述】:

我正在 IS 2015 Professional 中进行新的基本 MSI 安装,它是以前使用 installscript MSI 安装的产品的重大升级(我认为是 2012 年制作的)。

版本、产品、包代码不同,共享一个升级代码。

旧安装提供了为所有用户或仅当前用户安装的选项,新安装当前设置为仅“所有用户”。

在 virtualbox 中测试时(已为“所有用户”安装了旧版本),旧安装卸载,新版本安装成功,但旧版本的添加/删除程序中仍然存在损坏的条目。当然也有新版本的新条目。

令人沮丧的部分是我确信我曾经有过这个工作(最初我遇到了问题,因为我没有设置升级路径),但我不知道我可能做了什么改变来导致这个错误。

有什么想法可以解决这个问题或下一步该去哪里看吗?

【问题讨论】:

    标签: windows-installer installation upgrade installshield uninstallation


    【解决方案1】:

    这是 InstallShield 2012 中的一个已知(但未记录)错误。
    如果您对使用 IS 2012 编写的 MSI 项目进行主要或次要升级,则会将旧的 InstallShield_{} 密钥保留在 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall 下。
    这使 Windows 在添加/删除程序中显示旧条目。

    我不知道解决它的好方法,我所做的是编写一个我在每次升级结束时调用的 InstallScript 函数;见下文。该参数是出现在 ARP 中的产品名称。该功能会删除所有具有此显示名称的键,当然除了刚刚安装的键!

    function FixMajorUpgradeBug(szDisplayName)
        STRING szFunctionName,szBaseKey,svString,svValue;
        LIST listResults;
        NUMBER nResult;
    begin
        szBaseKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
        // go over the key, and remove all InstallShield_{} keys which have the given display name, except for the version installed by this very setup
        RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
        listResults = ListCreate(STRINGLIST);
        nResult = RegDBQueryKey(szBaseKey,REGDB_KEYS,listResults);
        if nResult = 0 then
            nResult = ListGetFirstString (listResults, svString); 
            while (nResult != END_OF_LIST) 
                if (svString % "InstallShield_{") then
                    if !(svString % PRODUCT_GUID) then
                        // delete only keys with the specified product name!
                        svValue = "";
                        GU_RegistryGetValue(szBaseKey + "\\" + svString,"DisplayName",svValue);
                        if (svValue = szDisplayName) then
                            RegDBSetDefaultRoot(HKEY_LOCAL_MACHINE);
                            RegDBDeleteKey(szBaseKey + "\\" + svString);
                        endif;
                    endif;
                endif;
                nResult = ListGetNextString (listResults, svString); 
            endwhile; 
        endif;
        ListDestroy(listResults);
    end;
    

    注意 - 如果您的产品是在每次升级后更改显示名称的产品之一(例如,在名称中包含版本号),您需要进行比svValue = szDisplayName 更智能的比较。

    【讨论】:

    • 我认为这会很好,但我们正在努力准备迁移到 WiX,我想避免依赖任何安装脚本。
    • 那么我猜你最终会在 C# 中编写一个类似的自定义操作 ...
    【解决方案2】:

    我最终得到了 2 个 CA,一个用于 32 位,一个用于 64 位。 64位: "[SystemFolder]cmd.exe" /C "echo y | reg delete HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\InstallShield_[ISACTIONPROP1]"

    作为具有执行条件的提交执行CA:VersionNT64 AND IS_MAJOR_UPGRADE

    “ISACTIONPROP1”在升级路径中定义(作为“检测属性”)来保存以前的产品代码。

    CA 在 Install Exec 中执行(在“WriteRegistryValues”和 Admin Exec 序列之后(在“ScheduleReboot”之后)。

    32 位 CA 几乎相同,只是条件为“NOT VersionNT64”并且注册表路径不同(基本上没有密钥路径中的 Wow6432)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      相关资源
      最近更新 更多