【发布时间】:2018-02-23 20:52:38
【问题描述】:
我有一个用于清除机器上的消息队列的函数,但我希望对其进行调整并使其更加健壮。即使当前机器没有安装 MSMQ,我也希望能够向机器发出命令。
本地命令没有问题,但是当调用命令时,检查队列是否存在返回 false(即使队列确实存在)。有没有人遇到过这样的事情?有什么建议吗?
这是我的功能:
Function Purge-MessageQueue
{
<#
.Synopsis
Use hostname to purge message queue
.DESCRIPTION
Checks if MSMQ is locally installed otherwise fire the purge
command to the machine you are purging
.EXAMPLE
Purge-MessageQueue -targetMachine $env:computername -queueName 'test'
#>
Param
(
[Parameter(Mandatory=$true)]
[String]$targetMachine,
[Parameter(Mandatory=$true)]
[string]$queueName
)
Write-Verbose "Purging $queueName queue on: $targetMachine"
$queueName = "$targetMachine\$queueName"
$error.clear()
[void] [Reflection.Assembly]::LoadWithPartialName("System.Messaging")
try {[void][System.Messaging.MessageQueue]::Exists($queueName)}
catch
{
if ($_.exception.ToString() -like '*Message Queuing has not been installed on this computer.*')
{
#push command to machine
$RemoteSuccess = Invoke-Command -ComputerName $targetMachine -ScriptBlock { Param($queueName)
[void] [Reflection.Assembly]::LoadWithPartialName("System.Messaging")
If([System.Messaging.MessageQueue]::Exists($queueName))
{
$queue = new-object -TypeName System.Messaging.MessageQueue -ArgumentList $queueName
Try{$queue.Purge()}
Catch{$error}
}
} -ArgumentList $queueName
}
}
If(!$error)
{
If([System.Messaging.MessageQueue]::Exists($queueName))
{
$queue = new-object -TypeName System.Messaging.MessageQueue -ArgumentList $queueName
$queue.Purge()
}
}
If(!$Error -and !$RemoteSuccess)
{
Write-Host "$queueName queue on $targetMachine cleared"
}
Else
{
Write-Warning "Failed locating queue $queueName on $targetMachine"
}
}
注意事项: 为了确定到底发生了什么,我在 exists 语句上使用了 write-host,它返回 false。当我通过脚本块时找不到队列。它正在另一台机器上执行(测试写入成功的文件)。当我跑步时:
Write-Host "$([System.Messaging.MessageQueue]::Exists($queueName))`n$queueName"
$objqueue = new-object -TypeName System.Messaging.MessageQueue -ArgumentList $queueName
我得到了错误的、正确的队列名称和以下错误:
使用“0”参数调用“Purge”的异常:“队列没有 存在或您没有足够的权限来执行 手术。” + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : MessageQueueException + PSComputerName : XXXXXX
直接在机器上运行相同的命令没有问题。
我还发现其他人试图在 serverfault 上做类似的事情: https://serverfault.com/questions/399178/how-to-retrieve-names-of-all-private-msmq-queues-efficiently
当我尝试这个时:
Invoke-Command -ComputerName $targetMachine -ScriptBlock { Get-MsmqQueue }
我得到以下结果:
找不到指定的机器。 + CategoryInfo : ObjectNotFound: (:) [Get-MsmqQueue], MessageQueueException + FullyQualifiedErrorId : MachineNotFound,Microsoft.Msmq.PowerShell.Commands.GetMSMQQueueCommand
以下命令确实返回数据,但它不允许我发送清除命令:
Invoke-Command -ComputerName $targetMachine -ScriptBlock {Get-WmiObject -class Win32_PerfRawData_MSMQ_MSMQQueue}
我还尝试将内容写入脚本文件,然后调用该文件,该文件在机器上运行时可以正常工作,但通过调用命令调用时不会:
$filewriter = @"
[Reflection.Assembly]::LoadWithPartialName("System.Messaging")
If([System.Messaging.MessageQueue]::Exists('$queueName'))
{
`$objqueue = new-object -TypeName System.Messaging.MessageQueue -ArgumentList $queueName
Try{`$objqueue.Purge()}
Catch{`$error}
}
"@
$session = New-PSSession -ComputerName $targetMachine
Invoke-Command -Session $session -ScriptBlock {Param($FileWriter)
$FileWriter | Out-File "C:\Temp\PurgeQueue.ps1"
} -ArgumentList $filewriter
$test = Invoke-Command -Session $session -scriptblock {Pushd "C:\Temp\"
.\PurgeQueue.ps1}
【问题讨论】:
标签: powershell msmq invoke-command