【问题标题】:Writing to a remote MSMQ写入远程 MSMQ
【发布时间】:2025-11-22 20:15:02
【问题描述】:

好的,这是一个非常简单和基本的问题。 如果我在 Windows 机器 A 上有一个应用程序想要写入 Windows 机器 B 上的队列,我是否需要在机器 A 上安装 MSMQ(即使那里没有队列)?我刚刚开始在我的应用程序中使用队列,并试图弄清楚一些基本原理。

谢谢

【问题讨论】:

    标签: .net windows msmq


    【解决方案1】:

    是的,您需要在本地安装 MSMQ 才能写入远程队列。如果您正在写入私有队列,请查看this page,其中包含有关如何格式化队列名称的有用信息。如果您正在写入远程事务队列,那么您需要确保正确指定(第 5 点)

    这是文章正文:

    1。使用远程队列时,machinename\private$\queuename 格式的队列名称不起作用。这导致一个 “无效的队列路径”错误。

    2。必须将队列名称称为FormatName:Direct=OS:machinename\\private$\\queuename

    这是必要的,因为队列访问是在内部使用格式完成的 仅限名称语法。另一个友好的表示被转换为 FormatName 然后使用。使用远程队列时,除非 有AD解析队列名称,友好名称不会 工作。详情请查看文档。

    例如。

    MessageQueue rmQ = new MessageQueue 
                  ("FormatName:Direct=OS:machinename\\private$\\queue");
    rmQ.Send("sent to regular queue - Atul");
    

    3。更进一步,请注意 FormatName 区分大小写。如果您提到前面的字符串 FORMATNAME:Direct=OS:machinename\\private$\\queuename,不会的 工作。令人惊讶的是,在这种情况下没有抛出错误。 字符串的“FormatName”部分似乎是唯一区分大小写的 部分。其他的可以出现在不同的情况下。例如。你可以写 “直接的”。

    4。如果您想使用机器的 IP 地址,语法将是 FormatName:Direct=TCP:ipaddress\\private$\\queuename

    例如。

    MessageQueue rmQ = new MessageQueue
                  ("FormatName:Direct=TCP:121.0.0.1\\private$\\queue");
    rmQ.Send("sent to regular queue - Atul");
    

    5。您在代码中创建的队列实例的事务属性应与您尝试发送的队列的事务属性相匹配 消息给。所以在前面的例子中,我向一个 非事务队列。要发送到事务队列,代码 会是

    MessageQueue rmTxnQ = new MessageQueue
                ("FormatName:Direct=OS:machinename\\private$\\queue");
    rmTxnQ.Send("sent to Txn queue - Atul", MessageQueueTransactionType.Single);
    

    如果事务属性不匹配,则消息不会 发表。令人惊讶的部分是,我没有收到任何错误,并且 消息消失了

    6。最后,当您向远程队列发送消息时,会在您自己的机器上创建一个临时的传出队列。这用于以防万一 远程队列不可用。如果你去电脑管理 控制台(compmgmt.msc),并展开服务和应用程序/ 消息队列/传出队列,您会看到这些队列。这 控制台右侧应显示包括状态在内的详细信息 (连接与否)和下一跳的 IP 地址。

    【讨论】:

    • 是的,我就是这么想的。我只是想听听别人说的。我正在使用私有队列(格式部分已经完成)。格兰芬多得一分!
    • 根据上述设置(权限和 MSMQ 安装)进行更改后: queue.send() :工作正常。但是 queue.receive() 或 queue.getMessageEnumerator2() 都不起作用。你能帮我吗??我正在我的本地机器上测试这个(安装的 MSMQ 组件)。
    • @watraplion 你应该问一个新问题。
    • 顺便提一下,对于远程队列,必须提供实际的机器名称。 DNS 别名不起作用。
    【解决方案2】:

    所有 MSMQ 通信都需要在每一端都有一个 MSMQ 队列管理器。 使用 MSMQ 的应用程序与为它们工作的本地队列管理器进行通信。 使用 MSMQ 的应用程序无法直接与任何本地或远程队列通信。

    【讨论】:

      【解决方案3】:

      另一个(而不是在运行客户端的本地计算机上安装 MSMQ)是实现 WCF 服务,该服务从 MSMQ 队列中获取消息。在这种情况下,您的远程客户端只需指定远程服务端点即可直接写入远程队列。您还必须注意远程队列的安全设置是否正确。

      我认为这将是实现基于队列的通信的更好方式。这是一个简短的答案,但如果您有兴趣,我会很乐意扩展(我注意到您对另一个答案非常满意:)

      【讨论】:

      • 不,我只是想澄清一下。您提议的 WCF 服务没有使用 MSMQ 集成,是吗?它只是碰巧消费了 MSMQ 消息。
      • 嗨,WCF 服务在远程服务器上运行并使用传入的消息。客户端 - 通过代理 - 使用服务合同(通过 http 和 net.msmq)并写入服务所在的队列可以捡起来。另一种方法是使用写入队列并仅使用 http 的 vanilla 服务。那么你就不需要客户端机器上的 msmq。
      【解决方案4】:

      以下格式对我们有用

      key="PublicQueueName" value="FormatName:Direct=TCP:192.168.12.58\private$\myqueue"
      

      您还需要授予远程队列访问权限

      安全性:允许匿名登录

      【讨论】: