如何正确实施我的安装程序
Posted
技术标签:
【中文标题】如何正确实施我的安装程序【英文标题】:How do I implement my Installer correctly 【发布时间】:2012-03-27 07:19:30 【问题描述】:我正在尝试创建一个安装程序,它会自动更新已安装的组件。 因此,我创建了一个安装程序项目,具有以下设置:
产品代码:9835AE3C-1CED-4FC6-85E1-D2DC8093E9F4 产品名称:Foo 升级代码:02FD8E1A-A552-47AE-BDAA-F165702DE8DC 版本:1.2.002当我更改我的Version
-attribute 时,会生成一个新的ProductCode
(我的理解是,产品上的分组是通过UpgradeCode
完成的,具体版本绑定到ProductCode
)。
我的自定义操作如下所示:
Sooo ...这里有我的安装程序类:
[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
但不同的 ProductCode
安装新的 .msi-package 时,安装程序会失败并显示“错误 1001:指定的服务已经存在”——这让我相信,任何卸载处理程序 (或调用)没有被调用并且UpgradeCode
/Productcode
-magic 不起作用...
所以,我的问题是:处理(或应该处理)卸载的路径(覆盖)在哪里?正确的实现是什么?
编辑:HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Installer:Logging
的设置是 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 行调用@客户端
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
第 313 行调用@服务器
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 ...操作是安装,而不是更新/卸载/...?!
【问题讨论】:
如果您有相同的升级代码和较新的版本,升级应该触发旧版本的卸载。例如,如果应用程序具有不同的安装类型,即第一个是按用户安装的,而第二个是按机器安装的,或者相反,则操作系统会跳过升级。您应该创建一个详细日志以查看实际发生的情况:support.microsoft.com/kb/223300 @BogdanMitrache 感谢您的提示 - 我已经包含了一个“审查”输出@pastebin (pastebin.com/CnXXgeJT) 【参考方案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 正在为您完成工作。
【讨论】:
非常感谢您的输入...实际上我已经删除了 .vdproj 文件并编写了一个漂亮而纤细的 .wxs 文件。我实现的唯一缺点是我必须列出所有带有文件标签的文件,并且无法获取“项目 X 的输出”。但是 ServiceInstall- 和 ServiceControl-tag 是如此强大的优点...... 如果您在执行此操作时遇到困难,请随时与我联系。第一次做的时候可能会有点困惑。 WiX 支持项目引用。您将 .NET 项目的引用添加到 WiX 项目,然后在 wxs 中为文件名属性输入类似 $(var.ProjectName.TargetPath) 的内容。 顺便说一句,我并不是说您必须将 ALL 文件放入 WxS 模块,而只是将您的服务 exe 文件。但是,如果您选择执行它们ALL,那并不是一个可怕的想法。我在 Codeplex 上有一个名为 IsWiX 的工具,可以帮助您解决这个问题。有关充分利用 VDPROJ 的信息,请参阅 blog.deploymentengineering.com/2011/03/…。 实际的 .wxs-file @ pastebin (pastebin.com/GzR4CXW2) (我真的很喜欢克服 vdproj 并去使用 wix ...)...对于第一次尝试来说还不错。项目参考真的很酷——你的博客也是:)以上是关于如何正确实施我的安装程序的主要内容,如果未能解决你的问题,请参考以下文章