Wix:安装MSMQ组件

时间:2013-03-04 10:13:39

标签: windows wix msmq

我有一个.NET项目,它有两个通过MSMQ进行通信的组件。我正在使用Wix构建我的安装程序,因为Microsoft已经莫名其妙地停止了对Visual Studio 2012中安装程序的支持。我对在Wix安装程序中创建MSMQ实例的过程非常满意,我对这个过程非常满意检测是否在计算机上安装了MSMQ(通过尝试加载Mqrt.dll)。

有谁知道如何使用Wix安装MSMQ Windows系统组件本身?有没有办法让Wix指示Windows安装系统组件?

2 个答案:

答案 0 :(得分:4)

花了很长时间,但最后我发现了这种优雅的方式。

1)在Visual Studio中创建一个新的WiX C#自定义操作项目

2)将以下内容粘贴到CustomAction.cs文件中:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;

namespace InstallMsmq
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult CustomAction1(Session session)
        {
            session.Log("Begin CustomAction1");

            return ActionResult.Success;
        }

        [DllImport("kernel32")]
        static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool FreeLibrary(IntPtr hModule);

        [CustomAction]
        public static ActionResult InstallMsmq(Session session)
        {

            ActionResult result = ActionResult.Failure;
            session.Log("Detecting MSMQ");
            bool loaded;
            CreateConfigFile();
            CreateWindows8InstallerScript();

            try
            {
                IntPtr handle = LoadLibrary("Mqrt.dll");
                if (handle == IntPtr.Zero || handle.ToInt32() == 0)
                {
                    loaded = false;
                }
                else
                {
                    loaded = true;
                    session.Log("MSMQ is already installed");
                    result = ActionResult.Success;
                    FreeLibrary(handle);
                }
            }
            catch
            {
                loaded = false;
            }

            if (!loaded)
            {
                session.Log("Installing MSMQ");
                try
                {

                    Version win8version = new Version(6, 2, 9200, 0);

                    if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version >= win8version)//Windows 8 or higher
                    {
                        // its win8 or higher.

                        session.Log("Windows 8 or Server 2012 detected");

                        using (Process p = new Process())
                        {
                            session.Log("Installing MSMQ Server");
                            ProcessStartInfo containerStart = new ProcessStartInfo("MSMQWindows8.bat");
                            containerStart.Verb = "runas";
                            p.StartInfo = containerStart;                            
                            bool success = p.Start();
                            p.WaitForExit();
                        }
                    }
                    else if (Environment.OSVersion.Version.Major < 6) // Windows XP or earlier
                    {
                        session.Log("Windows XP or earlier detected");
                        string fileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "MSMQAnswer.ans");
                        using (System.IO.StreamWriter writer = new System.IO.StreamWriter(fileName))
                        {
                            writer.WriteLine("[Version]");
                            writer.WriteLine("Signature = \"$Windows NT$\"");
                            writer.WriteLine();
                            writer.WriteLine("[Global]");
                            writer.WriteLine("FreshMode = Custom");
                            writer.WriteLine("MaintenanceMode = RemoveAll");
                            writer.WriteLine("UpgradeMode = UpgradeOnly");
                            writer.WriteLine();
                            writer.WriteLine("[Components]");
                            writer.WriteLine("msmq_Core = ON");
                            writer.WriteLine("msmq_LocalStorage = ON");
                        }

                        using (Process p = new Process())
                        {
                            session.Log("Installing MSMQ Container");
                            ProcessStartInfo start = new ProcessStartInfo("sysocmgr.exe", "/i:sysoc.inf /u:\"" + fileName + "\"");
                            p.StartInfo = start;
                            p.Start();
                            p.WaitForExit();
                        }
                    }
                    else if (Environment.OSVersion.Version.Major < 8) // Vista or later
                    {
                        session.Log("Windows Vista or Windows 7 detected");
                        using (Process p = new Process())
                        {
                            session.Log("Installing MSMQ Container");
                            ProcessStartInfo containerStart = new ProcessStartInfo("ocsetup.exe", "MSMQ-Container /unattendFile:MSMQ.xml");
                            containerStart.Verb = "runas";
                            p.StartInfo = containerStart;
                            p.Start();
                            p.WaitForExit();
                        }
                        using (Process p = new Process())
                        {
                            session.Log("Installing MSMQ Server");
                            ProcessStartInfo serverStart = new ProcessStartInfo("ocsetup.exe", "MSMQ-Server /unattendFile:MSMQ.xml");
                            serverStart.Verb = "runas";
                            p.StartInfo = serverStart;
                            p.Start();
                            p.WaitForExit();
                        }
                    }
                    session.Log("Installation of MSMQ Completed succesfully");
                    result = ActionResult.Success;
                }
                catch (Exception ex)
                {
                    session.Log("Installation of MSMQ failed due to " + ex.Message);
                }
            }
            return result;
        }

        private static void CreateWindows8InstallerScript()
        {
            StreamWriter configFile = new StreamWriter("MSMQWindows8.bat");
            configFile.WriteLine("%WINDIR%\\SysNative\\dism.exe /online /enable-feature /all /featurename:MSMQ-Server");
            configFile.Close();
        }
        private static void CreateConfigFile()
        {
            StreamWriter configFile = new StreamWriter("MSMQ.xml");
            configFile.WriteLine("<?xml version=\"1.0\"?>");
            configFile.WriteLine("");
            configFile.WriteLine("<unattend>");
            configFile.WriteLine("");
            configFile.WriteLine("  <servicing>");
            configFile.WriteLine("");
            configFile.WriteLine("    <package action=\"configure\">");
            configFile.WriteLine("");
            configFile.WriteLine("<assemblyIdentity name=\"Microsoft-Windows-Foundation-Package\" version=\"6.0.6000.16386\" language=\"neutral\" processorArchitecture=\"AMD64\" publicKeyToken=\"31bf3856ad364e35\" versionScope=\"nonSxS\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("      <selection name=\"MSMQ-Container\" state=\"true\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("<selection name=\"MSMQ-Server\" state=\"true\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("<selection name=\"MSMQ-Triggers\" state=\"true\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("<selection name=\"MSMQ-DCOMProxy\" state=\"true\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("<selection name=\"MSMQ-Multicast\" state=\"true\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("<selection name=\"MSMQ-ADIntegration\" state=\"true\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("<selection name=\"MSMQ-HTTP\" state=\"true\"/>");
            configFile.WriteLine("");
            configFile.WriteLine("    </package>");
            configFile.WriteLine("");
            configFile.WriteLine("  </servicing>");
            configFile.WriteLine("");
            configFile.WriteLine("</unattend>");
            configFile.Close();
        }
    }
}

3)编译自定义操作

4)将以下内容添加到WiX setup.wxs文件中:

<Binary SourceFile="[path to custom action project]\bin\[Debug or Release]\[custom action project name].CA.dll" Id="[custom action project name]step" />
<CustomAction Id="[custom action project name]CustomAction" BinaryKey="[custom action project name]step" DllEntry="[custom action project name]" Execute="deferred" Impersonate="no"/>
<InstallExecuteSequence>
  <Custom Action="[custom action project name]CustomAction" Before="InstallFiles"/>
</InstallExecuteSequence> 

5)可以将自定义操作配置为在安装过程中的多个点中的任何一个点运行(详细信息如下:http://wixtoolset.org/documentation/manual/v3/xsd/wix/installexecutesequence.html)。上面的示例在安装.wxs文件中详细说明的文件之前运行自定义操作。

6)测试 - 如果一切顺利,你应该有一个安装文件,安装msmq作为安装顺序的一部分!

答案 1 :(得分:-1)

当您的产品依赖于其他第三方先决条件(如MSMQ,.NET Framework,SQL Server等)时,您需要使用引导程序来运行一系列安装:首先需要先决条件一个接一个,然后是主要产品安装。

在WiX中,这些链称为bundles,使用burn引导程序创建/运行。