Скрипт для изменения записей последовательности действий в MSI
Чтобы решить проблему, перечисленную здесь, я должен изменить запись InstallExecuteSequence .RemoveExistingProducts в MSI.
Я хочу сделать это как часть процесса сборки, а не дурачиться с Orca
3 ответа
Изменение сценария MSI_SetProperty.js дает
// MSI_SetActionSequence.js <msi-file> <table> <action> <sequence>
// Performs a post-build fixup of an msi to set the specified table/action/sequence
// Constant values from Windows Installer SDK
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1;
var msiViewModifyUpdate = 2;
var msiViewModifyAssign = 3;
var msiViewModifyReplace = 4;
var msiViewModifyDelete = 6;
if (WScript.Arguments.Length != 4)
{
WScript.StdErr.WriteLine("Usage: " + WScript.ScriptName + " file table action sequence");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var table = WScript.Arguments(1);
var action = WScript.Arguments(2);
var sequence = parseInt(WScript.Arguments(3));
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
WScript.StdOut.WriteLine("Looking for action:" + action);
try
{
var sql = "SELECT Action, Sequence FROM " + table + " WHERE Action = '" + action + "'";
var view = database.OpenView(sql);
view.Execute();
var record = view.Fetch();
if (record)
{
while (record)
{
WScript.StdOut.Write("Found: " + record.StringData(0) + ", " + record.StringData(1) + ", " + record.StringData(2));
if (record.IntegerData(2) != sequence)
{
WScript.StdOut.WriteLine(" - changing to " + sequence);
record.IntegerData(2) = sequence;
view.Modify(msiViewModifyUpdate,record);
}
else
WScript.StdOut.WriteLine(" - OK");
record = view.Fetch();
}
view.Close();
database.Commit();
}
else
{
view.Close();
throw("Warning - Could not find " + table + "." + action);
}
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
Чтобы вызвать этот сценарий для внесения изменений в последовательность действий, упомянутую выше, вы должны поместить следующее в пакетный файл и вызвать его из события после сборки, например, PostBuildEvent = $(ProjectDir)PostBuild.bat
cscript.exe MSI_SetActionSequence.js YOURINSTALLER.MSI InstallExecuteSequence RemoveExistingProducts 1525
Решение, предоставленное Райаном, решает часть проблемы, с которой я сталкиваюсь. Он выполняет полное удаление с последующей установкой.
Однако у меня есть другая проблема, в моем случае некоторые программы работают в фоновом режиме. Перед запуском установщика установщик жалуется, что некоторые файлы используются. И дает стандартное диалоговое окно с просьбой либо закрыть приложение, либо перезапустить для завершения обновления.
Есть ли способ, например. пользовательское действие или параметр, чтобы убить процессы, работающие в фоновом режиме, чтобы установщик прошел гладко?
Некоторые заметки для других там. У меня была проблема "Ошибка 1001. Указанная служба уже существует", и я попробовал описанное выше, но она не работает. Вот с чем я столкнулся:
* Убедитесь, что для свойства RemovePreviousVersions в проекте установки установлено значение True. Это кажется очевидным - очевидным, то есть если вы знаете об этом. По умолчанию установлено значение False. Если False, описанная выше процедура не решит вашу проблему. *
У меня есть несколько сборок, установленных в GAC. Похоже, что когда я переместил последовательность RemoveExistingProducts, эти файлы были удалены из GAC, но не переустановлены. Чтобы решить эту проблему, я установил все сборки в папке приложений. К вашему сведению, я использую VS2010.
Также еще один придира. Если пользователь выбирает "Восстановить" при попытке переустановить ту же версию продукта, он все равно получит ошибку "Указанная служба уже существует". Если у меня будет время, я постараюсь это исправить. Если кто-то еще знает, как это исправить, не могли бы вы опубликовать?
Все, что сказал, спасибо за размещение этого!