Установщик 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.
Ответ 3
Если кто-нибудь получит эту ошибку после обновления с VS2008 до VS2010, то проверьте этот поток:
http://social.msdn.microsoft.com/Forums/en-US/winformssetup/thread/829d5c90-9a0d-4258-9d4d-1341cc50f95b/
Это решило проблему для меня:
Измените "BackwardCompatibleIDGeneration" на true при настройке свойств проекта.
Ответ 4
Одна вещь, о которой я должен был убедиться, заключается в том, что мои пути были сбежаны должным образом; либо сделайте это с помощью
@"My Documents\Blah"
или
"My\ Documents\\Blah"
Ответ 5
В моем случае это произошло потому, что я ошибочно добавил пользовательское действие к откату node вместо установки node. Простая ошибка.
Ответ 6
Проблема заключается в том, что одна обратная косая черта перед завершающей цитатой будет интерпретироваться как цитата, принадлежащая String, и не завершает строку.
В строке CustomactionActionDatap >
/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