Windows service installer not reading App.Config file - c#

I have added App.Config in my project.
I have a installer class(ProjectInstaller.cs) which needs to read values from App.config.
I am providing the keys .
Below is the sample Code :
ConfigurationManager.AppSettings["CONFIG_FILE"]
I am getting null values as per above code ,when invoked in Installer class.
But in App.Config file the value for the above key exists.

Try:
public string GetServiceNameAppConfig(string serviceName)
{
var config = ConfigurationManager.OpenExeConfiguration(Assembly.GetAssembly(typeof(MyServiceInstaller)).Location);
return config.AppSettings.Settings[serviceName].Value;
}

Google helps: http://social.msdn.microsoft.com/Forums/ar/winformssetup/thread/896e110e-692d-4934-b120-ecc99b01c562
the point is that your installer is NOT running as exe alone and an app.config called whatever you imagine will not be loaded by default as the exe running your installer is InstallUtil.exe and it would eventually search appSettings from the file InstallUtil.exe.config which is not yours and is not what you want, read the following and check the links...
If you invoke it through InstallUtil then the configuration file is
defined as InstallUtil.exe.config which is not what you want. You
could manually load the config file using Configuration but it will
probably be a little messy
The trick is in the execution context of the installer classes. If you
install your app using InstallUtil all code will be executed in the
same process as InstallUtil.exe. If you need to pass some data to the
Installer class during deployment you should use install parameters.
They are passed to the installer during execution of Install, Commit,
Rollback and Uninstall methods by the execution enviroment
(installutil, windows instller...). You can access there parameters
using InstallContex property ot the installer class.
There is a excellent artiicle on CodeProject regarding Setup projects
and parameters:
http://www.codeproject.com/dotnet/SetupAndDeployment.asp
Check out
http://msdn2.microsoft.com/en-us/library/system.configuration.install.installcontext.aspx

Davide Piras explained very well, why you can't use your app.config and suggests to pass your values as parameters.
I found a nice and helpful article on how to pass parameters to the installutil.exe and use them in the serviceInstaller or projectInstaller:
Part 1: Using Parameters with InstallUtil
Part 2: Configuring Windows Services with Parameters from InstallUtil
It explains very shortly how to pass arguments and how to read them.

For me the easiest solution was to create InstallUtil.exe.config file, and fill it up with content from application config file. Service installer successfully read from this config file.
I created my service by following steps described in: Host a WCF Service in a Managed Windows Service

Related

How to allow for editable .Net generated config files with MSIX?

I am trying to help port a .Net service to a more modern .Net version (possibly Core) and use the MSIX installer. The application has several configuration files generated by the compiler (in source they are app.config but compiled they become *.exe.xml), they are installed into Program File right next to the binaries and a GUI helper app as well and the application itself can modify them to change service behavior (port, ip, tls cert, etc).
Writes under C:\Program Files\WindowsApps\package_name are not allowed.Writes under C:\Program Files\WindowsApps\package_name are not allowed.
The problem I am facing is that the MSIX installer makes it so that files in it's sandboxed version of Program Files cannot be written to (see above). That means that this application cannot be configured, so I am trying to figure out not only how to make the app configurable again, but also how windows wants to handle app configuration.
Right now it seems like there is two general approaches to do this:
write the configuration data to the service account's AppData/local folder
try to mimic a /etc/Myservice behavior in another folder. (meaning a local system-wide directory that houses configuration data for the service)
If you suggest #1 please answer the following additional questions:
How would I move Application configuration files to a user configuration file directory
how can an admin with a normal account modify the config file in the Service Account's AppData folder with the mentioned GUI helper application? (do they need to enable desktop access to the service account, login and run the GUI)?
If you suggest #2:
Where would you suggest this directory exist (specifically where will MSIX allow it)?
How do I tell the .Net application that the files are not right next to it? Can I just use AppData.CurrentDomain.SetData?
Well, a service running on the system account is the same for all users, so I would say that CommonApplicationData is a better folder for storing its settings, instead of appdata. This folder is easily accessible to both your service and to any admin that needs to deploy a custom config file.
In AppData you should store only actual user files (like files or settings generated by the actions taken inside your app by a specific user - thus different files for different users).
Now, the second part is where you need to configure you code to load the config file from a custom path instead of looking for it next to the EXE. I am no .NET expert but after a quick search I found this:
Relocating app.config file to a custom path
The modern approach to deploying app customizations
What is not clear to me is how your customers use the GUI helper tool to customize the config file. Is this just a tool that is used by someone from the IT department to generate the config file, and then they would copy that file and deploy it to the end-user machines using an MSI/MST file (or through some other custom deployment method)?
If your application is only deployed by IT folks, then you can try another simpler (and much elegant) solution for providing it with a custom config file, which actually doesn't require any code changes.
You can still leave the config file next to the EXE, in ProgramFiles and instruct the IT teams that deploy the app to use an MSIX Modification Package to deploy the custom config file generated by your GUI helper. (check the link included above for an example - with a video version at the end of the article).
Note: IT teams can use multiple free or paid tools to generate MSIX Modifications Packages.
Of course, your GUI helper tool still needs to generate that customized config file in a folder where it is allowed, as it can no longer write under ProgramFiles. So actually, you do need to modify a little bit your code in this scenario too.

Deploy on premise web app with transformed release configs

We are in the process of setting up our release definitions to finally finish the last piece of our CD/CI setup in VSTS and are running into an issue where we are unable to transform our configs.
Currently we are following Scott Hanselman's approach of keeping connection strings and secrets out of our web.config via a secrets.config because we don't want any of that information committed to source control. If there is a better practice for this scenario we are open to switching but currently unsure of how this would integrate with VSTS CD/CI.
We've tried using the XDT Transform Extension to transform our web.base.config to web.config to remove the file and the configsource references but it doesn't seem to be transforming.
We've also used the IIS Web App Deploy task with the XML transformation and XML variable substitution but the transformation isn't working because the web.base.config doesn't exist in the artifacts. I'm not sure why that is not being pulled in on build.
We'd like to know what best practice is for any or all of these different steps and how we can accomplish an on premise deployment successfully without committing config settings to source control. We'd also like to know how to execute this methodology for console apps as well.
Since the web.base.config file isn’t uploaded to source control and no in build agent machine, so you can’t use XDT Transform or XML transformation task/feature.
You can store the data in secret variable or Azure Key Vault and link it to release definition.
For example:
Add a new variable (click lock icon) or link Azure key Vault in release definition (e.g. connectionStrings)
Way 1: Check XML variable substitution option (Variables defined in the Build or Release Definition will be matched against the 'key' or 'name' entries in the appSettings, applicationSettings, and connectionStrings sections of any config file and parameters.xml. Variable Substitution is run after config transforms.), then the variable value will be replaced to the config files
Way 2: If the web app published as the web deployment package: override web deploy parameters (SetParameters.xml )by specifying value in Override Parameters input in release task. (You can add parameters.xml file to the project, then the related parameters will be added to SetParameters.xml file when generate web deployment package) Configuring Parameters for Web Package Deployment
Way 3: Using Replace Token task to replace the token in a file (e.g. #{mypassword}#) to the variable value (mypassword)

Windows service cannot read parameters from the App.config

I created a Windows service used to execute automated procedures (.Net code) for multiple periodic operations, like backups, sanity checks, reports generation, etc. After building the project, I installed the service with installutil. Everything worked great.
I decided to move various "static" parameters for these automated procedures in the App.config file. I uninstalled the previous version of the service with installutil /u and built the new version of the project. In my build output folder, there's a AppName.exe file and a AppName.exe.config file, as I would expect. I installed the new version of the service, again with installutil from the VS 2012 Developer Command Prompt as an administrator.
The problem is that the service doesn't seem to be able to read the configuration file from the ConfigurationManager. The call for ConfigurationManager.AppSettings("paramname") doesn't fail, but the resulting parameter value is an empty string. As far as I know, the problem occurs for all parameters and not only for specific ones. The parameters are located in the <appSettings> section, under <configuration>, like I've done multiple times before in various projects.
I don't know if it can help, but my service runs on the LocalSystem account and starts automatically after installation and with Windows.
What did I do wrong?
Edit: I already tried uninstalling/re-installing the service (multiple times), like some stackoverflow answers suggests. Also, I'm not looking to update/refresh the file at runtime.
I solved this by setting the location of the config file in runtime. This enables me to place and name the config file where ever I want. I fetch the executing assembly path and then checks if the config file is there. Check the answer on this thread how to dynamically set the config file
This is how I fetch the executing assembly:
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var configFilePath = Path.Combine(path, "service.config");
Hope this helps!
Turns out I was getting the configuration value in a variable declared with the same name as the property I was using to store the value. For an unknown reason, I had no warning from the compiler. Since a Windows service cannot be debugged, the solution was to review the code/rewrite this part from scratch, and that's when I saw the error.

Sharing information between C# project and WiX

I have an application that starts and stops a specific service. However that service is named differently depending on what configuration I build the project in. In my WiX setup I have
<ServiceInstall
<!-- etc... -->
Name='$(var.ServiceName)'
DisplayName='$(var.ServiceDisplayName)' />
where var.ServiceName comes from an include file specified during the build process. I have to use the same service name in my C# code, but my problem with this approach is that the service names are written in two different places. How can I get the service name into one place?
Consider putting the service name into a registry key, where your C# code can easily access it. Since you install a service, your product is not copy-deployable anyway so using the registry could be an option.
How is the C# code getting the service name? If it is picking up from config, then you can edit the config during install and get the installer to write the service name in to the config file, that way you keep the code in step with the value you specified in the WiX include.
EDIT.
In response to the question; by edit I mean configure the installer to edit the config for you at install time. I agree that doing it "by hand" (or requesting the user do it) is a bad idea. You can set this up in WiX. You need to use the XML File custom action, the WiX would look something like this snippet:
<Component ...>
<UTIL:XmlConfig>
Id=...
On="install"
Action="create"
File=[.. config file ID goes here ...]
ElementPath="//myElement/livesHere
Node="value"
Name="someNodeName"
Value="some value to set"
...
Sorry I can't paste a real snippet, our WiX config is proprietary:( Hopefully that doc link will see you right.
If you are naming it based on the configuration, why don't you use the $(var.ProjectName.Configuration) (where ProjectName is the name of your C# project) in the name of the service?

Send parameters to Windows Service Installer Visual Studio

I am new to C# and I just created a Windows Service that writes some logs in the event log. In order to install it I created a Visual Studio Setup Project and it all works.
I would like this service to have a configuration file that may be created when installing it. So it should receive some parameters when being installed, like:
-writes to database or event log
-input folder path (it uses an input folder where it reads data from)
-etc.
I know the parameters are received by the service in the OnStart method, I just don't know how to send the parameters to this method.
Along the lines of DJ Kraze's comment. I would use an application config http://msdn.microsoft.com/en-us/library/1xtk877y.aspx. Then create a setup project (creates the MSI) to set the configuration parameters at install time. http://raquila.com/software/configure-app-config-application-settings-during-msi-install/

Categories