Thursday, November 11, 2004

Blogging on Demand #4

This search recently piqued my interest. Not only is it something that's quite interesting, it's also something that, although I've used it a couple of times,I haven't really explored it very much.

"Me.ServiceProcessInstaller1.UserName" (via Google)

The ServiceProcessInstaller works in conjunction with the ServiceInstaller in providing information for, and interacting with Windows' own service installation utility, InstallUtil.exe, for (as the name suggests) installing a service.

These classes should be included whenever you have a service that you want installed (again, the name says it all, really...). Visual Studio and the .NET framework make building Windows Services very easy. Although I haven't got any experience of doing it in the past, I hear services were tricky, to say the least! All you need to do in Visual Studio to create a service is select Add-->Windows Service in the solution explorer. Very Easy . Unfortunately, by default, when you go to install your service using InstallUtil, the compiled executable doesn't have all the information that Windows needs to install it as a service.

The ServiceProcessInstaller is where you set things like the Account Type that the service is going to run under (Whether it's the System Account, User Account etc.). More often than not, you'll be setting the Account property of the ServiceProcessInstaller to ServiceAccount.LocalSystem. The reason for this is that more often than not, you'll be building an application that needs a high privilege to be able to do the things you want (if you've got a service that monitors a folder, for instance, you'll want to make sure your service has access to that folder.

Just a quick note on security (Feel free to skip this paragraph, I'm more thinking out loud than I speaking from actual experience). The best practice is to run your code with the least amount of privilege possible. If you've got a process that needs a certain resource, give it access to that resource AND NOTHING ELSE. You might want to do this by setting up a new user (Ever noticed the ASPNET User account that gets set up when you install the .NET framework?That's what this is). You can also do it by putting together a security policy and deploying it to your machines. This does, however, mean extra stuff that needs to be done at installation, and it can only be done from an account with admin rights on the machine. LocalSystem, while it doesn't really follow best practices, and it does leave your system open to buggering about (Not necessarily malicious buggering about, it could just as easily be just a bit of flaky code. We've all written some of that!), is at least the easiest option when it comes to deployment. I can see from my machine, for example, that all but 2 of the services running on my machine run under the LocalSystem account.

If you do choose to run your services under a User account, the ServiceProcessInstaller is where you might want to specify your username and password. You don't have to put it there, but you may like to. If you don't specify it in there, you will be prompted for it when you go to install each service. I guess the most common need for that would be in a corporate environment where you have a user account set up on all your machines for running a particular service, and don't want to share those credentials with your users.

That's about it for the ServiceProcessInstaller class.

One of the things the ServiceProcessInstaller class does, though, is work with the ServiceInstalller class to get them... Well... Installed. Since you can have an exe that contains a number of services, you need a separate ServiceInstaller for each service within it. The serviceInstaller is where you can specify things like the name that's displayed in the Service Manager console, the Start behavior and things like that. The key properties of note are:

StartType - This can be one of 3 values 'Automatic', 'Manual', and 'Disabled'. You're not likely to use disabled much (I can't think of a situation that would warrant it, anyway...). Automatic means the service will be started up when Windows is fired up. Manual means it won't be started up when the OS starts up, but you can still start it manually either via the Service Manager, or by using a ServiceController in code.
Disabled, as the name suggests, means you can't start it, no matter what. See what I mean about using it when you write a service?

ServiceName - This is, as the name suggests, the name of your service. This needs to be the same name as the ServiceName specified in your code.

DisplayName - This is the friendly, fluffy name you want to appear in the Service Manager. For example, the ASP.NET State Server is actually called 'asp_state'. 'ASP.NET State Server' is it's DisplayName. You don't have to have friendly names, either. SQL Server's service is called 'MSSQLSERVER' (Imaginative, eh?) and it's DisplayName is also 'MSSQLSERVER'.

The ServiceInstaller supports transactions too. It's clever like that. If something goes wrong as it installs a service, it rolls back the whole installation and leaves your computer as if it had never even heard of your service.

By and large, I haven't played about too much in the code behind these classes. Visual Studio has quite a handy little tool that automatically creates ServiceProcessInstallers and ServiceInstaller for you. If you open your service in the designer, and select the service on the design surface, there'll be a handy little linkbutton there that says something along the lines of 'Create an Installer'. Click it, and you'll see your ServiceProcessInstaller and ServiceInstaller magically appear in the designer. You can just go through and change the properties you want to change and Bob's yer uncle. You'll have to go through and do this for each service you've written, but the widget is big enough and clever enough to produce one ServiceProcessInstaller for the executable, and a ServiceController for each service. Clever, eh?

There are a whole host of other things that you can do with ServiceProcessInstaller and ServiceInstallers. These are just the main bits I've used.

It's worth noting, however, that all your service's properties can be changed through the service manager as well. You want to go in and run your service under a User account, no problem, just open up the Service Manager console, and change away. These 2 classes only do their work at the point of installing your service.

If I've missed anything major, let me know. If there's anything wrong, then let me know. Hey, if you know something you didn't know before you read it, then still let me know. Some of this stuff I already knew when I set out, and some of it I learnt on the way whilst writing this post. So it's done it's job, I guess.

No comments: