Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating <appname>.config file from an Custom Installer Class Action

I've tried updating my application's .config file during installer (via a .NET Installer Class Action). But, I can't seem to get ConfigurationManager to list any properties or be able to set anything.

I learned of this approach from several stackoverflow posts that pointed me to this guide: http://raquila.com/software/configure-app-config-application-settings-during-msi-install/

I've investigated the differences between my project and his and noticed that my configuration files are formatted differently. I believe this has to do with the fact that i'm using "Settings" files.

Config files formatted in the guide look like:

<?xml version="1.0" encoding="utf-8" ?>     
<configuration>     
  <appSettings>      
    <add key="Param1" value="" />      
    <add key="Param2" value="" />      
    <add key="Param3" value="" />      
  </appSettings>      
</configuration> 

Where mine looks like:

   <?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MyAppName.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
            <section name="MyAppName.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MyAppName.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <userSettings>
        <MyAppName.Properties.Settings>
            <setting name="TESTSETTING" serializeAs="String">
                <value>asdfasdfasdf</value>
            </setting>
        </MyAppName.Properties.Settings>
        <MyAppName.Settings1>
            <setting name="VerboseErrorMode" serializeAs="String">
                <value>False</value>
            </setting>
    <applicationSettings>
        <MyAppName.Settings1>
            <setting name="RunOnStartup" serializeAs="String">
                <value>True</value>
            </setting>
        </MyAppName.Settings1>
    </applicationSettings>
</configuration>

To shed some light on what was going on... I tried printing out the list of settings like so:

            Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);               

            // Try getting the Settings1 Section
            AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("Settings1");  // Also tried myNamespace.Settings1
            if (appSettings != null)
            {
                valList = "Settings1: ";
                foreach (string key in appSettings.Settings.AllKeys)
                {
                    string value = appSettings.Settings[key].Value;
                    valList += ("Key: '" + key + "' = '" + value + "'\n");
                }
            }
            else
            {
                valList = "appSettings was null";
            }
            MessageBox.Show(valList);

        MessageBox.Show(valList);

I have tried several permutations of this... and in all cases output is "appSettings was null".

I also tried initializing the configuration manager in several different ways...

            Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);

            MessageBox.Show("Section Count: " + config.Sections.Count);
            MessageBox.Show("Has File: " + config.HasFile);
            MessageBox.Show("Namespace Declared: " + config.NamespaceDeclared);

            config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            MessageBox.Show("Section Count: " + config.Sections.Count);
            MessageBox.Show("Has File: " + config.HasFile);
            MessageBox.Show("Namespace Declared: " + config.NamespaceDeclared);

For each of them the section count returned was 20. (I have no idea where the 20 comes from... I would have expected it to be 3).
HasFile was true for the first case and false for the second.
Namespace Declared was false in both cases.

Thanks!

EDIT (6-18-09): Still looking into this question. Anyone else have any ideas? Thanks.

Search Keywords: "Object Reference Not Set to not set to an instance" <-- this occurs when trying to write to a property.

like image 747
blak3r Avatar asked May 27 '09 23:05

blak3r


People also ask

Where are app config files stored?

The file is stored inside this path "bin/debug/app. config", if you make changes while debugging, those changes should appear there. Just remember that this file is overwritten with the "app. config" from the project root each time you run the application on Visual Studio IDE.

Can we add app config file in class library?

NET Framework application in Visual Studio, an app. config file is added to your project. When you create a class library or a . NET Core project, such a file is not included, although it can be done afterward.

Where is app config file in Visual Studio 2010?

Right-click on the project, select Add->New Item..., then select "Application Configuration File" from the list of possible items. Show activity on this post. It would be a template in the templates directory of Visual Studio.


1 Answers

I came across the same problem, after deep investigation, I found out the easiest way to update any part of config files (e.g. app.config), that's by using XPath. We have an application which connects to web service, during the installation, the user enters the URL of the web service and this should be saved in the following app.config file:

        <?xml version="1.0"?>
    <configuration>
      <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <section name="ApplicationServer.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
      </configSections>

      <applicationSettings>
        <ApplicationServer.Properties.Settings>
          <setting name="ApplicationServer_ApplicationServerUrl" serializeAs="String">
            <value>whatever comes from setup should go here</value>
          </setting>
        </ApplicationServer.Properties.Settings>
      </applicationSettings>
    </configuration>

Here is the code to do this in the installer class:

public override void Install(System.Collections.IDictionary stateSaver)
    {
        base.Install(stateSaver);

        string targetDirectory = Context.Parameters["targetdir"];
        string param1 = Context.Parameters["param1"];

        string path = System.IO.Path.Combine(targetDirectory, "app.config");

        System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();

        xDoc.Load(path);

        System.Xml.XmlNode node = xDoc.SelectSingleNode("/configuration/applicationSettings/Intellisense.ApplicationServer.Properties.Settings/setting[@name='ApplicationServer_ApplicationServerUrl']/value");
        node.InnerText = (param1.EndsWith("/") ? param1 : param1 + "/");

        xDoc.Save(path); // saves the web.config file  
    }

Basically, since the config file is a XML based document, I am using XPath expression to locate specific node and change its value.

like image 101
K.A.D. Avatar answered Oct 06 '22 00:10

K.A.D.