Create a Custom Setup For Changing App.config

Today I will explain Setup Projects and how to create a custom setup that can change our app.config.

1: Installing our environment

I will use Visual Studio 2013 and we need to install the following tool:

Microsoft Visual Studio 2013 Installer Projects:

  • Download here.

  • Follow the installation (next, next, next).

2: Creating a simple setup project

Before we start, I created a solution with the following two projects:

  • Console Application (the application that we want to install);

  • Setup Project (Setup to install our application)

My console application has the following code:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace ApplicationToInstall  
  8. {  
  9.     class Program  
  10.     {  
  11.         static void Main(string[] args)  
  12.         {  
  13.             Console.WriteLine("Hellow World!!!");  
  14.             Console.ReadKey();  
  15.         }  
  16.     }  
  17. }  
Now we need to create our setup project with the following procedure:
  1. Solution Explorer, then click on Add and select New Project.

    add new project

  2. Add a Setup Wizard.

    setup wizard

    setup project wizaed

    create a setup

    primary output from application

  3. If you want to add some icon file, I suggest you include in the next form:

    choose files to include

    create project

  4. When the wizard ends (finish), the following tab will open:

    follow tab

  5. On “application folder”, right-click “Primary Output from ApplicationToInstall (Active)” and select “Create Shortcut to Primary”.

    ApplicationToInstall

    Create Shortcut to Primary

  6. Drag and Drop the shortcut to “User's Desktop”:

    user desktop

  7. If you want to set an icon, press “F4” at shortcut and change the icon property.

  8. Build our setup project:

    build

  9. Now let's install:

    click install

    click next

  10. At the end of installation, the shortcut will be at our desktop, if we open:

    shortcut

3: Incrementing functionalities

Now we will make some increments at our setup, right-click at Setup Project and go to “View" and select "User Interface”:

Interface

install

We can insert steps by right-click and Add Dialog:

Add Dialog

For this article we will add TextBoxes:

add textboxes

textboxes

Open the Property window (F4):

bannerBitmap

Now we can change any of these values, I will configure it as follows:

edit4visuable

I will mark the textboxes that I don't want to show to false (visible as false). Let's test our setup, just rebuild and try to install:

test parameter

It worked, but it doesn't do anything. Now we need to pass this parameter to some code and use them to do something. To do that, we will need to create an Installer Class for our main application (in my case, console application).

Go to Solution Explorer, select your main application, then click Add and select New Item:

installer class

And I will write the following code:

  1. using System;  
  2. using System.Collections;  
  3. using System.Collections.Specialized;  
  4. using System.ComponentModel;  
  5. using System.Text;  
  6. using System.Windows.Forms;  
  7. using System.Xml;  
  8.   
  9. namespace ApplicationToInstall  
  10. {  
  11.     [RunInstaller(true)]  
  12.     public partial class InstallerSetup : System.Configuration.Install.Installer  
  13.     {  
  14.         public InstallerSetup()  
  15.         {  
  16.             InitializeComponent();  
  17.         }  
  18.   
  19.         public override void Install(System.Collections.IDictionary stateSaver)  
  20.         {  
  21.             base.Install(stateSaver);  
  22.         }  
  23.   
  24.         public override void Commit(IDictionary savedState)  
  25.         {  
  26.             base.Commit(savedState);  
  27.   
  28.             try  
  29.             {  
  30.                 AddConfigurationFileDetails();  
  31.             }  
  32.             catch (Exception e)  
  33.             {  
  34.                 MessageBox.Show("Falha ao atualizar o arquivo de configuração da aplicação: " + e.Message);  
  35.                 base.Rollback(savedState);  
  36.             }  
  37.         }  
  38.   
  39.         public override void Rollback(IDictionary savedState)  
  40.         {  
  41.             base.Rollback(savedState);  
  42.         }  
  43.   
  44.         public override void Uninstall(IDictionary savedState)  
  45.         {  
  46.             base.Uninstall(savedState);  
  47.         }  
  48.   
  49.         private void showParameters()  
  50.         {  
  51.             StringBuilder sb = new StringBuilder();  
  52.             StringDictionary myStringDictionary = this.Context.Parameters;  
  53.             if (this.Context.Parameters.Count > 0)  
  54.             {  
  55.                 foreach (string myString in this.Context.Parameters.Keys)  
  56.                 {  
  57.                     sb.AppendFormat("String={0} Value= {1}\n", myString,  
  58.                     this.Context.Parameters[myString]);  
  59.                 }  
  60.             }  
  61.             MessageBox.Show(sb.ToString());  
  62.         }  
  63.   
  64.         private void AddConfigurationFileDetails()  
  65.         {  
  66.             try  
  67.             {  
  68.                 string TESTPARAMETER = Context.Parameters["TESTPARAMETER"];  
  69.   
  70.                 // Get the path to the executable file that is being installed on the target computer  
  71.                 string assemblypath = Context.Parameters["assemblypath"];  
  72.                 string appConfigPath = assemblypath + ".config";  
  73.   
  74.                 // Write the path to the app.config file  
  75.                 XmlDocument doc = new XmlDocument();  
  76.                 doc.Load(appConfigPath);  
  77.   
  78.                 XmlNode configuration = null;  
  79.                 foreach (XmlNode node in doc.ChildNodes)  
  80.                     if (node.Name == "configuration")  
  81.                         configuration = node;  
  82.   
  83.                 if (configuration != null)  
  84.                 {  
  85.                     //MessageBox.Show("configuration != null");  
  86.                     // Get the ‘appSettings’ node  
  87.                     XmlNode settingNode = null;  
  88.                     foreach (XmlNode node in configuration.ChildNodes)  
  89.                     {  
  90.                         if (node.Name == "appSettings")  
  91.                             settingNode = node;  
  92.                     }  
  93.   
  94.                     if (settingNode != null)  
  95.                     {  
  96.                         //MessageBox.Show("settingNode != null");  
  97.                         //Reassign values in the config file  
  98.                         foreach (XmlNode node in settingNode.ChildNodes)  
  99.                         {  
  100.                             //MessageBox.Show("node.Value = " + node.Value);  
  101.                             if (node.Attributes == null)  
  102.                                 continue;  
  103.                             XmlAttribute attribute = node.Attributes["value"];  
  104.                             //MessageBox.Show("attribute != null ");  
  105.                             //MessageBox.Show("node.Attributes['value'] = " + node.Attributes["value"].Value);  
  106.                             if (node.Attributes["key"] != null)  
  107.                             {  
  108.                                 //MessageBox.Show("node.Attributes['key'] != null ");  
  109.                                 //MessageBox.Show("node.Attributes['key'] = " + node.Attributes["key"].Value);  
  110.                                 switch (node.Attributes["key"].Value)  
  111.                                 {  
  112.                                     case "TestParameter":  
  113.                                         attribute.Value = TESTPARAMETER;  
  114.                                         break;  
  115.                                 }  
  116.                             }  
  117.                         }  
  118.                     }  
  119.                     doc.Save(appConfigPath);  
  120.                 }  
  121.             }  
  122.             catch  
  123.             {  
  124.                 throw;  
  125.             }  
  126.         }  
  127.     }  
  128. }  
This code overrides the commit event to read our TESTPARAMETER (TextBox value) and then insert on app.config.

Before running the installation we need to link our TextBox with our installer class. Go to the setup project and open the “Custom Actions”:

custom action view

As we override the commit method we need to insert a custom action on the commit step:

add custom action

click ok

Click twice the “Application Folder”:

Application Folder

primary output

Press “F4” or go to properties:

properties

At “CustomActionData” use the following value:

    /{our parameter key}=[{our textbox edit property value}]

For our application:

    /TESTPARAMETER=”[TESTPARAMETER]”
    If you need more than one parameter just put like as follow:
    /TESTPARAMETER=”[TESTPARAMETER]” /TESTPARAMETER2=”[TESTPARAMETER2]”

CustomActionData

Now we can test our application, our current config will look like the following:

  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <configuration>  
  3.     <startup>   
  4.         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />  
  5.     </startup>  
  6.   <appSettings>  
  7.     <add key="TestParameter" value="ThisValueHasToChange" />  
  8.   </appSettings>  
  9. </configuration>  

Let's run our setup (rebuild/install) and change the parameter:

run our setup

Open the config file at the install folder:

install folder

That's it guys, enjoy.

4: Errors that can happen

If you receive the following error:

error

Put a custom action at the “Install” step (no need to configure, it can be empty).

custom action


Similar Articles