Лучший метод для изменения времени установки папок установки (MSI)

Контекст:

Так что это пакет, который устанавливает старое программное обеспечение. Когда я говорю, старый, думаю, 20 лет. Он огромен, мы зависим от него, мы пишем замену, но пока он не будет готов, мы застрянем с этим старым приложением в течение следующих нескольких лет.

Проблема:

Msi должен передаваться через SCCM, и наш ИТ-отдел настаивает на том, что это означает, что у нас не может быть никаких элементов пользовательского интерфейса в этом пакете msi (например, поиск пути установки).

Программа должна быть установлена ​​по адресу: volume + ": \" + название компании. Путь по умолчанию - [WindowsVolume] название компании

Мы также должны сгенерировать несколько пустых папок для правильной работы программы, например, "ПЕРЕДАЧА"

Чтобы достичь этого, без утопления в предупреждениях ICE, wix xml выглядит так:

<Directory Id="TARGETDIR" Name="SourceDir">
    <Directory Id="VOLUME_WindowsVolume_companyabbreviation" Name="WindowsVolume_companyabbreviation">
        <Directory Id="Directory_0_1_0" Name="subfolderA">
            <Directory Id="Directory_0_2_1" Name="subsubfolderAA" />
        </Directory>
        <Directory Id="Directory_0_1_0" Name="subfolderB" /> 
        <!-- and a lot more directories -->
        <Directory Id="Directory_0_2_6" Name="TRANSFER" />
    </Directory>
</Directory>

<!-- Component groups -->
    <ComponentGroup Id="FEATUREID_Directory_0_2_6" Directory="VOLUME_WindowsVolume_companyabbreviation">
        <Component Id="INSTALL_Directory_0_2_6" Guid="4a9cd25e-4d66-4398-af52-356a3b48c337">
            <CreateFolder Directory="Directory_0_2_6" />
            <RemoveFile Id="PurgeCacheFolderDirectory_0_2_6" Name="*.*" On="uninstall" />
            <RemoveFolder Id="Directory_0_2_6" On="uninstall" />
        </Component>
    </ComponentGroup>
<!-- more Component Groups, components, features, etc.. -->

<SetDirectory Id="VOLUME_WindowsVolume_companyabbreviation" Value="[WindowsVolume]companyabbreviation" />

Это работает как задумано.

Поскольку это старое приложение (которое никогда не упаковывалось, а распространялось через самодельную программу установки), целевые машины обычно имеют своего рода "установку" до получения msi.

Поэтому я создал специальное действие для очистки из старой домашней версии. Который также работает хорошо. Мы просто следим за тем, чтобы он запускался только при попытке установить систему, в которой никто ранее не устанавливал через MSI.

<Binary Id="CustomActionsId" SourceFile="../customActions/CA UPDATE FROM REGISTRY.CA.dll" />
<CustomAction Id="Launch_UPDATE_FROM_REGEDIT" BinaryKey="CustomActionsId" DllEntry="UPDATE_FROM_REGISTRY" Execute="immediate" Return="check" />
<InstallExecuteSequence>
     <Custom Action="Launch_UPDATE_FROM_REGEDIT" Before="CostFinalize">NOT Installed</Custom>
</InstallExecuteSequence>

Теперь мы должны быть готовы к выпуску:)

Кроме того, что мы только что узнали, что кто-то мой предшественник? давным-давно решили, что они расскажут клиентам, как программа может быть перемещена из местоположения по умолчанию...

Видите, разработчики могут использовать несколько установок и просто выбирать, какую из них запускать, изменяя набор ключей реестра.

Таким образом, в основном разработчик позаботился о том, чтобы приложение можно было перенести на другой диск, например: D: \ companyabbreviation, и через реестр отредактировать, какую версию запустить. какую папку TRANSFER использовать, и так далее, и так далее...

Что ж, вы можете утверждать, что для этого нужно много разделов, но за время до того, как компания узнала о CVS, SVN, GIT и т. Д., Я думаю, это имело смысл...

Позже другой разработчик увидел эту функцию как способ обойти некоторые клиенты без административных прав (так что вы не можете установить на WindowsVolume Root) и решил, что старая программа установки будет уважать ключ реестра при его наличии. И что если ключа не было, он заставил бы старый установщик создать его и установить значение в пути по умолчанию.

Как следствие, спустя годы, теперь наш MSI, тоже должен это учитывать, если кто-то из наших пользователей переместил приложение... (и мы проверили, некоторые делают это..)

Наша идея - использовать пользовательское действие для обновления путей:

Мы сделали вспомогательные функции:

    public static ActionResult getCustomActionInfo(Session session, string WhereSourceStringContains, ref List<string> data)
    {
        var CustomActionsActions = session.Database.ExecuteQuery("SELECT Action from CustomAction");
        var CustomActionsTypes = session.Database.ExecuteQuery("SELECT Type from CustomAction");
        var CustomActionsSources = session.Database.ExecuteQuery("SELECT Source from CustomAction");
        var CustomActionsTargets = session.Database.ExecuteQuery("SELECT Target from CustomAction");

        session.Log("Retrieved " + CustomActionsTargets.Count.ToString() + " custom actions");
        int index = -1;
        for (int i = 0; i < CustomActionsTargets.Count; i++)
        {
            if (CustomActionsTypes[i].ToString().Trim() == "51" && CustomActionsSources[i].ToString().Contains(WhereSourceStringContains))
            {
                index = i;
                break;
            }
        }

        if (index == -1)
        {
            session.Log("Error could not locate the " + WhereSourceStringContains + " setDirectory customAction, cannot set a different installation target..");
            return ActionResult.SkipRemainingActions;
        }
        else
        {
            session.Log("row found with index: " + index.ToString() + "\r\n\t [action] => " + CustomActionsActions[index].ToString() + "\r\n\t [type]   => " + CustomActionsTypes[index].ToString() + "\r\n\t [source] => " + CustomActionsSources[index].ToString() + "\r\n\t [target] => " + CustomActionsTargets[index].ToString());
            data.Add(index.ToString());
            data.Add(CustomActionsActions[index].ToString());
            data.Add(CustomActionsTypes[index].ToString());
            data.Add(CustomActionsSources[index].ToString());
            data.Add(CustomActionsTargets[index].ToString());
        }

        return ActionResult.Success;
    }

а также:

    public static void setCustomActionTarget(Session session, string ActionData, string TargetData)
    {
        session.Database.Execute("UPDATE CustomAction SET Target='" + TargetData + "' WHERE Action='" + ActionData + "'");
    }

а затем этот код, который делает вещи происходить:

[CustomAction]
public static ActionResult UPDATE_FROM_REGISTRY(Session session)
{
    var view32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
    RegistryKey ProductKey = view32.OpenSubKey(@"secretPath\To\Applications\Key");

    /* instDir is the previous location of the folder */
    string instDir = ProductKey.GetValue("instDir ").ToString().Trim();
    session.Log("discovered a instDir  key: " + instDir );
    string BaseDir = instDir .Substring(0, DataDir.ToUpper().LastIndexOf("\\")).ToUpper();

    List<string> PRODUCT = new List<string>();
    ActionResult test = getCustomActionInfo(session, "companyabbreviation", ref PRODUCT );
    if (test != ActionResult.Success) return test;
    string BaseTarget = SABITC[4];
    session.Log("BaseTarget: " + BaseTarget + " == BaseDir: " + BaseDir.Replace(@"C:\", "[WindowsVolume]") + " ?? ");
   if (BaseTarget.ToUpper() == BaseDir.Replace(@"C:\", "[WindowsVolume]").ToUpper())
    {
        session.Log("\tdefault directory was used for SABITC, do nothing to change that :D ");
    }
    else
    {
        session.Log("\tinstall at old location: " + BaseDir);
        setCustomActionTarget(session, SABITC[1], BaseDir);  //here throws exception

        //TODO: update "target" and instdir in msi registry entries, to ensure information is not overwritten by defaults..
     }
}

ну, видимо, вам не разрешено изменять базу данных сеансов, но тогда как мы можем этого добиться?

Я не заинтересован в создании свойства в wix xml, если я могу избежать этого. - Причина в том, что в настоящее время xml генерируется автоматически, так как наши разработчики (в основном инженеры) не должны изучать wix, чтобы иметь возможность поддерживать математический код.

Если нам нужно использовать свойства, определенные в xml, нам нужно как-то сообщить настраиваемому действию, что такое идентификатор узла каталога.

Скажем, клиент решил переместить только указанную папку TRANSFER: это можно сделать так:

<!-- information for the custom action -->
<Property Id="TRANSFER_ID" Value="Directory_0_2_6"/>
<!-- values below can be overwritten by the custom action:
     but unfortunately also this line also sets default paths,
     and in case of errors, it makes the directory tree above unreliable
     at least for humans that read it in the future.-->
<Property Id="Directory_0_2_6" Value="C:\companyabbrevation\TRANSFER\" />

Чтобы сделать это, нам нужно было бы вручную изменить все эти автоматически сгенерированные файлы wix и установить значения пути "по умолчанию" в соответствии с тем, что неявно установлено в дереве каталогов. - или сделать что-то, что проанализировало xml, нашло правильные идентификаторы каталогов, а затем добавил свойства узлов.

возможно, если мы сможем добавить свойство MSI во время установки, мы все равно сможем заставить это работать?

Сводка требований к неработающему решению:

* change installation folder using information found in registry
* do not overwrite registry information for specific keys, if they are present.

0 ответов

Другие вопросы по тегам