我想创建一个基于许多参数创建MSI的C#程序。例如,根据用户设置,将包含某些文件,或设置运行时参数。
有人能指出我可能会有所帮助的任何文件,或者让我知道我可能从哪个开始这样的事情?
答案 0 :(得分:5)
我一直在使用WixSharp(WiX#),原因只是您描述的原因。我发现XML驱动的安装程序太丑陋而且不直观,即编辑XML文件作为构建安装程序的一种方式。我挖掘了基于C#的WiX#作为一种更平易近人的选择。在我的例子中,我需要生成一个MSI来在服务器上安装.NET DLL(不在GAC中),然后将其注册到COM Interop。
Wix#的CodePlex主页上的更多信息:http://wixsharp.codeplex.com/
对于OP描述的安装类型,"功能"的MSI / WiX概念。会看到应用,例如,用户可以选中一个框来安装或省略某些功能(A"功能"可以是一组文件/程序,一组注册表条目等)
在WiX#安装程序中,您在C#安装程序代码的顶部声明了一个"功能"以及#34; ID",例如二进制文件,docs,registryEntries等,然后在声明其他安装程序组件时引用该功能ID。 (参见" AllInOne" Wix#代码在Wix#install附带的" Samples"文件夹中),
Feature binaries = new Feature("MyApp Binaries");
Feature docs = new Feature("MyApp Documentation");
...
new File(binaries, @"AppFiles\MyApp.exe",
new FileShortcut(binaries, "MyApp", @"%ProgramMenu%\My Company\My Product"),
new FileShortcut(binaries, "MyApp", @"%Desktop%")),
注意功能ID"二进制文件"是声明File和FileShortcut组件的第一个参数,即" new File(二进制文件,...),并将这些组件链接到功能ID"二进制文件"。
此外,MSI安装程序允许您在命令行上指定功能ID,例如,
msiexec / i install.msi ADDLOCAL =二进制文件
另见帖子:WIX: How to Select Features From Command Line
虽然WiX有办法查看目标系统并确定要安装的内容,但我还没有看到Wix#示例看似直观,可能除了使用自定义操作(Wix#支持)。使安装程序的行为适应目标系统将使用自定义操作来设置属性,如Wix#sample," Conditional Installation"在Wix#deployment中。
//setting property to be used in install condition
new Property("INSTALLDESKTOPSHORTCUT", "no"),
new ManagedAction(@"MyAction", Return.ignore, When.Before, Step.LaunchConditions, Condition.NOT_Installed, Sequence.InstallUISequence));
之前在Wix#installer中返回此代码的链接:
new Dir(@"%Desktop%",
new ExeFileShortcut("MyApp", "[INSTALLDIR]MyApp.exe", "")
{
Condition = new Condition("INSTALLDESKTOPSHORTCUT=\"yes\"") //property based condition
}),
请注意"条件"在花括号中设置为测试属性" INSTALLDESKTOPSHORTCUT"对于值"是",它被设置为自定义操作的结果。自定义操作的C#代码如下所示。
public class CustomActions
{
[CustomAction]
public static ActionResult MyAction(Session session)
{
if (DialogResult.Yes == MessageBox.Show("Do you want to install desktop shortcut", "Installation", MessageBoxButtons.YesNo))
session["INSTALLDESKTOPSHORTCUT"] = "yes";
return ActionResult.Success;
}
}
对于C#技能组,另一种方法是使用C#程序对msi安装程序进行前端操作,该程序执行以下操作:
可能有其他" neater"这样做的方法,例如,涉及自定义操作等。但是,来自C#技能集,这种方式是平易近人的,可以帮助Windows Installer / WiX学习曲线。我在Wix#安装程序中所做的工作是,它帮助我逐步学习了一些WiX和Windows Installer。我经常在WiX中查找如何执行某个部署任务,然后将Wix方式转换为Wix#,以使Wix#在其生成的.wxs文件中生成所需的XML。
在那些我无法弄清楚如何让Wix#执行某个部署任务的情况下,我经常可以使用简单地在Wix#生成的.wxs文件中包含WiX XML语句的方法,例如,通过手动编辑.wxs文件。
例如,WiX和Wix#,提供特定驱动器和路径的方式不是"支持的#34;目的地不直观。我发现将这个xml片段从Wix#添加到生成的.wxs文件中,然后手动运行Candle然后运行Light,这对我来说很有用。
我记得跑步时遇到了一些如何获取Wix#C#代码以在.wxs语句中以编程方式包含XML,然后编译.wxs以生成msi的示例。如果我再次找到Wix#例子,我会更新这个答案。
更新我确实找到了示例代码...在Wix#附带的Wix#examples文件夹中的Wix#代码示例中有一对。但是......他们没有按照我想要的方式工作,还涉及了我还不熟悉的其他Wix#类和对象。我希望使用"标准"以Wix#输出作为XML文本。 XML C#工具集,而不是Wix#特定类。因此,我尝试解析.wxs文档XML,并且未能成功使用XPath导航到我想要插入其他WiX XML语句的位置。 (也许我会发布一个SO问题来寻求帮助)。但是,我确实通过使用WiX XML的文本替换来实现我想要的,将其视为文本字符串。以下是我成功的工作。
代码的作用是将委托分配给Compiler.WixSourceSaved事件,并且当" Compiler.BuildMsi"" Compiler.BuildMsi"在Wix#代码中调用方法。在读取了创建的.wxs文件之后(但是在从wxs构建MSI文件之前),我更新文件中的文本以包含我想要包含的XML行。
然后,基础Wix#事件序列继续并将修改后的wxs构建到最终的MSI中。
// ...
internal class Script
static string myWIX_SET_DIRECTORY_STATEMENT = " <SetDirectory Id=\"INSTALLDIR\" Value=\"D:\\Program Files\\DOL\\WA.DOL.HQSYS.ExecECL\" />";
static string myWIX_INSERT_AFTER_TEXT = " <InstallExecuteSequence >";
public static void Main()
{
// ... (your other Wix# code goes here...)
// Hook an event to Wix# save of .wxs file to post-process the .wxs
Compiler.WixSourceSaved += PostProcessWxsXMLOutput;
// Trigger the MSI file build
Compiler.BuildMsi(project);
}
/// <summary>
/// Post-process the Wix .wxs file before compiling it into an MSI
/// </summary>
/// <param name="wxsFileName"></param>
private static void PostProcessWxsXMLOutput(string wxsFileName)
{
StreamReader sr = new StreamReader(wxsFileName);
string myWixDocument = sr.ReadToEnd();
sr.Close();
string myProcessedWixDocument = WiXHelpers.InsertFragmentInWiXDocument(myWixDocument, myWIX_INSERT_AFTER_TEXT, myWIX_SET_DIRECTORY_STATEMENT);
StreamWriter sw = new StreamWriter(wxsFileName);
sw.Write(myProcessedWixDocument);
sw.Close();
}
注意:BuildMsi完成后会删除.wxs文件。要强制保存生成的.wxs文件,您需要在Compiler.BuildMsi行之后的Wix#代码中添加一行,如下所示:
Compiler.BuildWxs(Project)
这实际上做的是重新激活WixSourceSaved事件,然后调用我的PostProcessXMLOutput委托,该委托重新生成.wxs文件的新的,内容相同的副本。这次,wxs文件不会自动删除。生成的wxs文件也将具有比构建中的相应MSI文件更晚的时间戳。
答案 1 :(得分:4)
我会查看WiX。它有一个相当陡峭的学习曲线,但它会产生msi作为项目构建周期的一部分。
答案 2 :(得分:3)
查看WixSharp - 一组C#库,允许您用C#代码表示安装。然后将其转换为WiX(XML)文件,然后编译并链接以创建标准MSI(Windows Installer)文件。
答案 3 :(得分:2)
如果您真的想在代码中执行此操作,则需要查看Windows Installer API。但是,Wix构建了一个很好的托管工具集,可以使用XML语言更轻松地创建MSI。他们还在托管包装器中包装了许多Windows Installer API,但为了获得Windows Installer的全部功能,您需要查看API文档。