I have a service that when installed puts the Myapp.exe.config file (generated based of the app.config file) into the install directory. During the install process I need details from this file to configure the install. Particularly I need to tweak the Account/Username/Password fields of my service’s ServiceProcessInstaller instance so when it runs it runs as a particular user.
However, during the install process the installer hasn’t set my registry settings yet nor copied my Myapp.exe.config to the install directory…so I have no way of pulling these values, which means my service cannot install as the correct user. The only way I can do it now is to hardcode the user/pass values into the ProjectInstaller class, but I can’t bring myself to do it this way. It’s just wrong.
Is there a Windows install best practice regarding how to install a service as a particular user and how to access those credentials during the install process.
Currently I’m trying something like:
namespace MyService
{
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
//Set the user credentials.
//NOTE: Eventually this needs to be updated to pull these values out of a
// conf file. The problem now is that the location of the conf file
// is tied to a registry entry for the location of the service which
// may or may not exist when this block is executed.
/* This is the only way I can get it to work, but this is
* too horrible to ever actually do it this way:
serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;
serviceProcessInstaller1.Username = "DOMAIN\\user";
serviceProcessInstaller1.Password = "password";
*/
// Try to pull the service's registry values to know where it installed:
RegistryKey keyService = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\services\\MyService");
string path = ((string)keyService.GetValue("ImagePath"));
path = path.Substring(1, path.LastIndexOf('\\'));
string user = someValueFromFileIOontheAbovePath1,
pass = someValueFromFileIOontheAbovePath2;
serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.User;
serviceProcessInstaller1.Username = user;
serviceProcessInstaller1.Password = pass;
//Doesn't work because install isn't complete and there aren't reg settings
// yet, and even if I had the path the .config file is not written yet so
// there's no file to parse.
}
}
}
Some .config file that holds these parameters:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="User" value="DOMAIN\bob"/>
<add key="Password" value="secret"/>
</appSettings>
</configuration>
How can I pull these user/pass values during install without resorting to hardcoding them into the binary?
Thanks.
One way to accomplish what you want with the MSI is to use a Custom Action on the Commit to run your custom object installer. Commit Actions are run after the files have been copied, so the files will exist in the installation directory your user has chosen.