我正在尝试创建一个自动更新已安装组件的安装程序。 因此,我创建了一个安装程序项目,其中包含以下设置:
当我更改Version
- 属性时,会生成一个新的ProductCode
(我的理解方式,产品的分组是通过UpgradeCode
完成的,特定版本绑定到{ {1}})。
我的自定义动作如下所示:
Sooo ...这里有我的安装程序类:
ProductCode
初始安装不是问题 - 一切正常(安装,自动启动......)。但是当我尝试安装具有相同[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
}
但不同UpgradeCode
的新.msi-package时,安装程序失败并显示“错误1001:指定的服务已存在” - 这让我相信,任何卸载处理程序(或调用)未被调用,而ProductCode
/ UpgradeCode
- 魔法不起作用...
所以,我的问题是:处理(或应该处理)卸载的路径(覆盖)在哪里?什么是正确的实施?
修改
Productcode
的设置为HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Installer:Logging
- output @ pastebin(实际上,我的方案中的代码与我在此处的问题中的代码不同)。
正如我们在161ff行中看到的那样,找到了以前的版本:
iwemv
第272行调用@ client
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.
第313行调用@ server
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
sooo ...操作是安装,而不是更新/卸载/...?!
答案 0 :(得分:1)
由于您“正确”地询问,您应该知道InstallUtil自定义操作是一个可怕的反模式,并且您通过将代码写入MSI已经支持的内容来重新发明轮子。您还应该知道Visual Studio部署项目在很多方面都很糟糕(在这种情况下,不会暴露MSI安装和控制服务的能力),它们将在下一版VS11中被删除。
一些背景:(你的是a和c的一个例子)
Zataoca: Custom actions are (generally) an admission of failure.
现在我的建议是摆脱自定义操作并使用WiX合并模块。这个概念是将具有服务EXE的组件分解为合并模块,然后让VDPROJ使用合并模块。 (从控制台应用程序中取出一个类并将其移动到库中,然后使用ILDASM将库合并回控制台应用程序(如果愿意))。使用Windows Installer XML创建合并模块,因为1)它实际公开了ServiceInstall和ServiceControl表,2)它是FOSS。
Augmenting InstallShield using Windows Installer XML - Windows Services
由此产生的MSI将更加简单/清洁,您的1001错误消息将会神奇地消失,因为MSI正在为您完成工作。