ISWIX, LLC View Christopher Painter's profile on LinkedIn profile for Christopher Painter at Stack Overflow, Q&A for professional and enthusiast programmers

September 22, 2008

Different year, Same Problem...

5 years ago I was working at Continental Airlines learning MSI with Windows Installer 2.0. One of the biggest pain points was troubleshooting why services wouldn't start. Some programs just had horrible COM/ATL issues relating to COM extraction not working and /regsvr having race problems.

One of the more aggravating scenarios was for a program called Gate Reader that had a windows service with a dependency on a active directory service account.

Inevitably one of two things would go wrong: Either someone had locked the account out ( and no installs would work for up to the next 15 minutes ) or the service account had never been assigned the SeServiceLogonRight priv on the machine being installed to.

Now we can talk about eliminating the dependency by eliminating the service account but at the end of the day development typically doesn't give a flying brown mass about deployment/operational problems.

So it's the later that always irritated me. Why in the world is it that Windows Installer has columns in the ServiceInstall table for describing a service account but when it creates the service it doesnt' grant the SeServiceLogonRight priviledge?

A quick hop over to Services and type in the username and password gets you a dialog that says the account has been granted logon as service.

I know I'm not the only one to have this problem because there are many threads where setup developers suggest using the not-quite-redistributable NTRIGHTS.EXE to get around the problem.

So anyways, it's now 2008 and I'm running MSI 4.5 and sure enough, it's still a problem. Ugh. The good thing is I've since learned C# ( Gatereader was a .NET 1.1 application at the time ) and I've got DTF at my disposal. This allows me to make use of a project that was available on CodeProject some five years ago that at the time meant nothing to me:

LsaUtility.SetRight( session.CustomActionData["ServiceAccount"], "SeServiceLogonRight" );

Nice, thank you DTF! Now my real implementation is datadriven using the ServiceInstall table but I wanted to show how simple the problem is to solve with just one line of C# thanks to a freely available class file and DTF.

So while some things stay the same, some things actually do get better.


Matthew Rowan said...

The WiX User element has the attribute LogonAsService="yes". This seemed to resolved the issues I was having that you described. But as you said, it is still not msi native, but if using WiX it is simpler than using your own custom action.

Christopher Painter said...

I've seen that, but I'm not using WiX proper, only DTF upstream to build DLL's for consumption with InstallShield.

BTW, I also saw a post on WiX-Users archives from Rob stating that services aren't given permissions, users are.

I think that's a straw man's argument. In theory, that is true but MSI doesn't have a Users table and the ServiceInstall table doesn't have a foreign key join to. The ServiceInstall table specifically has the columns StartName and Password so since it's impossible to start a service with an an account that doesn't have the priv, then MSI should be assigning the priv to the account when the service is created.\

If MSI did have a User table ( and others ) then I would agree that it would be a foreign key join and some other standard action responsible for creating/modifying users would have the responsibility of having an attribute for defining which privs should be assigned to the user.

So WiX looks good, but it's a shame that once again the MSI team is asleep at the wheel depending on Tools groups to do things that should be in MSI proper.