長い時間がかかりましたが、ついにこれを行うエレガントな方法を見つけました。
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 をインストールするセットアップ ファイルが作成されます。