Установщик Visual Studio> Как запустить приложение в конце установщика
Это, вероятно, глупый вопрос, и мой Google не работает сегодня.
У меня есть приложение, в которое я добавил установщик Visual Studio> проект мастера установки. Мне интересно, как добавить кнопку или флажок, который будет запускать приложение после успешной установки. Это будет находиться на последней странице пакета установщика MSI. Я использую Visual Studio 2010 Ultimate.
Мне это нужно, чтобы, когда приложение выполняет автоматическое обновление, оно автоматически запускало установщик. Мне просто нужен установщик, чтобы перезапустить приложение после обновления.
Это, наверное, очень просто, но я не могу этого понять. Заранее спасибо за вашу помощь.
8 ответов
Чтобы запустить любое приложение после завершения установки,
- Щелкните правой кнопкой мыши по вашему проекту установки, выберите "Пользовательские действия".
- Затем щелкните правой кнопкой мыши на Commit, Add Custom Action и выберите файл, который вы хотите запустить. (Обратите внимание, что он уже должен находиться в папке вашего приложения, что не должно быть проблемой в вашем случае, так как вы все равно запускаете свою программу.
- Просто выберите выход вашего проекта.
- Затем нажмите на этот добавленный.exe и измените InstallerClass на false. Это очень важно, потому что в противном случае он будет искать программу установки.
- Вы даже можете передать параметры в ваш.exe, добавив их в свойство Arguments
Добавлено решение https://blogs.msdn.microsoft.com/astebner/2006/08/12/mailbag-how-can-i-customize-an-msi-in-the-visual-studio-setupdeployment-project/ флажок в конце настройки, чтобы выбрать, хотите ли вы запустить приложение или нет. Вы можете изменить скрипт для проверки по умолчанию... или даже скрыть его.
Большим преимуществом здесь является то, что приложение не будет работать с повышенными правами, как упоминал Морис Фланаган.
Необходимый скрипт вам нужен:
// EnableLaaunchApplication.js <msi-file>
// Performs a post-build fixup of an msi to launch a specific file when the install has completed
// Configurable values
var checkboxChecked = true; // Is the checkbox on the finished dialog checked by default?
var checkboxText = "Launch [ProductName]"; // Text for the checkbox on the finished dialog
var filename = "WindowsApplication1.exe"; // The name of the executable to launch - change this to match the file you want to launch at the end of your setup
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1
var msiViewModifyUpdate = 2
var msiViewModifyAssign = 3
var msiViewModifyReplace = 4
var msiViewModifyDelete = 6
if (WScript.Arguments.Length != 1)
{
WScript.StdErr.WriteLine(WScript.ScriptName + " file");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql
var view
var record
try
{
var fileId = FindFileIdentifier(database, filename);
if (!fileId)
throw "Unable to find '" + filename + "' in File table";
WScript.Echo("Updating the Control table...");
// Modify the Control_Next of BannerBmp control to point to the new CheckBox
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BannerBmp'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.StringData(11) = "CheckboxLaunch";
view.Modify(msiViewModifyReplace, record);
view.Close();
// Resize the BodyText and BodyTextRemove controls to be reasonable
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BodyTextRemove'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(7) = 33;
view.Modify(msiViewModifyReplace, record);
view.Close();
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BodyText'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(7) = 33;
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the new CheckBox control
sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '18', '117', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'CloseButton', '|')";
view = database.OpenView(sql);
view.Execute();
view.Close();
WScript.Echo("Updating the ControlEvent table...");
// Modify the Order of the EndDialog event of the FinishedForm to 1
sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(6) = 1;
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the Event to launch the application
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch', 'LAUNCHAPP=1', '0')";
view = database.OpenView(sql);
view.Execute();
view.Close();
WScript.Echo("Updating the CustomAction table...");
// Insert the custom action to launch the application when finished
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch', '210', '" + fileId + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();
if (checkboxChecked)
{
WScript.Echo("Updating the Property table...");
// Set the default value of the CheckBox
sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('LAUNCHAPP', '1')";
view = database.OpenView(sql);
view.Execute();
view.Close();
}
database.Commit();
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
function FindFileIdentifier(database, fileName)
{
var sql
var view
var record
// First, try to find the exact file name
sql = "SELECT `File` FROM `File` WHERE `FileName`='" + fileName + "'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
if (record)
{
var value = record.StringData(1);
view.Close();
return value;
}
view.Close();
// The file may be in SFN|LFN format. Look for a filename in this case next
sql = "SELECT `File`, `FileName` FROM `File`";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
while (record)
{
if (StringEndsWith(record.StringData(2), "|" + fileName))
{
var value = record.StringData(1);
view.Close();
return value;
}
record = view.Fetch();
}
view.Close();
}
function StringEndsWith(str, value)
{
if (str.length < value.length)
return false;
return (str.indexOf(value, str.length - value.length) != -1);
}
Отредактируйте файл, чтобы показать желаемое имя и имя исполняемого файла, поместите этот файл рядом с вашим проектом установки.vdproj и в postbuild добавьте следующую строку:
CALL cscript.exe "$ (ProjectDir) EnableLaunchApplication.js" "$ (BuiltOuputPath)"
В Visual Studio 2010 здесь легко...
Шаг 1: Добавьте новый класс установщика в проект приложения, который вы хотите запустить после установки, назовите его как хотите.
Шаг 2: Добавьте следующий код в класс установщика, который вы только что добавили, перепечатывая MyApplication.exe с именем вашего.
Public Overrides Sub Commit(ByVal savedState As System.Collections.IDictionary)
MyBase.Commit(savedState)
System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(Me.Context.Parameters("AssemblyPath")) + "\MyApplication.exe")
End Sub
Скомпилируй и иди...
В моем случае я боролся с этим некоторое время, и решение было только там. Решение, предоставленное с использованием настраиваемого действия непосредственно к первичному выводу приложения, мне не подошло, поскольку приложение установки остается до тех пор, пока вы не покинете основное приложение. Таким образом, проблема может быть решена с использованием следующего подхода:
- Добавьте класс Install в ваш проект;
- В новом классе переопределите метод Commit, как Джаррод говорил выше.
System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(this.Context.Parameters["AssemblyPath"]) + @"\MyApplication.exe")
; - Теперь хитрость: перейдите на панель "Пользовательские действия" в проекте установщика и добавьте основной вывод вашего проекта в папки "Commit" и "Install". Не меняйте ничего в свойствах. Это будет работать именно так. По умолчанию он получит класс установщика, в который вы вставили код, в предыдущем пункте;
- Создайте свой установочный пакет и установите его. Вы должны заметить, что приложение запустится в конце;
- Просто закройте предупреждение об успешной установке и сделайте это.
Чтобы узнать больше об этом и где я получил это, пожалуйста, посетите это.
PS: я сделал это используя VS2017 и Framework 2.0.
Попробуйте проверить этот пост в блоге: http://blogs.msdn.com/b/astebner/archive/2006/08/12/696833.aspx
Я не могу подтвердить, работает ли он на 2010 год или нет; Я все еще не могу использовать 2008, пока мой TFS-сервер не будет обновлен. Также я использую WiX для своих инсталляторов. Но это просто пользовательское действие, поэтому я думаю, что оно все еще должно поддерживаться.
Надеюсь это поможет!
(Кстати, во время практики поиска в Google, чтобы найти это, ваш вопрос появлялся на первой странице Google по этому вопросу.)
сначала сгенерируйте класс установщика. в этом переопределите метод установки. и вставьте следующую команду.
public override void Install(IDictionary stateSaver) {
System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(this.Context.Parameters["AssemblyPath"]) + @"\windowsAgent.exe");
}
Добавление другого ответа, поскольку ни один из предыдущих ответов не затрагивает вопрос о флажке или кнопке в исходном сообщении.
Вы бы добавили один из стандартных диалогов в ваш проект установки, например CheckBoxes(A), щелкнув правой кнопкой мыши кнопку "Пуск" в представлении "Интерфейс пользователя". Щелкните правой кнопкой мыши диалоговое окно после добавления, чтобы переместить его вверх. Вам нужен только один флажок для вопроса о запуске программы, поэтому исключите остальные. Имя свойства по умолчанию - CHECKBOXA1, поэтому добавьте условие к пользовательскому действию, которое запускает ваш код CHECKBOXA1=1, что означает, что оно было проверено.
Скрипт JayTee был лучшим решением. Однако имя файла в первой строке скрипта написано с ошибкой.
Должно быть следующее:// EnableLaunchApplication.js <msi-file>
Чтобы оно работало, необходимо использовать правильное имя, следуя инструкциям по следующей ссылке: настроить msi
Ссылка на образец в приведенной выше ссылке неверна.
Используйте следующий сценарий с инструкциями по ссылке выше.
// EnableLaunchApplication.js <msi-file>
// Performs a post-build fixup of an msi to launch a specific file when the install has completed
// Configurable values
var checkboxChecked = true; // Is the checkbox on the finished dialog checked by default?
var checkboxText = "Launch [ProductName]"; // Text for the checkbox on the finished dialog
var filename = "TranslateFileNamesWin.exe"; // The name of the executable to launch - change this to match the file you want to launch at the end of your setup
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1
var msiViewModifyUpdate = 2
var msiViewModifyAssign = 3
var msiViewModifyReplace = 4
var msiViewModifyDelete = 6
if (WScript.Arguments.Length != 1)
{
WScript.StdErr.WriteLine(WScript.ScriptName + " file");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql
var view
var record
try
{
var fileId = FindFileIdentifier(database, filename);
if (!fileId)
throw "Unable to find '" + filename + "' in File table";
WScript.Echo("Updating the Control table...");
// Modify the Control_Next of BannerBmp control to point to the new CheckBox
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BannerBmp'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.StringData(11) = "CheckboxLaunch";
view.Modify(msiViewModifyReplace, record);
view.Close();
// Resize the BodyText and BodyTextRemove controls to be reasonable
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BodyTextRemove'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(7) = 33;
view.Modify(msiViewModifyReplace, record);
view.Close();
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BodyText'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(7) = 33;
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the new CheckBox control
sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '18', '117', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'Line1', '|')";
view = database.OpenView(sql);
view.Execute();
view.Close();
WScript.Echo("Updating the ControlEvent table...");
// Modify the Order of the EndDialog event of the FinishedForm to 1
sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(6) = 1;
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the Event to launch the application
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch', 'LAUNCHAPP=1', '0')";
view = database.OpenView(sql);
view.Execute();
view.Close();
WScript.Echo("Updating the CustomAction table...");
// Insert the custom action to launch the application when finished
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch', '210', '" + fileId + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();
if (checkboxChecked)
{
WScript.Echo("Updating the Property table...");
// Set the default value of the CheckBox
sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('LAUNCHAPP', '1')";
view = database.OpenView(sql);
view.Execute();
view.Close();
}
database.Commit();
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
function FindFileIdentifier(database, fileName)
{
var sql
var view
var record
// First, try to find the exact file name
sql = "SELECT `File` FROM `File` WHERE `FileName`='" + fileName + "'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
if (record)
{
var value = record.StringData(1);
view.Close();
return value;
}
view.Close();
// The file may be in SFN|LFN format. Look for a filename in this case next
sql = "SELECT `File`, `FileName` FROM `File`";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
while (record)
{
if (StringEndsWith(record.StringData(2), "|" + fileName))
{
var value = record.StringData(1);
view.Close();
return value;
}
record = view.Fetch();
}
view.Close();
}
function StringEndsWith(str, value)
{
if (str.length < value.length)
return false;
return (str.indexOf(value, str.length - value.length) != -1);
}