Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Monday, June 17, 2019

Clear out old MSMQ messages

Microsoft Message Queuing or MSMQ is a message queue implementation developed by Microsoft and deployed in its Windows Server operating systems.

MSMQ is essentially a messaging protocol that allows applications running on separate servers/processes to communicate in a failsafe manner. A queue is a temporary storage location from which messages can be sent and received reliably, as and when conditions permit. This enables communication across networks and between computers, running Windows, which may not always be connected. By contrast, sockets and other network protocols assume that direct connections always exist.

Source: Wikipedia

If everything is working, messages are added to the queue by one application, and then typically read and removed from the queue by another application.

However, sometimes messages will get 'stuck' in the queue. While this is sometimes due to networking or application changes, the queue may back up if the receiving application is not running or running slower than normal.

Once the underlying problem has been fixed, depending on your application, the receiving application may never be able to catch up with the quantity of messages currently in the queue plus those still being added.

While you can purge the full queue:
Computer Management -> Services and Applications -> Message Queuing
Select your private queue, right click, All Tasks -> Purge


You may want to only purge the "old" messages.
Depending on your application, "old" could be seconds, minutes or hours.

The following PowerShell script will iterate over your private queues and remove "old" messages.
You can set the definition of "old" and you can preview the messages without removing.

###
# remove old messages for all local msmq queues
# msmq = microsoft messaging queuing
#
# 20190530 122800
#   add options $showMsg and $dryRun
# 20190521 122800
#   initial
#

#
# config
#
[System.Reflection.Assembly]::LoadWithPartialName("System.Messaging") | Out-Null
$utf8 = new-object System.Text.UTF8Encoding
$now = Get-Date
# remove messages older than
# $old = $now.AddDays(-1)
$old = $now.AddMinutes(-10)
# show details of message to be removed
$showMsg = 1
# run without removing
$dryRun = 1

#
# run
#

# get queues
$queuePaths = Get-MsmqQueue -QueueType Private | Select -Property QueueName;
if ($dryRun)
{
    echo "dry run; would be "
}
echo "removing old messages for all local msmq queues"
echo ""
echo "nbr queues: $($queuePaths.Length); checking messages older than $($old)"
$queueCounts = Get-MsmqQueue -QueueType Private | Format-Table -Property QueueName,MessageCount;
echo $queueCounts
echo ""
pause
foreach ($queuePath in $queuePaths)
{
    # for proper permissions, prepend .\
    $localQueuePath = ".\$($queuePath.QueueName)"
    echo "queue: $localQueuePath"
   $queue = New-Object System.Messaging.MessageQueue $localQueuePath
   
    # to read ArrivedTime property
    $queue.MessageReadPropertyFilter.SetAll()
   
    # get snapshot of all messages, but uses memory, and slower
   # $msgs = $queue.GetAllMessages()
    # echo "  $($msgs.Length) messages"
    # get cursor to messages in queue
    $msgs = $queue.GetMessageEnumerator2()
   
    # add a message so can test
    # $queue.Send("<test body>", "test label")
    # pause
    $removed = 0
   # foreach ($msg in $msgs)
    while ($msgs.MoveNext([timespan]::FromSeconds(1)))
   {          
       $msg = $msgs.Current
      if ($msg.ArrivedTime -and $msg.ArrivedTime -lt $old)      
      {
           if ($showMsg)
           {
               echo "--------------------------------------------------"
               echo "ArrivedTime: $($msg.ArrivedTime)"
               echo "BodyStream:"
               if ($msg.BodyStream)
               {
                   echo $utf8.GetString($msg.BodyStream.ToArray())
               }
               echo "Properties:"
               echo $msg | Select-Object
               echo ""
           }
         
           try {
               if (!$dryRun)
               {
                   # receive ie remove message by id from queue
                   $queue.ReceiveById($msg.Id, [timespan]::FromSeconds(1))
               }
               $removed++
           } catch [System.Messaging.MessageQueueException] {
               $errorMessage = $_.Exception.Message
               # ignore timeouts              
               if (!$errorMessage.ToLower().Contains("timeout"))
               {
                   throw $errorMessage
               }
           }
      }
   }
    if ($dryRun)
    {
       echo "dry run; would have "
    }
    echo "removed $removed messages from $localQueuePath"
    echo ""
}

pause
#
###

View on GitHub

-End of Document-
Thanks for reading

Monday, July 23, 2018

PowerShell script to copy files based on shortcuts

From the source directory, find all shortcuts, and copy the shortcut contents to a destination directory

PowerShell is a task automation and configuration management framework from Microsoft, consisting of a command-line shell and associated scripting language. Wikipedia

# Get all shortcuts
$shortcuts = gci "$srcDir\*.lnk"

cgi = Get-ChildItem  Microsoft
Gets the items and child items in one or more specified locations.

# skip existing dirs
if (Test-Path "$destPath") {

Test-Path Microsoft
Determines whether all elements of a path exist.

# copy
copy-item -Path "$srcPath" -Destination "$destRecreatePath" -Force -Recurse -Container -Exclude $exclude

copy-item Microsoft
Copies an item from one location to another.
But alas, without any indication of progress.

So, from some help on Stack Overflow
# xcopy prompts for is this a file/dir, no progress
# robocopy asks for admin perms on ntfs/audit attribs
# copy copies with progress %
# /z   : Copies networked files in restartable mode.
cmd /c copy /z $srcFile $destFile

Some screenshots of the full script in action






And the full source is on GitHub


End of document. Thanks for reading.