I was trying to install the GDNet service processes on the backend server. Every service process needs its own user account - it makes security, auditing, and SQL Server access a lot neater. Normally when you install a service process that uses a user account, you get prompted for the username and password of the account the service should use. I want the installs to be unattended, so I hardcoded the usernames and passwords into each service process:
[RunInstaller(true)] public class RendererServiceInstaller : System.Management.Instrumentation.DefaultManagementInstaller { public RendererServiceInstaller() { var process = new ServiceProcessInstaller { Account = ServiceAccount.User, Username="GDNET\v5_render", Password = "xxxxxxxxxxxxxxxxxx" }; var service = new ServiceInstaller { DisplayName = "GDNet V5 Rendering Service", Description = "Service that renders GDNet XML into XHTML for output to users.", ServiceName = "V5Renderer" }; Installers.Add(process); Installers.Add(service); var evtLog = new EventLogInstaller {Source=RendererService.EventLogSourceName, Log="GDNet" }; Installers.Add(evtLog); } }
When I tried running InstallUtil to install the service, though, I got this error:
System.ComponentModel.Win32Exception: No mapping between account names and security IDs was done
I'd granted the accounts in question the 'Log on as a service' and 'Log on locally' rights, I could start processes as them by hand over remote desktop, so what was the problem?
Look at the username I'm using: it's a domain account, so it's in the form DOMAIN\accountname. Look at what's separating those two components. It's a backslash. Backslashes are special in C# (and many other languages). As far as the compiler was concerned, the account name wasn't 'GDNET\v5_render', it was 'GDNET', then a vertical tab, then "5_render".
Sticking an @ on the front of the username string has fixed it.