.NET Programmer Thoughts

Thursday, February 17, 2005

Book Review: Pro ADO.NET with VB.NET 1.1

I had a very narrow vision of what ADO.NET was until I read Pro ADO.NET with VB.NET 1.1. ADO.NET is more than just DataSets and DataAdapters. It also involves XML, Data Services and Web Services. This book covers it all and more!

All the basics are covered. Chapters 1 through 5 explain Data Readers, DataSets (Typed and UnTyped) , Data Adapters and Data Schemas. I was impressed with the depth covered on each of these subjects.

What I didn't expect was the XML coverage. Chapter 6 covers everything you need to know about XML and how to use XML with DataSets.

Chapters 7 through 9 explain Constraints, Relations, Views, Transactions, and Mapping.

Data Services and Web Services each had full chapter. This was an unexpected bonus.

Performance and Security is covered by including optimizing, connection pooling message queuing, and basic security concerns. I always wondered what MSMQ was and now I know!

Also covered where InterOp and Migration from ADO.

The last chapter walks you through creating a MSMQ custom data provider. Very cool!

This book will make a fantastic resource book. This is definitely a must have for any level programmer!

Tuesday, February 08, 2005

More on Windows Services

I found a problem. My service was supposed to monitor an process (DBMSAutoRecover.exe) and make sure that it was always running. If it found it wasn't running, then it was supposed to start it. If it couldn't start it, then it would send an email.

Here's the problem. The process I was monitoring has a user interface. So when the service started it, you couldn't see it! So I did some searching and found out that I could go to my service (DBMSWatcher.exe) and right click on it and go to the properties window. Then on the Log On tab, check the box "Allow service to interact with desktop". When I restarted the service and the server launched DBMSAutoRecover, you could see it! But it was running under a SYSTEM account.

Now, let me complicate things even more. DBMSAutoRecover monitors another application named DBMS. DBMS is an access application that does all kinds of things. Once of which is monitor an Inbox for email. Well, if DBMSAutoRecover is running under a SYSTEM account and then has to start DBMS then DBMS is running under a SYSTEM account. When it's running as a system account, it doesn't seem to be able to connect to that Inbox.

So then I noticed that I could have the server start as a specific user. Cool! Then everything would work. But when I did that I lost the option of allowing the service to interact with the desktop. Not so cool!

So I gave up and my service will just send an email if it finds that DBMSAutoRecover isn't running.

Also I read tons of stuff about how it's not safe to allow a service to interact with the desktop. A SYSTEM account as full privileges on the machine. Then you have a user interface that has full access to the machine. No so good.

Sunday, February 06, 2005

Using a Timer In A Windows Service

I've created my first windows service in .NET! It was so easy! The hard part was getting the timer to work!

My service is named DBMSWatcher. All it does is check to make sure that a program (process) is running. If it isn't, it tries to start it and if it can't restart it, it will send an email to someone to let them know it's not running. During this time the application log is also being updated.

The first thing you have to do is create a Windows Service project. Just like you would create a windows forms project, locate the Windows Service template. It's that simple!

Most examples on the net will tell you just to add a timer control from the toolbar. Well, that isn't going to work. Using a System.Timers.Timer won't work either. At least it didn't for me. I had to use a System.Threading.Timer. Switch to the code view and you will see override methods for OnStart and OnStop.

Sorry, the code is in VB.NET again. There are lots of sources on the net to explain about to create a windows service. The key here is just to let you know the toolbar timer isn't going to work. And I couldn't get the System.Timers.Timer to work. The only way I could get a timer to work was to use the System.Threading.Timer.

Create a Private timer.

Private oTimer As System.Threading.Timer

In the OnStart method, type the following code.

Dim oCallback as New TimerCallback(AddressOf OnTimedEvent)
oTimer = New System.Threading.Timer(oCallback, Nothing, 60000, 60000)


Then create a method for the OnTimedEvent as follows.

Private Sub OnTimedEvent(ByVal state As Object)

Dim myLog As New EventLog
If Not myLog.SourceExists("DBMSWatcher") Then

myLog.CreateEventSource("DBMSWatcher", "DBMSWatcher Log")

End If
myLog.Source = "DBMSWatcher"
myLog.WriteEntry("Something Happened!", EventLogEntryType.Information)

EndSub


INSTALLING A WINDOWS SERVICE

Now look how easy it is to install the service. Go to the design windows and right click on it. Select Add Installer. It will add an installer project with two controls. ServiceProcessInstaller1 and ServiceInstaller1. Select the ServiceInstaller1 control and open the property window. Change the "ServiceName" and the "DisplayName" to what ever you want your service called. Select the ServiceProcessInstaller1 control and change the Account property to "LocalSystem".

Now build the application and create an executable.

To install the service you nned to use the InstallUtil program. You can find it in c:\windows\microsoft.net\framework\v.x.x.xxxx\. If you go to the VS .NET command prompt you will be pathed to the folder. (To get to the command prompt, select Start -> Microsoft Visual Studio .NET -> Visual Studio .NET Tools -> Visual Stuido .NET Command Prompt)

Type in the follow command in the command window.

InstallUtil "c:\program dir\DBMSWatcher.exe"

Now you need to start the service. Open the control panel and open the Administrative Tools. Click on Services, and locate your service. Right click on it and select Start to start it.

When you need to install a new version you have to stop the service and then uninstall it. Type in the following to uninstall a service.

InstallUtil /u "c:\program dir\DBMSWatcher.exe"

DEBUGGING A WINDOWS SERVICE

First you have to start your service. In the VS .NET IDE go to Debug -> Processes. Find DBMSWatcher.exe and attach the debugger. Then you will be able to set your breakpoints as usual. If you want to debug the OnStart procedure you need to place a "Stop" in the code