Установщик MSI не может найти InstallState при использовании пользовательских действий с параметрами

Прежде всего, да, я знаю, что проекты VS Setup являются злыми. Это то, с чем мне нужно работать. Я также видел несколько связанных вопросов, но они либо остаются без ответа, либо не соответствуют моей ситуации достаточно близко для ответа на работу (или они рассказывают о зле VS Setup Projects и чудеса WiX).

У меня есть проект установки для моего приложения. Он отлично работал для копирования файлов, но после копирования файлов мне нужно было выполнить два пользовательских действия. Я создал класс установщика и настроил его как настраиваемое действие в проекте установки, а его скелет (который не работал, просто показал диалог, чтобы я мог приложить отладчик и осмотреться) работал отлично. Затем я обнаружил, что мне нужно передать параметры из MSI в мое пользовательское действие, чтобы я мог получить к ним доступ через свойство Context класса установщика.

Здесь текущий код класса установщика (некоторые имена были изменены для защиты невинных). Он в основном ничего не делает, кроме как показывать диалог в нужное время (после копирования файлов, но до того, как установка будет выполнена):

namespace MyApp.Install.CustomSetup
{
    [RunInstaller(true)]
    public partial class MyAppCustomInstallActions : System.Configuration.Install.Installer
    {
        public MyAppCustomInstallActions()
        {
            InitializeComponent();
        }

        protected override void OnAfterInstall(IDictionary savedState)
        {
            try
            {
                base.OnAfterInstall(savedState);
                if (MessageBox.Show(
                    "Custom Action OnAfterInstall successfully integrated. You can attach a debugger if desired. Do you wish to perform the custom actions?",
                    "DEBUG", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) return;

                SetEditablePermissionOnFolder(savedState);
                SetApplicationSettingsFromWizard(savedState);
            }
            catch (Exception ex)
            {
                Context.LogMessage(ex.ToString());
                throw;
            }
        }

        private void SetApplicationSettingsFromWizard(IDictionary savedState)
        { 
            //TODO: Implement
        }

        private void SetEditablePermissionOnViewerFolder(IDictionary savedState)
        {
            //TODO: Implement
        }
    }
}

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

Вот строка для CustomActionData для действия установки пользовательских действий проекта установки:

/phonenumber=[phonenumber] /thirdpartyinstallpath1="[thirdpartyinstallpath1]\" /thirdpartyinstallpath2="[thirdpartyinstallpath2]\" /thirdpartyinstallpath3="[thirdpartyinstallpath3]\"

Если я не использую эту строку параметров, это нормально, но у меня нет параметров. Если я укажу эту строку, программа установки завершит работу до появления моего собственного диалогового окна с двумя ошибками: "Exception occurred while initializing the installation: Could not load file or assembly 'file:///C:\Windows\SysWOW64\Files' or one of its dependencies. The system cannot find the file specified" и "Error 1001. Could not find file C:\Program Files (x86)\MyCompany\MyApp\MyApp.Install.CustomSetup.InstallState".

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

EDIT: Я обнаружил, что удаление всего, кроме параметра номера телефона, и установка [PHONENUMBER] в кавычках позволяет передать этот параметр. Однако я не могу пройти ни один из путей к каталогам; Я попытался с помощью [INSTALLDIR] точно, как несколько блогов и пошаговых инструкций говорят, чтобы сделать это, без кубиков.

Ответы

Ответ 1

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

Ответ 2

У меня была аналогичная проблема, и я решил ее:

В свойствах вашего настраиваемого действия установите InstallerClass на false.

Ответ 4

Одна вещь, о которой я должен был убедиться, заключается в том, что мои пути были сбежаны должным образом; либо сделайте это с помощью

@"My Documents\Blah"

или

"My\ Documents\\Blah"

Ответ 5

В моем случае это произошло потому, что я ошибочно добавил пользовательское действие к откату node вместо установки node. Простая ошибка.

Ответ 6

Проблема заключается в том, что одна обратная косая черта перед завершающей цитатой будет интерпретироваться как цитата, принадлежащая String, и не завершает строку. В строке CustomactionActionData​​p >

/thirdpartyinstallpath1="[thirdpartyinstallpath1]\" /thirdpartyinstallpath2="[thirdpartyinstallpath2]\"

подстановки установщика [thirdpartyinstallpath1] и [thirdpartyinstallpath2] с помощью пользовательского ввода, а затем попытается интерпретировать строку CustomactionActionData. Если пользователь вводит для "thirdpartyinstallpath1" значение "C:\Test", указанная выше строка CustomactionActionData может быть в порядке, но если пользователь вводит "C:\Test", установка завершится с ошибкой

"Исключение произошло при инициализации установки: не удалось загрузить файл или файл сборки:///C:\Windows\SysWOW64\Files... 'или один его зависимостей..."

С строкой CustomactionActionData, например

/thirdpartyinstallpath1="[thirdpartyinstallpath1]" /thirdpartyinstallpath2="[thirdpartyinstallpath2]"

Установку не удастся, если пользовательский ввод "C:\Test". Это будет нормально, если пользовательский ввод "C:\Test". Но вы никогда не знаете, что сделает пользователь.

Мой обходной путь - это пробел перед завершающей строкой:

/thirdpartyinstallpath1="[thirdpartyinstallpath1] " /thirdpartyinstallpath2="[thirdpartyinstallpath2] "

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