Trim Queue

Microsoft.MSMQ.10.0.TrimQueue (WriteActionModuleType)

Removes messages from the queue until specified quota usage is reached.

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityPublic
RunAsMicrosoft.MSMQ.10.0.QueueAccessProfile
InputTypeSystem.BaseData

Member Modules:

ID Module Type TypeId RunAs 
WA WriteAction Microsoft.Windows.ScriptWriteAction Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
TrimLogicstring$Config/TrimLogic$Trim Logic
NumericParameterint$Config/NumericParameter$Numeric Parameter
TimeoutSecondsint$Config/TimeoutSeconds$Timeout Seconds

Source Code:

<WriteActionModuleType ID="Microsoft.MSMQ.10.0.TrimQueue" Accessibility="Public" RunAs="Microsoft.MSMQ.10.0.QueueAccessProfile" Batching="false">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="Computer" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="QueuePath" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" maxOccurs="1" name="TargetQueue" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="TrimLogic" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="0" maxOccurs="1" name="NumericParameter" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="TimeoutSeconds" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="TrimLogic" Selector="$Config/TrimLogic$" ParameterType="string"/>
<OverrideableParameter ID="NumericParameter" Selector="$Config/NumericParameter$" ParameterType="int"/>
<OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<WriteAction ID="WA" TypeID="Windows!Microsoft.Windows.ScriptWriteAction">
<ScriptName>TrimQueue.vbs</ScriptName>
<Arguments>"$Config/Computer$" "$Config/QueuePath$" "$Config/TrimLogic$" $Config/NumericParameter$</Arguments>
<ScriptBody><Script>option explicit
SetLocale("en-us")

Const SCRIPT_NAME = "TrimQueue.vbs"

Const MQ_RECEIVE_ACCESS = 1
Const MQ_SEND_ACCESS = 2
Const MQ_PEEK_ACCESS = 32
Const MQ_ADMIN_ACCESS = 128

Const MQ_DENY_NONE = 0
Const MQ_DENY_RECEIVE_SHARE = 1

Const MQ_MTS_TRANSACTION = 1
Const MQ_XA_TRANSACTION = 2
Const MQ_SINGLE_MESSAGE = 3

Const EVENTNO_SCRIPT_STARTED = 14501
Const EVENTNO_SCRIPT_ENDED = 14502
Const EVENTNO_MESSAGES_REMOVED = 14531
Const EVENTNO_QUEUE_PURGED = 14532
Const EVENTNO_ERROR_BADLOGIC = 14590


Const EVENT_LEVEL_ERROR = 1
Const EVENT_LEVEL_WARNING = 2
Const EVENT_LEVEL_INFO = 4

Dim oApi
Dim sComputer, sQueuePath, sLogic, wshNetwork, sDomain, sUser, sMessage
Dim bIsCluster, WshShell, objWshShell, sName
Dim oQueueInfo, oJournalInfo, oMgmt, oJournalMgmt, oJournal, oMessage
Dim oInitialStats, oRunningStats, iMessagesRemoved, dKBytesRemoved, bShowSummary, dLatestDateRemoved, dCutoffDate
Dim dTargetQuotaPctg, iMinutes, dKbytes, dTargetSize

sComputer = WScript.Arguments(0)
sQueuePath = WScript.Arguments(1)
sLogic = WScript.Arguments(2)

Set oAPI = CreateObject("MOM.ScriptAPI")

Set wshNetwork = CreateObject("Wscript.Network")
sDomain = wshNetwork.UserDomain
sUser = wshNetwork.UserName
sMessage = "Starting Script: " &amp; SCRIPT_NAME &amp; VbCrLf &amp; _
"User credentials: " &amp; sDomain &amp; "\" &amp; sUser &amp; VbCrLf &amp; _
"Network Name: " &amp; wshNetwork.ComputerName &amp; VbCrLf &amp; _
"Computer Name: " &amp; sComputer &amp; VbCrLf &amp; _
"Queue Path: " &amp; sQueuePath &amp; VbCrLf &amp; _
"Logic: " &amp; sLogic

Call oAPI.LogScriptEvent(SCRIPT_NAME,EVENTNO_SCRIPT_STARTED,EVENT_LEVEL_INFO,sMessage)
Wscript.Echo sMessage

bIsCluster = false
If IsCluster = True then
bIsCluster = true
set WshShell = CreateObject("WScript.Shell")
set objWshShell = WshShell.Environment("Process")
sName = GetQueueServer(sComputer)
objWshShell("_CLUSTER_NETWORK_NAME_") = sName
objWshShell("_CLUSTER_NETWORK_HOSTNAME_") = sName
End If

Set oQueueInfo = CreateObject("MSMQ.MSMQQueueInfo")
Set oJournalInfo = CreateObject("MSMQ.MSMQQueueInfo")
Set oMgmt = CreateObject("MSMQ.MSMQManagement")
Set oJournalMgmt = CreateObject("MSMQ.MSMQManagement")

On Error resume next
oQueueInfo.PathName = sQueuePath
oQueueInfo.Refresh
oJournalInfo.FormatName = oQueueInfo.FormatName &amp; ";JOURNAL"
Set oJournal = oJournalInfo.Open(MQ_RECEIVE_ACCESS,MQ_DENY_NONE)
Call oMgmt.Init(sComputer, , "DIRECT=OS:" &amp; sQueuePath)
if Err &lt;&gt; 0 then
sMessage = "There was an error" &amp; VbCrLf &amp; _
"Error Number: " &amp; Err.Number &amp; VbCrLf &amp; _
"Error Description: " &amp; Err.Description
Call ThrowScriptError(EVENTNO_ERROR_BADLOGIC,EVENT_LEVEL_WARNING,sMessage)
End if

Set oInitialStats = New QueueStat
Set oRunningStats = New QueueStat

iMessagesRemoved = 0
dKBytesRemoved = 0
Select Case lcase(sLogic)

Case "quota"
bShowSummary = True
dTargetQuotaPctg = CDbl(WScript.Arguments(3))
While oRunningStats.JournalQuotaPctg &gt; dTargetQuotaPctg
Set oMessage = oJournal.Receive(MQ_SINGLE_MESSAGE, False, True, 5, False)
oRunningStats.Refresh
iMessagesRemoved = iMessagesRemoved + 1
dLatestDateRemoved = oMessage.ArrivedTime
Wend

Case "time"
bShowSummary = True
iMinutes = WScript.Arguments(3)
dCutoffDate = DateAdd("n",-iMinutes,Now)
Set oMessage = oJournal.Receive(MQ_SINGLE_MESSAGE, False, True, 5, False)
oRunningStats.Refresh
iMessagesRemoved = 1
While oMessage.ArrivedTime &lt; dCutoffDate
Set oMessage = oJournal.Receive(MQ_SINGLE_MESSAGE, False, True, 5, False)
iMessagesRemoved = iMessagesRemoved + 1
dKBytesRemoved = dKBytesRemoved + (CDbl(oMgmt.BytesInJournal) / 1000)
dLatestDateRemoved = oMessage.ArrivedTime
Wend

Case "kbytes"
bShowSummary = True
dKbytes = WScript.Arguments(3)
Set oMessage = oJournal.Receive(MQ_SINGLE_MESSAGE, False, True, 5, False)
oRunningStats.Refresh
dTargetSize = oInitialStats.KBytesInJournalQueue - dKbytes
While oRunningStats.KBytesInJournalQueue &gt; dTargetSize
Set oMessage = oJournal.Receive(MQ_SINGLE_MESSAGE, False, True, 5, False)
iMessagesRemoved = iMessagesRemoved + 1
dKBytesRemoved = dKBytesRemoved + (CDbl(oMgmt.BytesInJournal) / 1000)
dLatestDateRemoved = oMessage.ArrivedTime
oRunningStats.Refresh
Wend

Case "purge"
bShowSummary = True
oJournal.Purge
oRunningStats.Refresh

Case "statistics"
bShowSummary = False
WScript.Echo oInitialStats.GetSummary

Case Else
sMessage = "Bad argument provided for trimming logic." &amp; VbCrLf &amp; _
"Possible values are quota, time, kbytes, or purge." &amp; VbCrLf &amp; _
"Argument provided: " &amp; sLogic
Call ThrowScriptError(EVENTNO_ERROR_BADLOGIC,EVENT_LEVEL_WARNING,sMessage)

End Select

If bShowSummary = True Then
sMessage = "Messages were removed from queue journal." &amp; VbCrLf &amp; _
"Queue: " &amp; sQueuePath &amp; VbCrLf &amp; _
"Algorithm: " &amp; sLogic &amp; VbCrLf &amp; _
"Messages removed: " &amp; iMessagesRemoved &amp; VbCrLf &amp; _
"KBytes removed: " &amp; dKBytesRemoved &amp; VbCrLf &amp; _
"Latest date removed: " &amp; dLatestDateRemoved &amp; VbCrLf &amp; _
VbCrLf &amp; _
"Initial statistics: " &amp; VbCrLf &amp; _
oInitialStats.GetSummary &amp; VbCrLf &amp; _
VbCrLf &amp; _
"Final statistics: " &amp; VbCrLf &amp; _
oRunningStats.GetSummary

Call oAPI.LogScriptEvent(SCRIPT_NAME,EVENTNO_MESSAGES_REMOVED,EVENT_LEVEL_WARNING,sMessage)
WScript.Echo sMessage
End If

if bIsCluster = true then
objWshShell.Remove("_CLUSTER_NETWORK_NAME_")
objWshShell.Remove("_CLUSTER_NETWORK_HOSTNAME_")
End If

Call oAPI.LogScriptEvent(SCRIPT_NAME,EVENTNO_SCRIPT_ENDED,EVENT_LEVEL_INFO,"TrimQueue.vbs finished.")

Function GetQueueServer(Path)

If InStr(Path,".") &gt; 0 Then
GetQueueServer = Left(Path,InStr(Path,".")-1)
Else
GetQueueServer = Path
End If

End Function

Function IsCluster()
Dim wshNetwork

Set wshNetwork = CreateObject("Wscript.Network")
if StrComp(wshNetwork.ComputerName, GetQueueServer(sComputer), 1) &lt;&gt; 0 then
IsCluster = True
else
IsCluster = False
End if

End Function

Sub ThrowScriptError(EventNo,Severity,Message)

Message = "Script aborted due to the following script error:" &amp; VbCrLf &amp; Message
Call oAPI.LogScriptEvent(SCRIPT_NAME,EventNo,Severity,Message)
WScript.Quit

End Sub

Class QueueStat

Private Sub Class_Initialize()
ComputerName = sComputer
QueuePath = sQueuePath
Me.Refresh
End Sub

Public Sub Refresh()

Quota = oQueueInfo.Quota
JournalQuota = oQueueInfo.JournalQuota
MessagesInQueue = oMgmt.MessageCount
KBytesInQueue = CDbl(oMgmt.BytesInQueue) / 1000
MessagesInJournalQueue = oMgmt.JournalMessageCount
KBytesInJournalQueue = CDbl(oMgmt.BytesInJournal) / 1000
If oQueueInfo.Quota &gt; 0 Then
QuotaPctg = (CDbl(oMgmt.BytesInQueue) / 1000) / (CDbl(oQueueInfo.Quota)) * 100
Else
QuotaPctg = 0
End If
If oQueueInfo.JournalQuota &gt; 0 Then
JournalQuotaPctg = (CDbl(oMgmt.BytesInJournal) / 1000) / (CDbl(oQueueInfo.JournalQuota)) * 100
Else
JournalQuotaPctg = 0
End If

End Sub

Public Function GetSummary

With Me

GetSummary = "Computer Name: " &amp; .ComputerName &amp; VbCrLf &amp; _
"Queue Path: " &amp; .QueuePath &amp; VbCrLf &amp; _
"Quota: " &amp; .Quota &amp; VbCrLf &amp; _
"Journal Quota: " &amp; .JournalQuota &amp; VbCrLf &amp; _
"Messages in Queue: " &amp; .MessagesInQueue &amp; VbCrLf &amp; _
"KBytes in Queue: " &amp; .KBytesInQueue &amp; VbCrLf &amp; _
"Quota Pctg: " &amp; .QuotaPctg &amp; VbCrLf &amp; _
"Messages in Journal Queue: " &amp; .MessagesInJournalQueue &amp; VbCrLf &amp; _
"KBytes in Journal Queue: " &amp; .KBytesInJournalQueue &amp; VbCrLf &amp; _
"Journal Quota Pctg: " &amp; .JournalQuotaPctg
End With

End Function

Public ComputerName
Public QueuePath
Public Quota
Public JournalQuota
Public MessagesInQueue
Public KBytesInQueue
Public QuotaPctg
Public MessagesInJournalQueue
Public KBytesInJournalQueue
Public JournalQuotaPctg

End Class</Script></ScriptBody>
<TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="WA"/>
</Composition>
</Composite>
</ModuleImplementation>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>