2013-03-04 91 views
2

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

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

+0

一个更简单的方法来做到这一点:https://stackoverflow.com/questions/18126502/wix-enable-windows-feature – donovan 2018-01-31 23:47:50

回答

4

这花了很长时间,但最终我找到了这样做的优雅方式。

1)在Visual Studio中创建一个新的维克斯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)习惯m动作可以配置为在安装过程中的任意一点运行(详细信息请参阅:http://wixtoolset.org/documentation/manual/v3/xsd/wix/installexecutesequence.html)。上述示例在安装.wxs文件中详述的文件之前运行自定义操作。

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

-1

当你的产品依赖于其他第三方先决条件如MSMQ,.NET框架,SQL服务器等,你需要使用一个引导程序的程序来运行安装的链条:首先需要prereqs一个接 - 一个,然后主要产品安装。

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

+0

这只是关于WiX安装程序的一般性响应 - 它并没有真正回答具体问题题。 – 2013-03-06 14:05:34

+0

它指向文档“什么是WiX安装系统组件?”,这是一个通用问题的通用答案。一旦@Rik知道如何建立一系列先决条件安装,我认为他知道命令行要在链接中使用,特别安装MSMQ。 (我不这样做,)。 – 2013-03-07 08:32:08