Solved

MSMQ and Windows Service

Posted on 2004-09-02
9
587 Views
Last Modified: 2012-09-05
- Experts -
I have a requirement to write a windows service applictaion in C# that listens on a local message queue  for new messages and performs certain transactions based on the message label.
Can anyone provide me with sample working code in C# or VB.NET .;
0
Comment
Question by:bmukoro
  • 7
9 Comments
 
LVL 4

Expert Comment

by:jrandallsexton
ID: 11963330
bmukoro:

This will be quite the post if I were to give you code for the service, the queue that the service instantiates, and then the other code to actually send the message.

I'll give you the guts to each of those portions, but you're going to need to do some reading.  I just finished a project doing exactly this - and it's no small task in figuring it all out.  

However, I have a template of sorts and will post it in pieces for you.

I will start with an example of the service.
0
 
LVL 4

Accepted Solution

by:
jrandallsexton earned 400 total points
ID: 11963382
This is the code for the service.  In order to use it, you'll need to create a "helper" form.  It is difficult to debug a service, so it is adviseable to get everything going in a standard class first, then cut and paste the code into a Windows Service application.

The ServiceDebug class represents the Windows Service.  The only thing it does is expose 2 methods: Start & Stop.  Start happens when the service starts, and conversely Stop occurs when the service stops.
When you instantiate ServiceDebug, you'll notice that the "Service" instantiates a QueueClass.  This is where our "listening" will occur - where we will receive our messages.  That part will be posted next.

Imports System
Imports System.Messaging
Imports Microsoft.ApplicationBlocks.ExceptionManagement 'Exception logging

'Project Imports
Imports WSvc.Queue
Imports WSvc.DataObjects

Public Class ServiceDebug
    Private _serviceQueue As WSvc.Queue

    Sub New()
        MyBase.new()
        Console.WriteLine(Me.GetType.ToString & ": Service Invoked")
        Start()
    End Sub

    Public Sub Start()
        Try

            Log(True, False, False)

            Console.WriteLine(Me.GetType.ToString & ": ServiceDebug instantiated.")
            Console.WriteLine(Me.GetType.ToString & ": Instantiating ServiceQueue...")

            Me._serviceQueue = New WSvc.Queue

            Console.WriteLine(Me.GetType.ToString & ": ServiceQueue should now be instantiated.")

        Catch ex As Exception
            ExceptionManager.Publish(ex)
        End Try
    End Sub

    Public Sub [Stop]()
        Try
            Me._serviceQueue = Nothing
            Log(False, True, False)
        Catch ex As Exception
            ExceptionManager.Publish(ex)
        End Try
    End Sub

    Private Sub Log(ByVal isStarting As Boolean, ByVal isStopping As Boolean, ByVal isRunning As Boolean)
        Try

            Dim MyLog As New EventLog   ' create a new event log

            ' Check if the the Event Log Exists
            If Not MyLog.SourceExists("WinService") Then
                MyLog.CreateEventSource("WinService", "WinService Log") ' Create Log
            End If

            MyLog.Source = "AlertService"

            ' Write to the Log
            If isStarting Then
                MyLog.WriteEntry("WinService Log", "WinService started at: " & CStr(TimeOfDay), EventLogEntryType.Information)
            ElseIf isStopping Then
                MyLog.WriteEntry("WinService Log", "WinService stopped at:  " & CStr(TimeOfDay), EventLogEntryType.Information)
            Else
                MyLog.WriteEntry("WinService Log", "WinService running at:  " & CStr(TimeOfDay), EventLogEntryType.Information)
            End If

        Catch ex As Exception
            ExceptionManager.Publish(ex)
        End Try
    End Sub

End Class
0
 
LVL 4

Expert Comment

by:jrandallsexton
ID: 11963439
Imports System.Messaging
Imports System.Reflection
Imports System.Xml

Imports WSvc.DataObjects
Imports WSvc.QueueArgs
Imports WSvc.DALC

Imports Microsoft.ApplicationBlocks.ExceptionManagement

Public Class Queue

    Private _strQueuePath As String
    Private _newMessageQueue As MessageQueue
    Private _theIncomingData As SvcDataObject
    Private _queueArg As QueueArg

    ' Define static class members for Messaging
    Private Shared signal As New ManualResetEvent(False)
    Private Shared count As Integer = 0

    Public Sub New()

        MyBase.new()

        Try

            'get the queue's path from the xml/configuration file
            _strQueuePath = ".\Private$\SvcQueue"

            'does the queue already exist ? ...
            If (Not MessageQueue.Exists(Me._strQueuePath)) Then

                ' ... no, it doesn't.  Create it.
                MessageQueue.Create(Me._strQueuePath)

            Else

                ' ... yes, it does.
                Me._newMessageQueue = New MessageQueue(Me._strQueuePath)
                Me._newMessageQueue.Formatter = New XmlMessageFormatter(New Type() {GetType(WSvc.DataObjects.SvcDataObject)})

                ' Add an event handler for the ReceiveCompleted event ...
                AddHandler Me._newMessageQueue.ReceiveCompleted, AddressOf Me.ServiceDataObjectArrived

                ' ... start waiting for a message
                Me._newMessageQueue.BeginReceive()

            End If

        Catch ex As Exception
            ExceptionManager.Publish(ex)
        End Try

    End Sub

    Private Sub ServiceDataObjectArrived(ByVal [source] As _
        [Object], ByVal asyncReceived As ReceiveCompletedEventArgs)

        '=====================================================================
        ' PURPOSE: Handles the ReceiveCompleted event which the service queue raises
        '               when a message arrives
        ' ACCEPTS: The object which arrived via the queue
        '=====================================================================

        Dim theResponse As MessageQueue
        Dim theMessage As System.Messaging.Message

        Try

            Console.WriteLine("A ServiceDataObject has been found in queue ...")

            ' Connect to the queue.
            theResponse = CType([source], MessageQueue)

            ' End the asynchronous receive operation.
            theMessage = theResponse.EndReceive(asyncReceived.AsyncResult)
            theMessage.Formatter = New XmlMessageFormatter(New Type() {GetType(WSvc.DataObjects.SvcDataObject)})

            count += 1
            If count = 10 Then
                signal.Set()
            End If

            Console.WriteLine("Getting the ServiceDataObject from the message queue ...")

            'Get the object
            Dim theDataObject As SvcDataObject = CType(theMessage.Body, WSvc.DataObjects.SvcDataObject)

            Debug.WriteLine("... ServiceDataObject loaded from queue.")

            'Assign the object to the private member variable for the ServiceQueue
            Me._theIncomingData = theDataObject

            'HERE'S WHERE YOU CAN CHECK THE Message Label
            If (theMessage.Label.Length > 0) Then
                Console.WriteLine("Label found")
            End If

Here, do whatever it is that you need to do.

        Catch ex As MessageQueueException
            ' Handle sources of MessageQueueException.

        Catch ex As Exception
            ' Handle other exceptions.
            ExceptionManager.Publish(ex)
        Finally
            ' Restart the asynchronous receive operation.
            theResponse.BeginReceive()
        End Try

        Return
    End Sub 'ServiceDataObjectArrived
0
 
LVL 4

Expert Comment

by:jrandallsexton
ID: 11963568
And, here's the ServiceDataObject class.  This is simply the class object that the ServiceQueue is expecting.

Public Class SvcDataObject

    Private _Name As String
    Private _Data As ArrayList

    Sub New()
        MyBase.new()
    End Sub

    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal Value As String)
            _Name = Value
        End Set
    End Property

    Public Property Data() As ArrayList
        Get
            Return _Data
        End Get
        Set(ByVal Value As ArrayList)
            _Data = Value
        End Set
    End Property

End Class
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 4

Expert Comment

by:jrandallsexton
ID: 11963620
Ok, now that you have all of the pieces....

I'm going to post a few links for you.

The rest you REALLY need to figure out on your own.

I suggest truly learning this as MSMQ is a very reliable means of doing many things - not just sending "mesages".

Accessing Message Queues
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdadotnetasync1.asp

VB.NET Makes Windows Services a Breeze
http://www.informit.com/articles/article.asp?p=29838&redir=1

Developing Windows Services
http://www.ondotnet.com/pub/a/dotnet/2003/08/18/winservices.html

Programming MSMQ in .NET - Part 1
http://www.codeproject.com/dotnet/MGRMSMQ.asp
0
 

Author Comment

by:bmukoro
ID: 11965672
Thank for your post, I guess I was not very clear..

I know how to use MSMQ and also to receive messages asynchronously, I simply want to be able to receive messages asynchronously using a windows service application (c#) instead of a console application for obvious reasons..

I will award you the points, for you post primarily because your post as highlighted the fact that I was on the right path...but my service just would not started.

and I will post a new question specific to my problem..

Thanks again
0
 
LVL 4

Expert Comment

by:jrandallsexton
ID: 11965695
So you give me a "B" all because your requirements weren't clear?

That's pretty shabby of you.
0
 
LVL 4

Expert Comment

by:jrandallsexton
ID: 11965712
Are you looking for instructions on how to create a service then?  Or do you already have the service and need to know how to install it.

Judging from what you stated originally, you didn't state explicitly that you knew how to do any of it.

0
 

Expert Comment

by:petel2k
ID: 38369871
Hey jrandal.. I'll give you an A++++ if you can help. Using the listener, I want to respond to a message, however there are many messages that need processing at once. The last thing I want to do is read the first, process it, read the 2nd, process it.. (processing is identicle in each case, the message has an axccount number and I want to do some processing and write it to a table< -- don't need help with processing, just wanted to give you some insight.)

In effect, I need to launch an instance of the process with an account number the moment the message is noticed. In other words many of these processes need to happen at the same time. What is the best method to writing a service as such? And how do I ensure no more than 1,000 of these processes are going on at one time to avoid memory overflow?

Thanks
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now