包括 MSMQ 作为我的应用程序的先决条件

Posted

技术标签:

【中文标题】包括 MSMQ 作为我的应用程序的先决条件【英文标题】:Including MSMQ as a prerequisite for my application 【发布时间】:2010-10-15 12:20:14 【问题描述】:

我正在开发一个使用 MSMQ 进行进程间通信的应用程序,如果尚未安装该服务,我需要安装项目才能安装该服务。我已经检查了有关使其成为先决条件的信息,但到目前为止,我一直没有成功找到它。有什么想法吗?

【问题讨论】:

【参考方案1】:

我自己发现了答案...Windows 组件安装程序不会因为在任何给定时间无法安装多个 MSI 的典型情况而瘫痪,因此我可以使用自定义安装程序操作来执行命令行安装 MSMQ 的脚本。

这是我的安装程序类(您的选择可能会明显不同):

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();
                
            
        
    

【讨论】:

那是一个破解者。谢谢分享。 安装方法怎么调用?我已经添加了参考system.configuration.Install InitializeComponent 方法是基础中的方法吗?如何使用这个类来安装 msmq? @Adam:你有没有为这个安装程序类使用一个单独的类库?使用您的代码时出现错误“找不到 InitializeComponent”。 @Abhishek:这是一个部分类;如果您将Installer 添加到现有项目,它应该创建必要的基础架构。这里的代码是为了演示怎么写,不一定提供交钥匙解决方案。 我没有注意到 partial 关键字。知道了!谢谢。【参考方案2】:

pkgmgr 命令呢?

pkgmgr /iu:MSMQ-Container;MSMQ-Server

【讨论】:

这似乎与我的回答中的ocsetup.exe 做同样的事情。 但 ocsetup 在 Windows 8.1 中默认不存在【参考方案3】:

谢谢你!!这是任何有兴趣的人的 VB.Net 版本。

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

【讨论】:

以上是关于包括 MSMQ 作为我的应用程序的先决条件的主要内容,如果未能解决你的问题,请参考以下文章

如何在C#中使用MSMQ

我们如何加快从 MSMQ 接收消息的速度?

写入远程 MSMQ

MSMQ消息队列的安装启用

通过 MSMQ 发送文件

C# MSMQ 无效操作异常