通过Powershell在MSMQ上发送的消息数

通过Powershell在MSMQ上发送的消息数,powershell,msmq,Powershell,Msmq,我想提供一个queuepath并获得相应的消息数。关于如何做到这一点有什么建议吗?中有一组MSMQ管理cmdlet。尝试一下这些方法,看看它们是否有帮助(可能获得MSMQUE): 注意:尝试获取基于beta 2.0模块的发行版-只需记住在解压之前“解锁”拉链。因此,我看到了以下内容:然后转到这里: 做了这个 # Add the .NET assembly MSMQ to the environment. [Reflection.Assembly]::LoadWithPartialName("Sy

我想提供一个queuepath并获得相应的消息数。关于如何做到这一点有什么建议吗?

中有一组MSMQ管理cmdlet。尝试一下这些方法,看看它们是否有帮助(可能获得MSMQUE):

注意:尝试获取基于beta 2.0模块的发行版-只需记住在解压之前“解锁”拉链。

因此,我看到了以下内容:然后转到这里:

做了这个

# Add the .NET assembly MSMQ to the environment.
[Reflection.Assembly]::LoadWithPartialName("System.Messaging")

# Create a new QueueSizer .NET class help to warp MSMQ calls.
$qsource = @"
public class QueueSizer
    {
        public static System.Messaging.Message PeekWithoutTimeout(System.Messaging.MessageQueue q, System.Messaging.Cursor cursor, System.Messaging.PeekAction action)
        {
            System.Messaging.Message ret = null;
            try
            {
                // Peek at the queue, but timeout in one clock tick.
                ret = q.Peek(new System.TimeSpan(1), cursor, action);
            }
            catch (System.Messaging.MessageQueueException mqe)
            {
                // Trap MSMQ exceptions but only ones relating to timeout. Bubble up any other MSMQ exceptions.
                if (!mqe.Message.ToLower().Contains("timeout"))
                {
                    throw;
                }
            }
            return ret;
        }

        // Main message counting method.
        public static int GetMessageCount(string queuepath)
        {
            // Get a specific MSMQ queue by name.
            System.Messaging.MessageQueue q = new System.Messaging.MessageQueue(queuepath);

            int count = 0;

            // Create a cursor to store the current position in the queue.
            System.Messaging.Cursor cursor = q.CreateCursor();

            // Have quick peak at the queue.
            System.Messaging.Message m = PeekWithoutTimeout(q, cursor, System.Messaging.PeekAction.Current);

            if (m != null)
            {
                count = 1;

                // Keep on iterating through the queue and keep count of the number of messages that are found.
                while ((m = PeekWithoutTimeout(q, cursor, System.Messaging.PeekAction.Next)) != null)
                {
                    count++;
                }
            }

            // Return the tally.
            return count;
        }
    }
"@

# Add the new QueueSizer class helper to the environment.
Add-Type -TypeDefinition $qsource -ReferencedAssemblies C:\Windows\assembly\GAC_MSIL\System.Messaging\2.0.0.0__b03f5f7f11d50a3a\System.Messaging.dll

# Call the helper and get the message count.
[QueueSizer]::GetMessageCount('mymachine\private$\myqueue');

而且它起了作用。

欧文提供的解决方案比idea的要少

有一个
.GetAllMessages
调用,您可以在一次检查中完成此操作,而不是foreach循环

$QueueName = "MycomputerName\MyQueueName" 
$QueuesFromDotNet =  new-object System.Messaging.MessageQueue $QueueName


If($QueuesFromDotNet.GetAllMessages().Length -gt $Curr)
{
    //Do Something
}

.Length
提供给定队列中的消息数。

这将列出计算机上的所有队列和消息数:

gwmi -class Win32_PerfRawData_MSMQ_MSMQQueue -computerName $computerName |
    ft -prop Name, MessagesInQueue

Windows Server 2012/2012 R2和Windows 8/8.1下的PowerShell具有一系列内置cmdlet,可通过安装Microsoft消息队列(MSMQ)服务器核心功能来使用

# Get all message queues
Get-MsmqQueue;

# Get all the private message queues.
# Display only the QueueName and MessageCount for each queue.
Get-MsmqQueue -QueueType Private | Format-Table -Property QueueName,MessageCount;
还有许多其他cmdlet可用于队列管理和消息创建。i、 e

  • 新的MsmqQueue
  • 删除MsmqQueue
  • 发送MsmqQueue
  • 接收MsmqQueue
  • 获取MsmqQueueManager

有关MSMQ Cmdlet帮助的完整列表,请参阅或
Get Command-Module MSMQ
(如果您已经安装了该功能)。

按照中的说明,您可以使用

$queues = Get-WmiObject Win32_PerfFormattedData_msmq_MSMQQueue
$queues | ft -property Name,MessagesInQueue
获取本地队列的大小,或

$host = ...
$cred = get-credential
$queues = Get-WmiObject Win32_PerfFormattedData_msmq_MSMQQueue -computer $host -credential $cred
$queues | ft -property Name,MessagesInQueue
用于远程队列。

请尝试下列方法之一

function GetMessageCount2($queuename)
{
    $queuename = $env:computername + "\" + $queuename
    return (Get-WmiObject Win32_PerfFormattedData_msmq_MSMQQueue | Where-Object -filterscript {$_.Name -eq $queuename}).MessagesinQueue 
}

function GetMessageCount3($queuename)
{
    return (Get-MsmqQueue | Where-Object -FilterScript {$_.QueueName -eq $queuename}).MessageCount
}

我在寻找一个很好的答案,虽然欧文的答案让我有了正确的基础,但我在寻找一些更像Powershell的代码。这样做的主要原因是为了处理更改,因为由于在.Net运行时加载了类型,您无法多次添加类型,并且在不关闭powershell实例的情况下无法卸载

因此,我接受了他的回答,并提出:

# Add the .NET assembly MSMQ to the environment.
[Reflection.Assembly]::LoadWithPartialName("System.Messaging") | out-Null

function Get-QueueNames([Parameter(Mandatory=$true)][String]$machineName, [String]$servicePrefix)
{
    [System.Messaging.MessageQueue]::GetPrivateQueuesByMachine($machineName) |
        ForEach-Object { $_.Path } | 
        Where-Object { $_ -like "*$($servicePrefix).*" } 
}

function Get-MessageCount([parameter(Mandatory=$true)][String]$queueName)
{
    function HasMessage
    {
        param
        (
            [System.Messaging.MessageQueue]$queue,
            [System.Messaging.Cursor]$cursor,
            [System.Messaging.PeekAction]$action
        )

        $hasMessage = $false
        try
        {
            $timeout = New-Object System.TimeSpan -ArgumentList 1
            $message = $queue.Peek($timeout, $cursor, $action)
            if ($message -ne $null)
            {
                $hasMessage = $true
            }
        }
        catch [System.Messaging.MessageQueueException]
        {
            # Only trap timeout related exceptions
            if ($_.Exception.Message -notmatch "timeout")
            {
                throw
            }
        }

        $hasMessage
    }

    $count = 0
    $queue = New-Object System.Messaging.MessageQueue -ArgumentList $queueName
    $cursor = $queue.CreateCursor()

    $action = [System.Messaging.PeekAction]::Current
    $hasMessage = HasMessage $queue $cursor $action
    while ($hasMessage)
    {
        $count++
        $action = [System.Messaging.PeekAction]::Next
        $hasMessage = HasMessage $queue $cursor $action
    }

    $count
}

$machineName = "."
$prefix = "something"

Get-QueueNames $machineName $prefix |
    ForEach-Object {
        New-Object PSObject -Property @{
            QueueName = $_
            MessageCount = Get-MessageCount $_
        }
    }
可以对其进行优化,以便第一个函数返回队列而不是队列名称,但在不同的场景中,我需要这两个函数

winrm s winrm/config/client '@{TrustedHosts="yourIp"}'
$securePassword = ConvertTo-SecureString "YourPassword" -AsPlainText -force
$credential = New-Object System.Management.Automation.PsCredential("Domain\Usernama",$securePassword)  
$session = New-PSSession YourIP -credential $credential
$command = {Get-WmiObject Win32_PerfFormattedData_msmq_MSMQQueue | ft -property Name,MessagesinJournalQueue,MessagesInQueue | out-String} 
Invoke-Command -session $session -scriptblock $command

将此用于您的c#块以获取计数。它使用性能计数器查询单个时间:

public static int GetMessageCount(string machineName, string queuepath)
    {
        var queueCounter = new PerformanceCounter(
            "MSMQ Queue",
            "Messages in Queue",
            string.Format("{0}\\{1}", machineName, queuepath),
            machineName);

        return (int)queueCounter.NextValue();
    }
这比重复查看更有效,因为工作主要在远程机器上完成,也比GetAllMessages更有效,因为这会返回额外的消息数据,然后计算元素-在任何实际负载下的糟糕性能。

这对我来说很有效

[System.Reflection.Assembly]::LoadWithPartialName("System.Messaging") | Out-Null

$AlertCount = 39

$queuePath = ".\private$\test.pdpvts.error"

$queue = New-Object System.Messaging.MessageQueue $queuePath


If($queue.GetAllMessages().Length -gt $AlertCount)
{
    Send-MailMessage -To "Me" -From "Alerts" -Subject "Message queue is full" -Credential mycridentials -UseSsl -SmtpServer mail.google.com
}

我一直在四处寻找有关访问集群中队列的信息

对于尝试在群集队列上使用powershell命令的其他人:

在其中一个群集节点上:

$env:computername = "MsmqHostName"
Get-MsmqQueue | Format-Table -Property QueueName,MessageCount
远程群集:

Invoke-Command -ScriptBlock {$env:computername = "msmqHostName";Get-MsmqQueue | Format-Table -Property QueueName,MessageCount } -ComputerName ClusternNodeName


实际上,我注意到WMI调用并不总是枚举所有队列。不知道为什么。最后,我在一个服务器列表上调用了[System.Messaging.MessageQueue]::GetPublicQueuesByMachine($machineName),然后使用Irwin的[QueueSizer]::GetMessageCount($queuepath)方法获取每个队列的消息数。有没有办法从中获取超过前100条的消息?不幸的是,这会将队列名称截断为64个字符,并且只返回前97个结果:(@RobO是否有办法获取完整脚本的副本?谢谢。但这是否安全?这两种解决方案是否都可能阻止读取这些队列的其他进程?当您有一个包含数万条消息的队列时,此方法的性能很差,不是一个好的选择。此处相同。此脚本占用千兆字节的内存对于大消息和长时间排队,请稍等片刻,然后投票这最后两条评论(我刚刚做了)。这是一个公平的批评。对你们两个来说,什么选项对你们有效?你们投票了吗?你们有更好的选项吗?我已经有一段时间没做MSMQ工作了,希望永远不要再做了:-)“这是一种效率低下的获取消息计数的方法,因为它需要读取所有消息并将它们存储在内存中的数组中。根据消息的频率、大小和队列中当前消息的数量,这可能会导致巨大的内存消耗,并可能影响应用程序的性能。“更好地使用WMI:+1回答得好。另外,不确定原因,但我必须将“QueueSizer::”更改为“[QueueSizer]::“在该脚本运行的最后一行中,@JohnD+1方括号表示一种类型。正如你提到的,这是必需的。因为GetMessageCount是一个静态方法,所以需要直接引用该类型。如果它是一个实例方法,您必须首先创建一个对象,比如$qs=newobjectqueuesizer;然后引用$qs.NetMessageCourt…这是一个糟糕的答案,因为它正在迭代消息并计算它们。将1000000条消息添加到您的队列中,然后运行此操作,您将看到安装SPCX需要多长时间?我只希望在远程服务器中执行XCOPY deploment。PowerShell的更高版本附带MSMQ模块-尽管我不知道该模块是否仅在Win8/Server2012上可用。@RobertMooney该链接不起作用。是的,没有连接到远程计算机的内置-ComputerName参数,但是您可以使用PowerShell远程处理。但是请注意,Get-MsMqQueue仅适用于本地队列。请参阅。此处的一些注释将非常有用。这在没有新cmdlet的旧2008 R2服务器上运行得非常好
Invoke-Command -ScriptBlock {$env:computername = "msmqHostName";Get-MsmqQueue | Format-Table -Property QueueName,MessageCount } -ComputerName ClusternNodeName