Click here to Skip to main content
Click here to Skip to main content

A Setup and Deployment project that passes parameters to the configuration file

By , 20 Jan 2006
 

Introduction

I am a struggling young software developer, and I often find myself surfing the web in search of various solutions for various problems, and CodeProject seems to be there for me most of the times. This time I encountered another problem: I wanted to create a setup and deployment project which passes arguments during installation time from the user to the configuration file of my application. It took me a while but I managed to find a way to make it work.

In this article, I will demonstrate how to create a Windows setup project which receives a string from the user and places that string in the configuration file of the application during the installation.

Background

In brief, the whole process is as follows:

  • We create a project that we want to install.
  • We create a Setup And Deployment project that will install the former project on the target computer.
  • In the 'File System' window of the setup project, we add the primary output of our application and do all the usual routines.
  • We add to the 'User Interface' window of the setup project a new dialog window that has a textbox in which the user will insert his string.
  • We add a new class that derives from the class 'Installer' and override the methods we want to use during the installation (Install, Commit, Rollback, and Uninstall).
  • We "connect" the new 'Installer'-derived-class to the setup project by adding our primary output to the Install Custom Action in the 'Custom Actions' window.
  • We expose the textbox in the newly added dialog window so that it can be reached from the code.
  • Finally, we write the code we want to perform during the installation (in my case, the code reads the string from the newly added dialog and updates the configuration file in the target computer).

Using the code

Let's get to work...

First of all, I created a simple Windows application that simply gets a path from the configuration file and sets the background image of the form to that path.

The app.config file looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
       <appSettings>
        <add key="FilePath" value="..\..\Images\penguin.png"/>
    </appSettings>
</configuration>

And the constructor of the form gets that string and sets the BackgroundImage property to the given string which, in fact, represents the image file.

The constructor looks like this:

public Form1()
{
    //
    // Required for Windows Form Designer support
    //
    InitializeComponent();

    // Get the path for the background Image from app.Config
    string filePath = 
      ConfigurationSettings.AppSettings["FilePath"];

    // Set the BackgroundImage property
    Image backImage = Image.FromFile(filePath);
    this.BackgroundImage = backImage.GetThumbnailImage(
    this.Width, 
    this.Height, 
    null, 
    IntPtr.Zero);
    this.Refresh();
}

Don't forget to add a reference to the System.Configuration namespace in order to gain access to ConfigurationSettings.AppSettings.

Now, what I want to do is create a setup and deployment project for my desktop application. In order to do that, what we need is to add a new project to our solution and select the setup and deployment project option as shown in the image below, and choose the "Setup Project" option in the Templates option.

Image 1: adding a setup and deployment project.

After adding the project, we can see the 'File System' window:

Image 2: file system window.

This window has three default folders:

  • Application Folder – this shows the structure of the files as they will be installed on the target computer. Here, I place the primary output of my application by right clicking the 'Application Folder' and choosing 'add' and then 'Project Output', as shown in the image:

    Image 3: Adding primary output to the Application Folder

  • User's Desktop – the items in this folder will be installed to the user desktop. I added to this folder a shortcut for my application primary output by right clicking on the primary output (that was added to the 'Application Folder') and choosing 'Create Shortcut' option. Then move the new shortcut to the 'User's Desktop' folder.
  • User Programs Menu – the items in this folder will be installed to the Start menu at the 'All Programs' menu item.

By right clicking the root ('File System On Target Machine'), one can add more folders to the tree in the 'File System' window, were each folder installs the items placed with in it to a similar location on the target computer.

Up until now, all I did was simply install my application on the target computer and create its shortcut in the desktop.

When we run the installation wizard, we see only three screens: Welcome screen, Installation Folder screen (in which we specify were to install our application, and it is in that location that the installation wizard will install all the items we put in the 'Application Folder' node in the 'File System' eindow), and the Confirm screen which is the last screen before the installation finishes.

Now, let's play with the installation wizard and add some more screens. First of all, we need to right click the setup project in the Solution Explorer, and in the 'View' option, we choose 'User Interface' (as shown in the image below). In this screen, we see a tree that specifies the order of the screens of the installation wizard. Under the Install node, you can see the three default screens. I added a screen with a textbox for the user to enter a string, by right clicking the Install node and choose the 'Add Dialog' option (Image 5). You will see a number of dialogs you can add. I chose the TextBoxes (A) dialog.

Image 4: view the 'User Interface' window to add more dialogs to the installation wizard.

Image 5: add a dialog to the 'User Interface' window.

In the TextBoxes dialog that I add to my wizard, there are, by default, four textboxes, but I need only one, so I simply change the other three textboxes' 'Visible' property to false in the Properties window. In the Properties window, you can also play with the text in the banner and the body of the dialog.

After we add the dialog, we need to somehow perform during the installation an action that will take the string from the textbox in the newly added dialog, and update the configuration file.

Now, we write a method that will be called during the installation process. To do that, we need to create a class that will derive from the class Installer, and add the attribute [RunInstaller(true)]. The new class can override the four main methods: Install, Uninstall, Commit, and Rollback.

[RunInstaller(true)]
public class InstallHelper : Installer
{
    *
    *
    *

In this class, I override the Install method in which I will get the text from the new textbox, and update the configuration file.

However, in order that the installation wizard will turn to our method, we first need to add a Custom Action. By right clicking on the setup project in the Solution Explorer window and clicking View->Custom Actions, we see the 'Custom Actions' window which presents to us a tree with four nodes: Install, Commit, Rollback, and Uninstall.

What I need now is to "connect" the installation wizard to my 'Install' method, so I added a new custom action by right clicking the Install node and clicking on 'Add Custom Action':

Image 6: Custom Actions window.

After doing so, a window pops up in which I select my application primary output (in my application, I have the 'InstallerHelper' class):

Image 7: adding a Custom Action

Note that for each method we can override (in the class that derives from 'Installer'), we have a node in the Custom Actions window.

Now when the install wizard will run, it will perform my overridden 'Install' method.

Now what we need to do is:

  1. Expose the Text property of the TextBox in the new dialog so that we can access its value from the code.
  2. Write the code in the Install method that will update the configuration file.

For exposing the Text property, we go to the Properties window of the newly added custom action. Here, we can see a property named 'CustomActionData', and here, I declare my Text property in the following format: /<key>=[<property name>]. My specific declaration was '/PathValue=[EDITA1]' because PathValue was the name I gave, and with this name, I will get the property value in the code later on, and the TextBox name was 'EDITA1':

Image 8: update the CustomActionData property

Note that you can add as much declarations as you want.

Now, we can finally write some code.

To read the value in the TextBox from the code, all we need to do is in the 'Install' method we override, read the value from Context.Parameters[key] were the 'key' is actually the key we write when we declare the property (when we expose the textbox). In my case, the key is, of course, 'PathValue'.

Note that the property Context.Parameters's default value does not contain the Text property of our new textbox. We had to expose it in the Custom Action Properties window.

Another important fact is that after installing the application, the configuration file exists in the target computer under the name of the executable file plus the ending ".config". For instance, if after the installation, the executable file is "MyApp.exe", then in the same directory, you will find the configuration file "MyApp.exe.config" (assuming of course that the application has a configuration file).

Another important value in the 'Context.Parameters' property is the path to the executable file that will be installed to the target computer. Since we know that the configuration file has exactly the same path plus the ending ".config", we have the path to the configuration file.

// Get the path to the executable file that is being installed on 
// the target computer
string assemblypath = Context.Parameters["assemblypath"];
string appConfigPath = assemblypath + ".config";

All that is left to be done is to use the 'XmlDocument' class to update the configuration file which we have the path to. You can view my code in the files attached.

Hope this will help you like you always help me.

Points of Interest

Very important: note that the user can't enter a string with spaces in the textbox. For some reason unknown to me, whenever I enter a string with spaces, the installation fails to work.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Adi Eduard
Web Developer
Israel Israel
Member
Adi Eduard is a software developer for the last 3 years. Working with C# and ASP.Net.
 
Currently working as a senior software developer for Correlation Syatems LTD in Israel.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: Regarding the note in the Point of Interest sessionmemberguido.auchli20 Feb '12 - 3:56 
Change the custom action '/PathValue=[EDITA1]' to '/PathValue="[EDITA1]"'
GeneralMy vote of 5memberKanasz Robert13 Nov '10 - 6:08 
good job
GeneralArguments not neededmemberramin tarhandeh26 Jul '10 - 1:12 
We don't need to set Arguments of the custom action (image 8); I guess it should have another use.
Thanks for the good article
Ramin

Generalin .net2.0 VS2005memberSunshine Always11 Apr '10 - 23:54 
Hi,
I am using VS2005 for setup project creation. I have a directory structure wih many folders that would be installed with the app. I need a way to control the installation of the folders depending on ini file. only the names that appear in the file would get installed.
Is there a way to do this in VS2005? Can i do it using the installer class? or is there any way other than using ini file for configuring the folder names?
 
thanks
Generalblanks in the text stringmemberJohn Mealing11 Apr '10 - 11:14 
Thanks for the cleanest description of how to get text strings yet, and I've been at it for two days. MS Docs are not wonderful! Smile | :)
 
In VS 2008 & Win 7 I had to add one line to the Install Action make things work:
 
// next line is new to make the note visible, may not be necessary in VS 2005
stateSaver.Add("Note", Context.Parameters["Note"].ToString());
String strNote = Context.Parameters["Note"]; // grab the note into a string

Put quotation marks around the text and it works just fine.
GeneralDeployment microsoft officemembermsmalldog10 Mar '10 - 17:31 
I have the first RadioButtons dialog with 2 value(full=1, and custom=2); when I choose full, disable the second Checkboxes dialog; and I choose custom, enable the second Checkboxes dialog.
 
Please help me.
Thank you.
QuestionHow can I react to events during installation?memberDudi Daabul4 Oct '09 - 4:47 
I need to react to events BEFORE files are coppied to the target machine. For example: I need my installer to check the existance of specific drive at the target machine. If this drive doesn't exist, the installer should pop up some message and quit (WITHOUT COPYING THE FILES OF THE APPLICATION!!!) - is it possible to do that? how?
GeneralThanks!membercplas18 Aug '09 - 10:04 
E.X.A.C.T.L.Y. what I was trying to do, thanks!!!
QuestionWhat about parameters from checkboxes?memberErlendG9 Jun '09 - 5:32 
First of all, thank you for an excellent article! This article helped me create an installation project for an application my company has developed, and to let the user enter such as Host name/IP address of server and port number and write these to the application's config file.
 
Now we have made new features to the application, and some more properties need to be written to the config file. These should have the value "true" or "false", and typically these would be handled in a checkbox. I therefore added a checkbox to my custom actions, and placed it after the textbox. I have two parameters that should be either true or false, so I made only the two first textboxes visible. For simplicity let's call them PROPERTY1 and correspondingly PROPERTY2. I named the dialog with checkboxes Properties.
 
On Custom actions in the installer project I added a new custom action, and in CustomActionData I wrote /Properties="[PROPERTY1]";"[PROPERTY2]". I know you haven't used the "", but it works with the textbox custom action dialog box.
 
In the class Installer2.vb I already had this code:
 
Dim myInputFromTextboxA As String = Me.Context.Parameters.Item("HostName")
Dim myPropertyA As String
Dim myPropertyB As String
 
Dim myInputArrayTextBoxA() As String = myInputFromTextboxA.Split(";"c)
This gives me an array with the content the user typed in the custom action dialog window. I can then traverse the array, extract the values and assign them to the proper variables before writing these variables to my config file.
 
Problem is, how do I extract the content of a checkbox custom dialog window? I've tried to do correspondingly:
Dim myInputFromCheckboxA As String = Me.Context.Parameters.Item("Properties")
Dim myInputArrayCheckboxA() As Objecet = myInputFromCheckbox.Split(";"c)
I've set the type of myInputArrayCheckboxA to Object because I don't know what type these values will have, but Object should cover everything. These two lines appears to work fine, but I've tried to add some message boxes with myInputFromCheckboxA.ToString to see what's in there, but when I try to run the installer, it fails.
 
Can anyone tell me how to extract the content from a checkbox, and what type a variable from a checkbox has?
 
ErlendG

AnswerI found the answer myselfmemberErlendG11 Jun '09 - 20:35 
And I'll reveal it here in case anyone else have the same problem.
 
First, I found out, as described in another thread here, that it's not necessary to add another custom action. I'm not even sure if it's possible, at least I didn't find out how to make that work.
 
I have a textbox dialog and a checkbox dialog, named respectively HostName and Properties. On the property CustomActionData of the custom action I wrote
/HostName=[EDIT1];[EDIT2];[EDIT3];[EDIT4]/Properties=[CHECKBOX1];[CHECKBOX2]
 
I inserted a message box to see what the code line
Dim myInput As String = Me.Context.Parameters.Item("HostName")
gave me, it was ContentOfEdit1;ContentOfEdit2;ContentOfEdit3;ContentOfEdit4/Properties=1;1
 
Behind properties I got 1;1 if both checkboxes were checked, 1; if only the first was checked and so on. I then made a string array subStrings, and used this line to separate the content from the textbox and the checkbox:
subStrings = myInput.Split(New String() {"/Properties="}, StringSplitOptions.None)
myInputFromTextbox = subStrings(0)
myInputFromCheckbox = subStrings(1)
Dim myInputArray() As String = myInputFromTextbox.Split(";"c)
 
I could then traverse myInputArray to extract what the user had typed in the textboxes. When I tried to run the install program on a test computer I found that it crashed if I typed a space in one of the textboxes, but found the solution in another thread here: Add "" to the properties, i.e. /HostName="[EDIT1]";"[EDIT2]" etc.
 
This solution has a couple of weaknesses which means the installer program isn't completely idiot proof. If the user types a semicolon or /Properties in a textbox, the splits would not give me what the user has typed to the correct variables, and my program would not write what the user has typed to the config file. I could use any character as delimiter, but the user could also type any character in the textboxes, so no character is safe. Does anyone have a good solution for this problem?
 
ErlendG

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 20 Jan 2006
Article Copyright 2006 by Adi Eduard
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid