Automatically resend expired MSMQ dead letter messages using QueueMonitor

There were few inquires recently on what to do with messages which were moved by MSMQ to dead letter queue because they reached “Time to be received” timeout.

When is Time to be received property useful?

Sometimes messages are of temporary value and are not important unless they are processed immediately. For instance if we use queue to send current status of some process, next message will anyway be come after few seconds. Even if we stop processing we don’t want to process all pending messages if we’re only interested in latest one. For these scenarios Time to be received makes sense, since MSMQ will automatically remove these messages from queue once timeout is reached. If messages are set to use Dead letter queue, they will be moved to one of two System Dead-letter queues – one for transactional messages and one for non-transactional.

However sometimes reality gets in a way. Sender has some expectations and sets Time to be received to few minutes, but circumstances change and we find out that these messages are still needed and important even if they were moved to dead letter queue.

How to automatically resend messages to their original queue using QueueMonitor

For this to work you’ll need QueueMonitor Professional, since it offers more complex processing.


Step 1 – New task

Click on “New Task…” and pick “Process messages – scheduled” task.

QueueMonitor - Select a task

Why scheduled processing? Because dead letter queues can contain messages which came there for various reasons – for instance purged messages, etc. We don’t want to return all of these messages back to their queues, we’re interested only in expired ones. There’s similar task “Process messages – constantly” but it constantly watches a queue and should be used when all arriving messages should be processed as soon as they arrive. If we don’t want to remove all messages after they’re processed, constant processing will be suboptimal because it will keep iterating through queue all the time which could be a problem for system resources.


Step 2 – Pick a queue

Choose one of System queues – “Dead letter messages” or “Transactional dead-letter messages”. In you want to monitor both DL queues, you should create two separate tasks because of limitations in current version of QueueMonitor we’ll discuss later.

Select a queue

Step 3 – Schedule

Pick how often you want this task to occur:


Step 4 – Message filter

If we want to only resend messages which were expired, we should make appropriate filter:

Message filter for ReceiveTimeout

Turn on Advanced query option, select Acknowledgment property and set it to equals ReceiveTimeout

You can make more complex query here, if you want to process only certain messages.


Step 5 – Actions

Change Time to be received

Add Change message properties action and configure it to change “Time to be received” property.

Send to queue action

Add Send to queue action. For destination name type {msg_destination} (you can also insert macros by clicking on M button). This will make sure that message goes back to its original destination.

And here’s a reason why you had to create separate tasks for transactional and non-transactional DLQs. Sending in MSMQ requires that you either wrap it in Transaction or not, depending on type of queue. For local queues QueueMonitor can determine whether queue is transactional, but if it’s remote queue or if macros are used (like in this case), it can’t and you have to set it manually. So if this task is for transactional DLQ check Transactional checkbox, otherwise leave it unchecked.

Step 6 – Done

You can save new task now. In order to read system queues, QueueMonitor service will have to work under account with administrative privileges. If it’s not already set, go to Computer Management, find QueueMonitor service and change it’s Log On as setting.

You can use “Run once now” option to test new task whether it works correctly. If everything is ok, you can enable this task and it will continue to work in background, happily resending all expired messages back to their original queues.