CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Brendan Tompkins [MVP]

Blog First. Ask Questions Later.

Windows Service Administration with ASP.NET - Part 1 - Marshalling Status Information

This is the first of a three-part blog post on how to monitor and control a .NET Windows Service from an ASP.NET page.  The general approach I've taken involves using remoting to marshal a singleton object over a tcp channel.  If you're not familiar with Singleton objects, remoting, serialization and marshalling, you may want to go figure out that stuff first, then come back here to the specifics.  I'm not an expert on these in general, so I'm not going to even try to do them justice with explanations here.  This approach does work well for me, I'm using it to monitor a service that checks for status changes on shipping containers. It looks like this:

Step 1: Add a reference to System.Runtime.Remoting to your Service project.  You also want to use the following namespaces in your .cs code:

using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.Runtime.Remoting.Channels.Tcp;

Step 2: Create a Serializable object that will be marshalled over the tcp channel. What I've done here create an object that contains the service information I want to monitor.  This class keeps information about how long the service has been running, how often it executes its checks, and an array of items that have info about each status check. It looks like this, sorta (I've simplified the code for this example).

[Serializable]
public class WatchListStatus
{
  
public
TimeSpan ExecutionInterval;
  
public
WatchListStatusItem [ ] StatusItems;
  
public
DateTime ServiceStarted;
}

[Serializable]
public class
WatchListStatusItem
{
  
public int
NumberEvents;
   public
DateTime CheckDateTime;
  
public
TimeSpan ExecutionTime;
  
public
WatchListCheckResult Result;
}

[Serializable]
public enum WatchListCheckResult
{
  
Successful,
  
FailedTimeOut,
  
FailedError
}

Step 3: Create a wrapper class that inherits from MarshalByRefObject.  This will be the remotable object. I've been calling these wrapper classes [wrapped-classname]Remotable for consistency. You can control the time-to-live for your object, by overriding the InitializeLifetimeService().  To make your object live for the life of the service process, return null here.

public class WatchListStatusRemotable : MarshalByRefObject
{
  
public
WatchListStatus ServiceStatus;
   
  
// Sets the time to live for this object. When this expires, the object will have to
   // be re-marshalled
  
public override
Object InitializeLifetimeService()
   {
    
return null
;
   }
}

Step 4: Add a private instance member object to your service class.  This is where the singleton model stuff becomes important.  You only want to have one instance of this object per service.

private
WatchListStatusRemotable m_Status;

Step 5: On - Startup of the service, marshal the object like so:

// Register the TCP Channel on port 8001
ChannelServices.RegisterChannel(new
TcpChannel(8001));

// Register the type

RemotingConfiguration.RegisterWellKnownServiceType (
        typeof
(WatchListStatusRemotable), 
        "WatchListStatus", 
        WellKnownObjectMode.Singleton);

// Now, Marshal it  this will make it available to other processes via the TCP remoting channel
try 
{
     RemotingServices.Marshal(m_Status, "WatchListStatus");
     System.Diagnostics.Trace.WriteLine("Watch List Status Marshalled");

catch
(System.Exception ex)
{
     System.Diagnostics.Trace.WriteLine(ex.Message);
     System.Diagnostics.Trace.WriteLine(ex.InnerException);
}

That's it!  You can modify the object as the service does it's thing and other processes that remote to this object will have access to this information.  All you have to do is consume it with a call to Activator.GetObject from your ASP.NET code. In part two, I'll go into the details of how I did this in my app and how to control the service.

-Brendan

Music tip: Have I mentioned British Sea Power?



Comments

Brendan Tompkins said:

Philip.

The control you see is a System.Web.UI.WebControls.DataGrid, which you can bind directly to a DataSet or View.

# March 30, 2004 12:48 AM

Philip_C said:

Thanks a lot ! I thought it was another control cause i'm starting in designing ASP.Net pages.
I'm searching tutorials to use DataList but i would like to know if i can use a DataList even if i'm not using any database as datasource. I just want to display data that i retrieve from my Windows Service as a string[][] array.
Anyway, thanks again.
# March 30, 2004 1:12 AM

Brendan Tompkins said:

Philip... There is a DataList in the System.Web.UI.WebControls namespace. You should be able to bind this to any object that implements System.Collections.IEnumerable
# March 30, 2004 1:22 AM

ahad zubair said:

good work!
# June 16, 2004 12:01 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Brendan Tompkins

Brendan has been programming with .NET since the first public beta and is owner and operator of Port Technology Services, a consultancy company providing .NET application development services to the Maritime industry. In July, 2007, he was awarded the Microsoft MVP award for ASP.NET. He's also a proud co-founder of failed .COM startup Intrinsigo, and has had a hand in the failure of numerous other businesses. He currently runs CodeBetter.Com and Devlicio.us, and lives in Norfolk, Virgina with his wife Tiara and son Ian.

View Brendan's profile on LinkedIn

Check out Devlicio.us!

Our Sponsors

This Blog

Syndication

News

MVP
Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.