Как получить каталог установки?

MSI хранит каталог установки для будущих задач удаления.

Использование свойства INSTALLPROPERTY_INSTALLLOCATION (то есть "InstallLocation") работает, только если установщик установил свойство ARPINSTALLLOCATION во время установки. Но это свойство является необязательным и им почти никто не пользуется.

Как я могу получить каталог установки?


person Michael Damatov    schedule 01.11.2008    source источник


Ответы (6)


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

Используя WIX, я бы создал компонент, который создает ключ, сразу после тега Directy каталога установки, объявления

person CheGueVerra    schedule 01.11.2008
comment
Что вы используете для создания файла MSI, у каждого языка будут свои спецификации для получения этой информации. - person CheGueVerra; 01.11.2008
comment
Я сделал это с помощью InstallShield 11.5 (я знаю, что он устарел...). Проект BasicMSI. - person Michael Damatov; 01.11.2008

Я бы использовал MsiGetComponentPath() — вам нужны ProductId и ComponentId, но вы получите полный путь к установленному файлу — просто выберите тот, который ведет к местоположению вашего установочного каталога. Если вы хотите получить значение каталога для любого случайного MSI, я не верю, что существует API, который позволит вам это сделать.

person Community    schedule 20.08.2009

Я бы попытался использовать Installer.OpenProduct(код продукта). Это открывает сеанс, в котором вы можете запросить Property("TARGETDIR").

person Martin v. Löwis    schedule 01.11.2008

Попробуйте это: var sPath = this.Context.Parameters["assemblypath"].ToString();

person Community    schedule 01.04.2009

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

В тех случаях, когда я имею дело с установкой, которая этого не сделала, я использую встроенную функцию установщика Windows AppSearch: http://msdn.microsoft.com/en-us/library/aa367578(v=vs.85).aspx, чтобы найти каталог предыдущую установку, указав сигнатуру файла для поиска.

Подпись файла может состоять из имени файла, размера файла, версии файла и других свойств файла. Каждая подпись может быть указана с определенной степенью гибкости, поэтому вы можете найти разные версии одного и того же файла, например, указав диапазон версий для поиска. Ознакомьтесь с документацией SDK: http://msdn.microsoft.com/en-us/library/aa371853(v=vs.85).aspx

В большинстве случаев я использую основное приложение EXE и устанавливаю жесткую подпись, ища узкий диапазон версий файла с правильной версией и датой.

person Stein Åsmul    schedule 18.05.2011

Недавно мне нужно было автоматизировать установку Natural Docs через Кетарин. Я мог предположить, что он был установлен по пути по умолчанию (%ProgramFiles(x86)%\Natural Docs), но решил использовать безопасный подход. К сожалению, даже если установщик создал ключ на HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall, ни одно из его значений не привело меня к поиску установочного каталога.

Ответ Штейна предлагает функцию AppSearch MSI, и это выглядит интересно, но, к сожалению, установщик MSI Natural Docs не предоставляет таблицу подписей для его работы.

Поэтому я решил поискать в реестре любую ссылку на установочный каталог Natural Docs, и я нашел ее в ключе HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components.

Ключ реестра компонентов MSI

Я разработал Reg Class на C# для Ketarin, который допускает рекурсию. Поэтому я просматриваю все значения через HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components, и если исполняемый файл основного приложения (NaturalDocs.exe) находится в одном из значений подразделов, он извлекается (C:\Program Files (x86)\Natural Docs\NaturalDocs.exe становится C:\Program Files (x86)\Natural Docs) и добавляется в переменную системной среды %PATH% (так что я могу вызвать " NaturalDocs.exe" напрямую вместо использования полного пути).

«Класс» реестра (на самом деле функции) можно найти на GitHub (RegClassCS).

System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo("NaturalDocs.exe", "-h");
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;

var process = System.Diagnostics.Process.Start (startInfo);
process.WaitForExit();

if (process.ExitCode != 0)
{
    string Components = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components";

    bool breakFlag = false;

    string hKeyName = "HKEY_LOCAL_MACHINE";
    if (Environment.Is64BitOperatingSystem)
    {
        hKeyName = "HKEY_LOCAL_MACHINE64";
    }

    string[] subKeyNames = RegGetSubKeyNames(hKeyName, Components);
    // Array.Reverse(subKeyNames);
    for(int i = 0; i <= subKeyNames.Length - 1; i++)
    {
        string[] valueNames = RegGetValueNames(hKeyName, subKeyNames[i]);
        foreach(string valueName in valueNames)
        {
            string valueKind = RegGetValueKind(hKeyName, subKeyNames[i], valueName);
            switch(valueKind)
            {
                case "REG_SZ":
                // case "REG_EXPAND_SZ":
                // case "REG_BINARY":
                    string valueSZ = (RegGetValue(hKeyName, subKeyNames[i], valueName) as String);
                    if (valueSZ.IndexOf("NaturalDocs.exe") != -1)
                    {
                        startInfo = new System.Diagnostics.ProcessStartInfo("setx", "path \"%path%;" + System.IO.Path.GetDirectoryName(valueSZ) + "\" /M");
                        startInfo.Verb = "runas";

                        process = System.Diagnostics.Process.Start (startInfo);
                        process.WaitForExit();

                        if (process.ExitCode != 0)
                        {
                            Abort("SETX failed.");
                        }

                        breakFlag = true;
                    }
                    break;

                /*  
                case "REG_MULTI_SZ":
                    string[] valueMultiSZ = (string[])RegGetValue("HKEY_CURRENT_USER", subKeyNames[i], valueKind);

                    for(int k = 0; k <= valueMultiSZ.Length - 1; k++)
                    {
                        Ketarin.Forms.LogDialog.Log("valueMultiSZ[" + k + "] = " + valueMultiSZ[k]);
                    }
                    break;
                */

                default:
                    break;
            }

            if (breakFlag)
            {
                break;
            }
        }

        if (breakFlag)
        {
            break;
        }
    }
}

Даже если вы не используете Ketarin, вы можете легко вставить функцию и создать ее с помощью Visual Studio или CSC.

Можно использовать более общий подход, используя RegClassVBS, который допускает рекурсию ключей реестра и не зависит от .NET. Платформа фреймворка или процессы сборки.

Обратите внимание, что процесс перечисления ключа компонентов может сильно нагружать ЦП. В приведенном выше примере есть параметр «Длина», который вы можете использовать, чтобы показать пользователю некоторый прогресс (может быть, что-то вроде «i from (subKeysName.Length — 1) оставшихся ключей» — будьте изобретательны). Аналогичный подход можно использовать в RegClassVBS.

Оба класса (RegClassCS и RegClassVBS) имеют документацию и примеры, которые могут вам помочь, и вы можете использовать их в любом программном обеспечении и внести свой вклад в их разработку, сделав коммит в репозитории git и (конечно) открыв вопрос на его github. страницы, если вы обнаружите какую-либо проблему, которую не смогли решить самостоятельно, чтобы мы могли попытаться воспроизвести проблему, чтобы выяснить, что мы можем с ней сделать. знак равно

person eduardomozart    schedule 29.12.2017