Tuesday, August 5, 2008

InstallShield and LogonAsService Right

I was somewhat perplexed by this one. I am installing a Windows NT Service (don't let the "NT" bother you, that is just the OS when services where introduced or something like that). I have configured the service in my components. I filled out the properties for NT Services and set properties for the user and password. Then I use the user dialog I mentioned in previous posts to get the user credentials for the service. This dialog can create a new user for this, which is typically the case for my project.
However, the installed service doesn't start. Instead I get an error that the service can't be started with the message being "Error 1069: The service did not start due to a logon failure." I went into the properties to the Log On tab to check things. The password is obscured, so I retyped it in and clicked Apply. Then I get the message "The account has been granted the Log On As A Service right." After that, the service works.
This is what I learned. Users, especially domain users, don't have this right typically. I am guessing that since the new user is specified in the format "DOMAIN\USER" it is considered a domain user even if the domain is the local system. The localsystem user already has this right granted to it.
For some reason, MSI or InstallShield doesn't allow you to grant this right when the user is created. There are some posts on the InstallShield forums that say this. There is also mention of the answer.
The answer is calling the utility NTRIGHTS.EXE. This is the Windows command-line utility for administrating rights for users. So, first you need to acquire the utility. It comes from the Windows Resource Kit. It is not installed as part of Windows, so you will need to download it and install it. After that, you have the utility. Next it needs to be included in your InstallShield project. I copied the utility for a folder where I have my support files (I have all my files together for easy source-control). I then added it to my support files inside my project as a language independent file. Then I run it using LaunchAppAndWait.

szProgName = SUPPORTDIR^"ntrights.exe";
szProgParams = " -u" + szUserName + " +r SeServiceLogonRight";
StatusBox("Executing '" + szProgName + szProgParams + "'", DEBUG);
if (LaunchAppAndWait(szProgName, szProgParams, WAIT) <>
MessageBox("Unable to launch " + szProgName + ". Retype the password for the the user in the workflow service properties.", WARNING);
endif;

BTW, I call it from a later event in my InstallScript, specifically OnFirstUIAfter. That may not be the best as it would also need to be in OnMaintUIAfter, but this is a first cut and I haven't got all the maintenance mode worked out yet. Also, I put the call in a function so that I can call it from wherever it needs. The point is that it needs to called AFTER the user is created which is after InstallShield's "Do Stuff" phase.
Problem Solved.

3 comments:

Anonymous said...

Thank you! I had the same problem and this helped greatly. (I just called the ntrights.exe from a custom action though)

Anonymous said...

Thanks a lot for sharing this.
Inspired by your task I found:
http://articles.techrepublic.com.com/5100-10878_11-5032903.html

An in depth look at NTRIGHTS.

Anonymous said...

SeDebugPrivilege is not mentioned in the above article but it works too