Как получить установочный каталог? - PullRequest
8 голосов
/ 01 ноября 2008

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

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

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

Ответы [ 6 ]

2 голосов
/ 01 ноября 2008

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

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

0 голосов
/ 29 декабря 2017

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

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

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

MSI Components Registry Key

Я разработал 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 Framework или процессов сборки.

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

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

0 голосов
/ 19 мая 2011

Как указано в другом месте в потоке, я обычно пишу раздел реестра в 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 и устанавливаю жесткую подпись, ища узкий диапазон версий файла с правильной версией и датой.

0 голосов
/ 20 августа 2009

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

0 голосов
/ 01 апреля 2009

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

0 голосов
/ 01 ноября 2008

Я бы попробовал использовать Installer.OpenProduct (productcode). Откроется сеанс, в котором вы можете запросить свойство («TARGETDIR»).

...