Как правильно реализовать мой установщик - PullRequest
1 голос
/ 27 марта 2012

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

  • ProductCode: {9835AE3C-1CED-4FC6-85E1-D2DC8093E9F4}
  • ProductName: Foo
  • UpgradeCode: {02FD8E1A-A552-47AE-BDAA-F165702DE8DC}
  • Версия: 1.2.002

Когда я меняю свой Version -атрибут, генерируется новый ProductCode(насколько я понял, группировка по продукту осуществляется через UpgradeCode, а конкретная версия привязана к ProductCode).

Мои пользовательские действия выглядят так:

enter image description here

Оооо ... вот мой класс установщика:

[RunInstaller(true)]
// my .cs-file
public partial class Installer : System.Configuration.Install.Installer
{
    public Installer()
    {
        this.InitializeComponent();
    }

    protected override void OnAfterInstall(System.Collections.IDictionary savedState)
    {
        base.OnAfterInstall(savedState);

        using (var serviceController = new ServiceController(Settings.Service.Name))
        {
            serviceController.Start();
            serviceController.WaitForStatus(ServiceControllerStatus.Running);
        }
    }

    protected override void OnBeforeUninstall(System.Collections.IDictionary savedState)
    {
        base.OnBeforeUninstall(savedState);

        using (var serviceController = new ServiceController(Settings.Service.Name))
        {
            serviceController.Stop();
            serviceController.WaitForStatus(ServiceControllerStatus.Stopped);
        }
    }
}


// my designer
partial class Installer
{
    private ServiceInstaller ServiceInstaller;
    private ServiceProcessInstaller ServiceProcessInstaller;

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary> 
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Component Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.ServiceProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
        this.ServiceInstaller = new System.ServiceProcess.ServiceInstaller();
        // 
        // ServiceProcessInstaller
        // 
        this.ServiceProcessInstaller.Account = System.ServiceProcess.ServiceAccount.LocalService;
        this.ServiceProcessInstaller.Password = null;
        this.ServiceProcessInstaller.Username = null;
        // 
        // ServiceInstaller
        // 
        this.ServiceInstaller.ServiceName = "Foo";
        this.ServiceInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic;

    }

    #endregion
}

При первоначальной установке проблем нет - все работает нормально (установка, автоматический запуск, ...).Но когда я пытаюсь установить новый MSI-пакет с тем же UpgradeCode, но другим ProductCode, программа установки завершается с ошибкой «Ошибка 1001: указанная служба уже существует», что заставляет меня поверить, что любой обработчик удаления (или вызов) не вызывается и что магия UpgradeCode / Productcode не работает ...
Итак, мой вопрос: где находится путь (переопределение), который обрабатывает (или должен обрабатывать) удаление?Какова будет правильная реализация?

edit:
Установка HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Installer:Logging is iwemv - output @ pastebin (на самом деле у меня разные коды вмой сценарий, как в моем вопросе здесь).
, как мы видим в строке 161ff, найдена предыдущая версия:

MSI (c) (50:04) [10:03:31:319]: Doing action: AppSearch
Aktion gestartet um 10:03:31: AppSearch.
MSI (c) (50:04) [10:03:31:319]: Note: 1: 2262 2: AppSearch 3: -2147287038 
Aktion beendet um 10:03:31: AppSearch. Rückgabewert 1.
MSI (c) (50:04) [10:03:31:319]: Doing action: FindRelatedProducts
Aktion gestartet um 10:03:31: FindRelatedProducts.
MSI (c) (50:04) [10:03:31:319]: PROPERTY CHANGE: Adding PREVIOUSVERSIONSINSTALLED property. Its value is '{C4C4318A-2F89-416B-A48C-76BD035EB52B}'.
Aktion beendet um 10:03:31: FindRelatedProducts. Rückgabewert 1.

вызов строки 272 @ client

MSI (c) (50:04) [10:03:31:413]: Switching to server: TARGETDIR="C:\Program Files (x86)\MyCompany\Foobar\" ALLUSERS="1" PREVIOUSVERSIONSINSTALLED="{C4C4318A-2F89-416B-A48C-76BD035EB52B}" VSDNETURLMSG="Dieses Setup erfordert die Version 4.0 von .NET Framework. Installieren Sie .NET Framework, und führen Sie Setup erneut aus. .NET Framework kann über das Internet bezogen werden. Möchten Sie es jetzt beziehen?" VSDNETMSG="Dieses Setup erfordert die Version 4.0 von .NET Framework. Installieren Sie .NET Framework, und führen Sie Setup erneut aus." CURRENTDIRECTORY="D:\Foo\Release" CLIENTUILEVEL="0" CLIENTPROCESSID="5200" USERNAME="MyCompany Support" COMPANYNAME="MyCompany GmbH" SOURCEDIR="D:\Foo\Release\" ACTION="INSTALL" EXECUTEACTION="INSTALL" ROOTDRIVE="D:\" INSTALLLEVEL="1" SECONDSEQUENCE="1"  ADDLOCAL=DefaultFeature  

строка 313invocation @ server

MSI (s) (A4:6C) [10:03:41:219]: Command Line: TARGETDIR=C:\Program Files (x86)\MyCompany\Foobar\ ALLUSERS=1 PREVIOUSVERSIONSINSTALLED={C4C4318A-2F89-416B-A48C-76BD035EB52B} VSDNETURLMSG=Dieses Setup erfordert die Version 4.0 von .NET Framework. Installieren Sie .NET Framework, und führen Sie Setup erneut aus. .NET Framework kann über das Internet bezogen werden. Möchten Sie es jetzt beziehen? VSDNETMSG=Dieses Setup erfordert die Version 4.0 von .NET Framework. Installieren Sie .NET Framework, und führen Sie Setup erneut aus. CURRENTDIRECTORY=D:\Foo\Release CLIENTUILEVEL=0 CLIENTPROCESSID=5200 USERNAME=MyCompany Support COMPANYNAME=MyCompany GmbH SOURCEDIR=D:\Foo\Release\ ACTION=INSTALL EXECUTEACTION=INSTALL ROOTDRIVE=D:\ INSTALLLEVEL=1 SECONDSEQUENCE=1 ADDLOCAL=DefaultFeature ACTION=INSTALL 

sooo ... действие устанавливается, а не обновляется / удаляется /...?!

1 Ответ

1 голос
/ 27 марта 2012

Поскольку вы спросили «правильно», вы должны знать, что пользовательские действия InstallUtil являются ужасным антипаттерном, и вы заново изобретаете колесо, записывая код для вещей, которые MSI уже поддерживает изначально. Вы также должны знать, что проекты по развертыванию Visual Studio ужасны во многих отношениях (в данном случае без предоставления возможности установки и управления службами MSI), что они будут удалены в следующем выпуске VS11.

Некоторый фон: (Ваш пример a и c)

Zataoca: Пользовательские действия (как правило) - это признание ошибки.

Теперь я советую вам избавиться от настраиваемого действия и использовать вместо этого модуль слияния WiX. Идея состоит в том, чтобы включить компонент, содержащий EXE-файл службы, в модуль слияния, а затем VDPROJ потребляет модуль слияния. (Извлеките класс из консольного приложения и переместите его в библиотеку, а затем используйте ILDASM, чтобы объединить библиотеку с консольным приложением, если хотите). Используйте Windows Installer XML для создания модуля слияния, потому что 1) он фактически предоставляет таблицы ServiceInstall и ServiceControl и 2) это FOSS.

Дополнение InstallShield с помощью установщика Windows XML - Службы Windows

Ваш полученный MSI будет намного проще / чище, и ваши 1001 сообщения об ошибках волшебным образом исчезнут, потому что MSI делает всю работу за вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...