InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

Developing Windows Services with .NET

Developing Windows services with .NET is not always easy – sure, one can attach a debugger once the service is started (at least when developing on Windows XP / 2003). But this is not exactly an ‘F5’ experience one has with normal programs or even Websites. Another drawback of the “Attach to process” method is that the start of the service cannot be debugged. A common way to circumvent this is to write a System.Diagnostics.Debugger.Break statement within the first lines. This will bring up the Just-In-Time Debugger window that let’s you choose a debugger. Sadly, this does not work any more with Windows Vista / 2008 because services run on an isolated window station.

Luckily, there is a solution: A windows service is nothing more than a console application that is started slightly differently. One can take advantage of this by starting the service as a stand-alone program when started normally (via F5 or starting the service from the command line). But if the program detects if it is started by the Service Control manager, run it as a service. So, how can a program check whether it is started by the Service control manager? It depends on the user account the program runs under. If it’s running as “LocalSystem”, one can safely assume it’s running as a service. In any other case, the user account token has a special group membership: The System.Security.Principal.WellknownSidType.Service.

The default body of a program.cs file of blank service solution looks like this:

   1: using System.ServiceProcess;
   2:  
   3: namespace WindowsService1
   4: {
   5:     static class Program
   6:     {
   7:         /// <summary>
   8:         /// The main entry point for the application.
   9:         /// </summary>
  10:         static void Main()
  11:         {
  12:             var servicesToRun = new ServiceBase[] 
  13:                                               { 
  14:                                                   new Service1() 
  15:                                               };
  16:             ServiceBase.Run(servicesToRun);
  17:         }
  18:     }
  19: }

With a few additional lines, a comfortable F5 experience can be gained:

   1: using System;
   2: using System.Linq;
   3: using System.Security.Principal;
   4: using System.ServiceProcess;
   5:  
   6: namespace WindowsService1
   7: {
   8:     static class Program
   9:     {
  10:         /// <summary>
  11:         /// The main entry point for the application.
  12:         /// </summary>
  13:         static void Main()
  14:         {
  15:             var identity = WindowsIdentity.GetCurrent();
  16:             var principal = new WindowsPrincipal(identity);
  17:             // Check whether the current user account is the LocalSystem account
  18:             var isLocalSystemUser = 
  19:                 identity.User == new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
  20:  
  21:             if (isLocalSystemUser || principal.IsInRole(new SecurityIdentifier(WellKnownSidType.ServiceSid, null)))
  22:             {
  23:                 var servicesToRun = new ServiceBase[]
  24:                                         {
  25:                                             new Service1()
  26:                                         };
  27:                 ServiceBase.Run(servicesToRun);
  28:             }
  29:             else
  30:             {
  31:                 var service = new Service1();
  32:                 service.StartAsApplication();
  33:             }
  34:         }
  35:  
  36:     }
  37: }

I have added a StartAsApplication() method to the Service1 class, because the OnStart() method of the default service template is protected and therefore not accessible. And that is all there is. The service can now be started by just pressing F5.

Drawbacks

The gain of the F5 experience does not come without a cost – normally, a Windows service runs under a special account (which is hopefully not LocalSystem): NetworkService, LocalService or a dedicated service account. With this approach, the service runs with the permissions of the currently logged on user. Normally, that user account has far more security permissions than the service account would have. For example, the current user might have the permission to host WCF services on arbitrary ports – something only administrators are allowed to do. A service account would need explicit permission to host that service. Another example are private keys of certificates in the LocalComputer store – not accessible for the NetworkService account by default. But if a service needs to access those keys, it won’t fail unless during development. This should be kept in mind.!


Posted by Henning Krause on Saturday, June 13, 2009 12:26 PM, last modified on Monday, November 29, 2010 7:30 PM
Permalink | Post RSSRSS comment feed

Regain access to blocked atachments in Outlook XP

Affected products

  • Microsoft Outlook XP
  • Microsoft Outlook 2003

Summary

This article describes how Outlook XP can be configured, so that it no longer blocks access to attachments certain file types such as .exe.

Description

Since Outlook 200 SP 2, outlook blocks access to attachment of certain file type such as executables or scripts.
There are two types of blocks: The level one files are completely blocked, so that no access is possible, albeit they are not deleted by Outlook. The level 2 files are blocked in that way, that the user can not open them directly. They must be saved to disk before an access is possible.
Outlook XP can now be configured so that level one filetypes can be transformed to level two files..

SOLUTION

To change the behavior of Outlook, the following steps are necessary:
  1. Open the registry editor.
  2. If you are using Outlook XP, navigate to the key HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\10.0\Outlook\Security.Under Outlook 2003, navigate to the key HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\11.0\Outlook\Security.
  3. Create a new value of type String named Level1Remove.
  4. Open the value and enter a semicolon separated list. For example:
    .exe;.ppt;.url;
    After Outlook has been restarted, the access to the attachments is no longer blocked.

Status

This behavior is by design.

Posted by Henning Krause on Friday, December 31, 2004 2:09 PM, last modified on Friday, December 31, 2004 2:27 PM
Permalink | Post RSSRSS comment feed