Click here to Skip to main content
Click here to Skip to main content

Programatically Creating MSMQ Triggers

, 16 Apr 2008
Rate this:
Please Sign up or sign in to vote.
An article on creating MSMQ triggers dynamically at runtime and firing it to take a custom action

Introduction

As we know, the modern world's enterprise applications are more dynamic and require more complex communication among processes as well as among different application components. This is where MSMQ (Microsoft Message Queue) comes in the picture. MSMQ is essentially an application that guarantees sending and receiving messages reliably in a disconnected distributed environment. But the real power of MSMQ provided with MSMQ Triggers. Though creating Triggers manually is a fairly easy task, creating it dynamically at runtime and firing it to take some custom action is a more complex task. Recently I was implementing such a complex task in my project and believe me, at one stage when my clock was ticking past 3 A.M. I was wondering why did I choose this IT field which causes me such miserable moments in life ... Anyway, by a Click and Go approach I finally got the job done.

Background

About MSMQ

Basically MSMQ is standardized messaging (data transferring) technique in an enterprise environment. Data is transferred in a serializable format as a message to the queue. At the other side it's deserialized to get real data. An MSMQ message can be anything from a simple string to any class object or from an XML file to PDF Documents. Fortunately, now MS VS.NET 2005 provides support for MSMQ 3.0. To implement MSMQ in your .NET application you have to import the System.Messaging Namespace, which can be imported by adding reference to the System.Messaging assembly. Anyway, to keep track of this article I won't go in much detail about MSMQ, newbies can find lot of online tutorials about MSMQ including MSDN.

About MSMQ Trigger

At a basic level you can think of the MSMQ Trigger as like any simple database trigger. They are very handy when we need to take custom action in response to the arrival of incoming message(s) to the particular message queue. MSMQ Triggers allows us to take one of two actions, either you can execute a standalone .exe file or you can Invoke a COM+ service component's method. This way you can consume your COM+ services in the .NET world. So without further discussion about its advantages let me show you both of these approaches here. But before we go to develop a code let's see the other side of Trigger because it does have other sides as well.

About Trigger Rule

Surely, rule can be defined as the other side of the MSMQ Trigger. Rule consists of two components: Condition and Action. Conditions are checked against the properties of incoming message(s) which are evaluated to true or false. A single rule can contain more than one condition like the message body contains specific words, message labels do not contain specific words, message priorities and so on. Action is an execution of real business logic. When conditions of rule evaluates to true action associated with rule, will be taken. As I mentioned before, action can be taken by executing standalone .exe file or it can invoke COM+ service component method passing its required parameters. In order to fire Trigger successfully you must associate rule(s) with Trigger. What I mean is that there must be rule that exists to associate with Trigger. So let's move to the details of creating triggers and rules programatically to execute needed action.

Using Code

Basic Requirement

To create an MSMQ Trigger in your .NET application you must have it installed in your machine. If you are using MSMQ 3.0 then you dont have to install it separately but if you need to install it then you can download it from Microsoft download center. Moreover, when you decide to work with MSMQ Triggers you just need to make sure that your Message Queuing Triggers service is running. This service is required to fire MSMQ Triggers. I have it up and running in my machine as shown in the figure below:

MSMQ_Trigger_Service.JPG

To deal with Triggers in a programatic way you have to Import the MSMQ Trigger Objects library. To import this library in your application you need to add a reference to the mqtrig.dll file which resides under the %System Root%\Windows\System32 directory. When you finish adding reference to the mqtrig.dll file you can see that you have new references to the assembly MSMQTriggerObjects which will be added to your project as illustrated in below figure:

MSMQ_Trigger_Objects.JPG

For MSMQ Tigger to work you must have a reference to the monitoring Message Queue which you need to fire a trigger on. So let's first write code to get a reference to a message queue:

'Path for Message Queue to be monitored

Dim strQueuePath As String = ".\private$\TestQueue" 
'Reference to Message Queue
Dim QMsgQue As MessageQueue

'Get a reference to queue if it already exists else create new queue at the
'specified path 

If MessageQueue.Exists(strQueuePath) Then
    'Get a reference to queue 
    QMsgQue = New MessageQueue(strQueuePath)
Else
    'Create new queue 
    QMsgQue = MessageQueue.Create(strQueuePath)

End If

The above code will create a Message Queue named TestQueue on MSMQ Server (if it does not exist there) and give a reference to queue in your application to work with.

Rule Creation

The first task is to create a rule to specify conditions and actions of a trigger. Once we have rule available then we can associate this rule with trigger so we can decide to fire a trigger action or not based on an evaluation of condition. We need to specify the condition and action for rule, though, you can leave the condition part unspecified if you don't want to check any condition. Leaving the condition part blank will always evaluate condition as true. Of course, there are two options provided for action part:

  1. Executing stand alone EXE file and
  2. Invoking method of COM+ service component

So let's write code for our first option, executing a standalone EXE file:

'StringBuilder to specify condition and action for a rule
Dim RuleBuilder As New System.Text.StringBuilder

'Specify action to execute stand alone EXE file 

RuleBuilder.Append("EXE"    & vbTab) 
'Path of your exe file goes here
RuleBuilder.Append("C:\ASP.NET\CreateDir\CreateDir\bin\Debug\CreateDir.exe" & vbTab)

Dim allAction As String = RuleBuilder.ToString 

'Rule ID Parameter,This is going to be out parameter 
'and setted up when rule is successfully created
Dim ruleID As String  = String.Empty 

'Create RuleSet object to create rule
Dim objRule As New MSMQTriggerObjects.MSMQRuleSet 

'Initialize RuleSet object before calling any method on it 
objRule.Init(Environment.MachineName)

'Add Rule to RuleSet Object specifying rulename, 
'conditon,action and other parameters 
objRule.Add("MyTestRule", "Test Rule",String.Empty, _
allAction,"MSMQTriggerObjects.MSMQRuleHandler", 0, ruleID) 

'Condition string 
Dim strCondition As String = "$MSG_LABEL_CONTAINS=Test" 

'Optionally add rule with condition
objRule.Add("MyTestRule","Test",strCondition,allAction,
   "MSMQTriggerObjects.MSMQRuleHandler",0,ruleID)

Creating rule this way seems really simple but there are some points to keep in mind. First, make sure that path of .exe file is correct and file does exist at a given path otherwise an exception will be thrown at runtime. Second, you must first Initialize the MSMQRuleSet object by calling its Init() method passing it name of machine where rule is to be created. The Add() method of MSMQRuleSet object is used to add rule to the MSMQ server. The parameter passed to the Add() method are name, description, condition (note that leaving the condition blank means its true in all case), action (EXE Invocation), implementation of rule, flag (indicates whether excuting an EXE file should interact with deskop or should run silently). Lastly, ruleId is a reference parameter respectively. Upon successful creation of rule this ruleId will be assigned GUID. This ruleId is useful when you want to refer to a rule by its Id or if say, you want to delete a rule.

Our second option which is Invoking a method of the COM+ service component is not as simple as our first option because it interacts with an unmanaged code which is not under control of CLR. Additionally, for this option to work you must have a service component available and be registered with component services in your machine. If you are new to creating and registering a service component then I suggest you check for it across the web and I am sure you will find lot of tutorials and articles on it. You can check for registered service components in your machine under Control Panel --> Administrative Tools --> Component Services. You can even access it from the Run command menu by typing in dcomcnfg command and pressing Enter. The below figure shows the component which I am going to use to invoke its method.

COM__Service_Component.JPG

To implement the COM+ service component invocation in your application you just need to change an action part of rule definition and the rest will be the same.

'Specify to invoke COM+ Service component method 
RuleBuilder.Append("COM" & vbTab) 

'ProgramID of your COM+ Service component 

RuleBuilder.Append("COMAndMSMQTrigger.TraceMSMQMessage" & vbTab) 

'Name of method to be invoked 
RuleBuilder.Append("HelloUser" & vbTab) 

'Method parameter specification, 
'Here Message Label will be passed as parameter to method 
RuleBuilder.Append("$MSG_LABEL" & vbTab) 


'Our action string 
Dim allAction As String = RuleBuilder.ToString

The only important part in the above code is the parameters you pass to a method of COM component. The parameters you can pass must match the number of parameters a method accepts and order of paramaters in a method signature. You can pass various type of parameters like a message body as string, as class object, message Id and so on.

Trigger Creation

The next task is to create tigger so that we can associate existing rule with it.Below code will create trigger in your application.

'TriggerID Parameter,Its out parameter like RuleID      
'and setted up when trigger will be successfully created        
Dim TrgID As String = String.Empty         

'Create TriggerSet object to create trigger
Dim objTrg As New MSMQTriggerObjects.MSMQTriggerSet  


'Initialize TriggerSet object before calling any method on it 
objTrg.Init(Environment.MachineName) 

'Create and add trigger          
objTrg.AddTrigger("TestTrg",strQueuePath,
     MSMQTriggerObjects.SystemQueueIdentifier.SYSTEM_QUEUE_NONE, _
     1,0,MSMQTriggerObjects.MsgProcessingType.RECEIVE_MESSAGE,TrgID)

'Associate rule with trigger             
objTrg.AttachRule(TrgID,ruleID, 0)

Here again you must first call the Init() method on TriggerSet object passing it machine name and then you will be able to call any other method on it. Using AddTrigger() method you can create Trigger. The parameters you pass to this method are again similar to AddRule() method. Parameters to the AddTrigger() method are name of trigger, full name of queue, system queue identifier in this case which happens to be SYSTEM_QUEUE_NONE, flag to enable or disable trigger, flag to create serialized or nonserialized trigger which indicates to process messages in the order they arrive in a monitored queue or process it randomly, message processing type enum and finally triggerId which will be GUID. You use AttachRule() method of TriggerSet object to associate rule with trigger and use DetachRule() method to deassociate rule from trigger.

So now our final task is to fire a trigger. To do so you need to send a message to a monitored queue and it will cause the message received event to be fired in a queue. The received event of the queue will cause an associated rule to evaluate its condition to be true or false. If it evaluates to true then the trigger will be fired and triggering an action will be taken or else no action will be taken. The below code will send a message to our monitored queue to fire an event in the queue.

'Create message object to send to queue
Dim Msg As New Message() 
Msg.Label = "Test""

'Send message to queue to cause message receive event to occurre
QMsgQue.Send(Msg)

'Close message queue
QMsgQue.Close()

'You can even delete trigger when it finish job         
objTrg.DeleteTrigger(TrgID) 

'Delete rule 
objRule.Delete(ruleID)

When a message is received in a queue a triggering service will fire all the triggers associated with the queue depending on the condition specified in the rule associated with the triggers and defined action in the rule(s) will be taken.

Points of Interest

Up until now we have seen that MSMQ Triggers are such powerful objects that they can be used to interact with native .NET applications as well as unmanaged COM objects. They provide a better level of control over the customization process. With MSMQ Triggers you can take a programatic decision about creating, firing and deleting rule(s) and trigger(s). But at the same time don't forget to keep an eye on the red light, I mean care must be taken in exception handling while practicing with MSMQ Triggers because sometimes its hard to figure out the proper reason of thrown exception. It may be possible that any unhandled exception cause your triggering service to be stopped and until you come to know about that and manually restart a service again you might lose some message proccessing as well.

After all when you think about developing multitiered or distributed applications, MSMQ considers one of the richest objects for synchronous and asynchronious message processing for applications and processes communication and of course triggers add a lot more to its value by providing programmatic flexibility.

I hope this article will give you little reason to cheer about using MSMQ Triggers in your projects whenever you need to, and it prevents at least someone's life to become miserable. Please feel free to contact me If you have any query about MSMQ Triggers. I'll try my best to solve your problem.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Tejas Patel
Web Developer
India India
Tejas has been an ASP.NET,AJAX/C#.NET/VB.NET developer for about 5 years for both windows and web application. Currently, he is working on Distributed Application as a team leader in his company.He has worked with languages like C,C++,Java,PHP and databases like MySQL,Oracle,SQL Server.He especially enjoy web development.He holds a MCTS certification in web application.
 
In his free time, he likes to listen music, and hang out with friends.

Comments and Discussions

 
GeneralMSMQTriggerObjects PinmemberBob Kaye8-Mar-11 7:28 
GeneralRe: MSMQTriggerObjects PinmemberTejas Patel12-Mar-11 10:04 
GeneralRe: MSMQTriggerObjects PinmemberBob Kaye12-Mar-11 11:20 
GeneralRe: MSMQTriggerObjects Pinmemberer.Maryada11-Apr-12 2:28 
GeneralRe: MSMQTriggerObjects Pinmemberer.Maryada11-Apr-12 2:29 
GeneralEvent is not fired by trigger while rule and trigger is generated by code Pinmember31amit8-Dec-10 18:08 
GeneralRe: Event is not fired by trigger while rule and trigger is generated by code PinmemberTejas Patel27-Feb-11 9:43 
Questionhey,i have a question, hope your answer, Pinmemberf10293047-Dec-08 14:14 
GeneralQuestion on multiple conditions... PinmemberAli Jawad28-Oct-08 10:17 
Questionreceiving from triggers Pinmemberjorgenovoa14-Oct-08 9:50 
GeneralGood Article! PinmemberAli Jawad10-Oct-08 15:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140814.1 | Last Updated 16 Apr 2008
Article Copyright 2008 by Tejas Patel
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid