Including MSMQ as a prerequisite for my application
Asked Answered
G

3

21

I'm working on an application that uses MSMQ for interprocess communication, and I need the setup project to be able to install the service if it isn't already. I've checked around for information on making it a prerequisite, but so far I've been unsuccessful at finding this. Any ideas?

Gangplank answered 25/3, 2009 at 17:3 Comment(0)
G
26

Discovered the answer on my own...the windows component installer is not crippled by the typical inability to install more than one MSI at any given time, so I'm able to use a custom installer action to execute a command line script to install MSMQ.

Here's my Installer class (your options may obviously vary):

public partial class MSMQInstaller : Installer
{
    public MSMQInstaller()
    {
        InitializeComponent();
    }

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

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

    public override void Install(IDictionary stateSaver)
    {
        base.Install(stateSaver);

        bool loaded;

        try
        {
            IntPtr handle = LoadLibrary("Mqrt.dll");

            if (handle == IntPtr.Zero || handle.ToInt32() == 0)
            {
                loaded = false;
            }
            else
            {
                loaded = true;

                FreeLibrary(handle);
            }
        }
        catch
        {
            loaded = false;
        }

        if (!loaded)
        {
            if (Environment.OSVersion.Version.Major < 6) // Windows XP or earlier
            {
                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 (System.Diagnostics.Process p = new System.Diagnostics.Process())
                {
                    System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo("sysocmgr.exe", "/i:sysoc.inf /u:\"" + fileName + "\"");

                    p.StartInfo = start;

                    p.Start();
                    p.WaitForExit();
                }
            }
            else // Vista or later
            {
                using (System.Diagnostics.Process p = new System.Diagnostics.Process())
                {
                    System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo("ocsetup.exe", "MSMQ-Container;MSMQ-Server /passive");

                    p.StartInfo = start;

                    p.Start();
                    p.WaitForExit();
                }
            }
        }
    }
}
Gangplank answered 26/3, 2009 at 4:20 Comment(4)
How do you call the install method? I already added the reference system.configuration.Install The InitializeComponent method is a method in the base? how can I use this class to install msmq?Clypeate
@Adam: Have you taken a separate class library for this installer class? I get error "Cannot find InitializeComponent" when I use your code.Feria
@Abhishek: This is a partial class; if you add an Installer to an existing project, it should create the necessary infrastructure. The code here is to demonstrate how to write one, not necessarily to provide a turnkey solution.Gangplank
I didn't notice the partial keyword. Got it! Thanks.Feria
S
5

What about the pkgmgr command?

pkgmgr /iu:MSMQ-Container;MSMQ-Server

Smetana answered 8/2, 2010 at 14:48 Comment(2)
That seems to be doing the same thing as ocsetup.exe in my answer.Gangplank
But ocsetup in not present by default at Windows 8.1Assess
B
3

Thank You!! Here's the VB.Net version for anyone who is interested.

Option Explicit On
Option Strict On

Imports System.Diagnostics.Process
Imports System.IO
Imports System.Text
'Required in all cases when calling API functions
Imports System.Runtime.InteropServices
Imports System.Configuration.Install.Installer

<System.ComponentModel.RunInstallerAttribute(True)> _
Public Class msmqInstaller
    Inherits System.Configuration.Install.Installer

    Private Declare Function LoadLibrary Lib "kernel32" (ByVal lpFileName As String) As IntPtr`enter code here`
    <DllImport("KERNEL32.DLL", EntryPoint:="FreeLibrary", SetLastError:=True)> _
     Public Shared Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
        ' Leave function empty - DLLImport attribute 
        ' forces calls to LoadLibrary to
        ' be forwarded to LoadLibrary in KERNEL32.DLL
    End Function

    Public Const MAX_PATH As Integer = 256
    ' Dim testKernel As loadlibrary
    Dim p As New Process
    '  Dim startInfo As New ProcessStartInfo("sysocmgr.exe", "/i:sysoc.inf /u:\"" + fileName + " \ "")
    Dim fileName As String = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "MSMQAnswer.ans")
    Dim writer As New StreamWriter(fileName)

    ' Override the 'Install' method of the Installer class. When overridden in a derived class, performs the installation.
    'You must override the Install and Uninstall methods to add the code to perform your custom installation steps.
    Public Overrides Sub Install(ByVal mySavedState As IDictionary)
        MyBase.Install(mySavedState)
        Dim loaded As Boolean = False
        Dim fileName As String
        Dim writer As StreamWriter
        Dim p As Process

        Try
            Dim handle As IntPtr = LoadLibrary("Mqrt.dll")
            If handle = IntPtr.Zero Or handle.ToInt32 = 0 Then
                loaded = False
            Else
                loaded = True
                FreeLibrary(handle)
            End If
        Catch ex As Exception
            loaded = False
        End Try

        If Not loaded = True Then
            If Environment.OSVersion.Version.Major < 6 Then ' windows xp or earlier
                fileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "MSMQAnswer.ans")
                writer = New System.IO.StreamWriter(fileName)
                Using writer
                    writer.WriteLine("[Version]")
                    '  writer.WriteLine("Signature = \"$Windows NT$\"")
                    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")
                End Using
                p = New System.Diagnostics.Process()
                Using p
                    Dim startInfo As New ProcessStartInfo("sysocmgr.exe", "/i:sysoc.inf /u:\" + fileName + " \ ")
                    p.StartInfo = startInfo
                    p.Start()
                    p.WaitForExit()
                End Using
            Else 'windows vista or later, server 03 
                p = New System.Diagnostics.Process
                Using p
                    Dim startInfo As New ProcessStartInfo("ocsetup.exe", "MSMQ-Container;MSMQ-Server /passive")
                    p.StartInfo = startInfo
                    p.Start()
                    p.WaitForExit()
                End Using
            End If
        End If



    End Sub

End Class
Barbaresi answered 21/10, 2009 at 19:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.