如何使用 PowerShell 从 MSMQ 消息队列中删除特定消息
Posted
技术标签:
【中文标题】如何使用 PowerShell 从 MSMQ 消息队列中删除特定消息【英文标题】:How to use PowerShell to delete specific messages from an MSMQ message queue 【发布时间】:2016-09-23 16:02:10 【问题描述】:我正在尝试使用 PowerShell 从 MSMQ 消息队列中删除特定消息。我知道 PowerShell 4+ 中引入了几个用于管理 MSMQ 队列和消息的新 cmdlet,但据我所知,这些仍然无法帮助我实现删除特定消息的目标。
我想要实现的是一个连接到指定队列的简单脚本,然后遍历该队列中的每条消息,在消息正文中查找指定的搜索字符串,然后 MOVES 任何匹配的消息到同一服务器上的另一个队列。我可以很好地搜索消息,并且可以使用 Send 方法复制任何匹配项:
$source = new-object System.Messaging.MessageQueue($sourcequeuename)
$destination = new-object System.Messaging.MessageQueue($destinationqueuename)
$msgs = $source.GetAllMessages()
foreach ( $msg in $msgs )
#Extra logic here - check message body for search string etc...
$destination.Send($msg)
但是 - 一旦复制,我从源队列中删除原始消息的唯一选择似乎是清除 整个 源队列,这也会删除所有其他消息,我不会想做!
$source.Purge()
我以为我正在使用新的 (PowerShell 4+) 'Move-MsmqMessage' cmdlet...
Move-MsmqMessage -DestinationQueue $d -InputObject $q -Message $msg
但我正在努力让它工作 - 我不清楚我是否可以将特定的消息对象传递给它以移动。谁能给我一个使用 PowerShell(任何版本)循环队列中的消息并使用此 Move-MsmqMessage cmdlet 移动特定消息的工作示例?
【问题讨论】:
您不能将消息移出队列。您只能使用原始内容创建新消息以发送到不同的队列,然后删除原始消息。可能听起来很迂腐,但 MSMQ 的概念是目标队列是消息的最终存放位置。有一个确认传递到队列的基本机制和超时。如果您可以移动消息,那么该机制必须以某种方式跟踪该活动(跨多台机器!)并每次通知原始发件人。 Move-MsmqMessage 仅通过使用子队列影响同一队列中的消息。一个队列可以分为许多子队列,但所有消息仍然有效地在同一个队列中。 感谢约翰,让我更清楚了 【参考方案1】:未经测试,但您应该可以使用ReceiveById 函数删除消息:
foreach ( $msg in $msgs )
#Extra logic here - check message body for search string etc...
$source.ReceiveById($msg.Id, [timespan]::FromMinutes(1))
【讨论】:
这成功了!然后调用 $destinationqueue.Send($msg) 我得到了我想要的有效动作。原始消息从源队列中删除,副本出现在目标队列中。我尝试在 ReceivebyId 函数之前调用 .Send,但脚本一直挂起,然后报告超时。在我已经收到/删除源之后,我不太明白如何复制消息,但我认为这是因为在我的完整脚本中,我将所有消息加载到 $msgs = $q.GetAllMessages() 中,所以复制使用的是变量中的内容而不是实际的源消息? 是的,它可能使用变量中的消息。但是我不知道为什么如果你这样做会超时。【参考方案2】:问题和答案不包含使用的完整脚本。这是我用来从队列中删除单个消息的完整脚本,一旦我知道消息的 Id。
[System.Reflection.Assembly]::LoadWithPartialName("System.Messaging")
$queuePath = "FormatName:DIRECT=OS:MachineName\private$\NameOfQueue"
$queue = New-Object System.Messaging.MessageQueue $queuePath
$poisonMessageId = "d53df8ba-3b6a-418b-ab27-198655534253\39996"
$queue.ReceiveById($poisonMessageId)
顺便说一句,找到消息 ID 很容易,顺便说一句。 去寻找消息: 计算机管理 -> 服务和应用程序 -> 消息队列 -> 专用队列。 打开包含您要删除的消息的私人队列 选择“属性”并在“常规”选项卡中显示消息 ID。
【讨论】:
【参考方案3】:Jay Dubya 脚本的扩展版本,按模式删除
$StringToFind = "AMS1-COMET5"
$QueueName = "AMS1-COMET5"
[System.Reflection.Assembly]::LoadWithPartialName("System.Messaging")
$queuePath = "FormatName:DIRECT=OS:"+ [System.Net.Dns]::GetHostName() + "\private$\" + $QueueName
$queue = New-Object System.Messaging.MessageQueue $queuePath
$SrcQueue = Get-MsmqQueue($QueueName)
$Messages = $SrcQueue | Receive-MsmqQueue -Peek -Count 10000000
$Messages |foreach
if ($_.Label -match $StringToFind)
$_.Label
$queue.ReceiveById($_.Id)
【讨论】:
以上是关于如何使用 PowerShell 从 MSMQ 消息队列中删除特定消息的主要内容,如果未能解决你的问题,请参考以下文章