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

Extending Visual Studio Setup Project

By , 16 Jan 2011
 
1.png

Introduction

One of the things I hear all the time when companies talk about building reliable Windows Installer (MSI) for their product is –> Visual Studio Setup Project is not enough and we need much much more, my first response is – Wait, VS Setup project is not like Advanced Installer, InstallShield but still can do a lot more outside the box.

Setup projects are used to create Windows Installer (.msi) files, which are used to distribute your application for installation on another computer or Web server. There are two types of setup projects:

  • Standard setup projects create installers that install Windows applications on a target computer.
  • Web setup projects create installers that install Web applications on a Web server.

In this article, I’ll show how to extend your VS Setup Project and help to understand how VS Setup makes it easy for developers to build reliable Windows Installer (MSI) in Visual Studio. (All my screenshots will take from Visual Studio 2010.)

  1. Getting Started With VS Setup Project
  2. Adding New User Dialog and Deployments Conditions
  3. Run External Application during Setup

Getting Started

Open Visual Studio and create new Setup Project called – "DemoSetup", the Setup project item can be found under "Other Project Types"-> "Setup and Deployment" –> "Visual Studio Installer".

Also create a WPF application called – "DemoWpfApplication", we need some project to work with.

Two things need to be done in order to get the MSI ready for deployment.

  1. On the DemoSetup project, Add Project Output from DemoWPFApplication – Setup will automatically find all related dependencies.
  2. Modify Setup Project properties (See picture below)

The Version Property is very important for various MSI, in order to identify old installation and overwrite existing files with a newer version.

2.png

Adding New User Dialog and Deployments Conditions

Now, this is one of most common improvement users always want – Add an additional Dialog during the setup and add your own questions or input.
In this step, I’ll show how to add conditions and add a new user Dialog, here are the requirements: Add the following file (Dummy Files):

  • Blue.bmp,Red.bmp, Green.bmp
  • License.rtf
  • "Readme for 2000.txt", "Readme for Windows 7.txt"

1. First Let's Add Our Product License Agreement

Select the Setup Project and click "User Interface Editor" icon:

3.png

This will open a view showing all the dialogs the user will see during the Setup process.
Click "Add Dialog" and choose "License Agreement", after adding this dialog view dialog properties and select the License.rtf file.

4.png

2. Add Deployment by Condition

Add deployment condition for "Readme for 2000.txt", "Readme for Windows 7.txt", the propose is to copy each file only for specific operation system.
Select "Readme for 2000.txt" to see his properties, locate Condition and add this command –

WindowsBuild = 2195 or VersionNT = 500 

Now select "Readme for Windows 7.txt" and add this in the Condition property –

WindowsBuild >= 7100 or VersionNT = 601 

(More information on Operating System Property Values)
The condition will allow you to copy specific file depending on the user OS.

3. Add your User Choose Condition

This step will show you how to add your own questions (using Radio Buttons) and allow the user to define a Favorite Color and use User choose as condition for deployment.
Add a new Dialog and choose "RadioButton (3 buttons)" add fill the information as below:

5.png

To add the condition, you need to select each of the following files: Blue.bmp, Red.bmp, Green.bmp and add the proper value in the condition property as follow - FAVORITECOLOR="Blue", FAVORITECOLOR="Red" etc.

Build the setup project and run it, select Green in "Favorite Color" and the result should look like:

6.png

Run External Application during Setup

In this step, I’ll show how to run an external application before the actual install process using "Installer Class".
Create new WPF Application project called – "SetupHelper" and add additional Item of type "Installer Class" called – "MyInstallerHelper".
The InstallerClass will allow you to override the following events:

  • Rollback
  • Install
  • OnAfterInstall
  • Commit
  • OnAfterRollback
  • OnAfterUninstall
  • OnBeforeRollback
  • OnBeforeUninstall
  • OnCommitted
  • OnCommitting
  • Uninstall
  • OnBeforeInstall

First, add your code for "SetupHelper" WPF application, I’ve added code to show current processes and process title, but you can add whatever you want.
Now we need to add "SetupHelper" WPF app to our setup project, select the Setup Project and "Add Project Output" of SetupHelper.
Select the Setup Project and click on the "Custom Actions Editor" icon:

7.png

On the install, add new "Custom Action" and from the "Application Folder", pick "Primary output from SetupHelper (Active).
Now select the new Custom Action and in the "CustomActionData", add the following -

/Run=SetupHelper.exe /WaitForExit=true 

Back to MyInstallerHelper, override OnBeforeInstall and paste the code below in order to get the CustomActionData you wrote above:

protected override void OnBeforeInstall(IDictionary savedState)
{
    try
    {
        base.OnBeforeInstall(savedState);
        FileInfo fileInfo = new FileInfo
		(System.Reflection.Assembly.GetExecutingAssembly().Location);
        //Take custom action data values
        string sProgram = Context.Parameters["Run"];
        sProgram = Path.Combine(fileInfo.DirectoryName, sProgram);
        Trace.WriteLine("Install sProgram= " + sProgram);
        OpenWithStartInfo(sProgram);
    }
    catch (Exception exc)
    {
        Context.LogMessage(exc.ToString());
        throw;
    }
}

OpenWithStartInfo will run SetupHelper application and will pause the setup process while the SetupHelper is open.

void OpenWithStartInfo(string sProgram)
{
    ProcessStartInfo startInfo = new ProcessStartInfo(sProgram);
    startInfo.WindowStyle = ProcessWindowStyle.Normal;
    string[] ExcludeKeys = new string[] { "run", "WaitForExit" };
    startInfo.Arguments = ContextParametersToCommandArguments(Context, ExcludeKeys);
    Trace.WriteLine("run the program " + sProgram + startInfo.Arguments);
    Process p = Process.Start(startInfo);
    ShowWindow(p.MainWindowHandle, WindowShowStyle.Show); 	//otherwise it is 
							//not activated 
    SetForegroundWindow(p.MainWindowHandle);
    BringWindowToTop(p.MainWindowHandle); 	// Make sure the user will see 
					// the new window above of the setup.
    Trace.WriteLine("the program Responding= " + p.Responding);
    if ((Context.IsParameterTrue("WaitForExit")))
    {
        p.WaitForExit();// Have to hold the setup until the application is closed.
    }
}

ContextParametersToCommandArguments gets the CustomActionData arguments you added in the Custom Action.

public static String ContextParametersToCommandArguments
		(InstallContext context, string[] ExcludeKeys)
{
    ExcludeKeys = ToLower(ExcludeKeys);
    StringBuilder sb = new StringBuilder();
    foreach (DictionaryEntry de in context.Parameters)
    {
        string sKey = (string)de.Key;
        bool bAdd = true;
        if (ExcludeKeys != null)
        {
            bAdd = (Array.IndexOf(ExcludeKeys, sKey.ToLower()) < 0);
        }
        if (bAdd)
        {
            AppendArgument(sb, sKey, (string)de.Value);
        }
    }
    return sb.ToString();
}

public static StringBuilder AppendArgument(StringBuilder sb, String Key, string value)
{
    sb.Append(" /");
    sb.Append(Key);
    //Note that if value is empty string, = sign is expected, e.g."/PORT="
    if (value != null)
    {
        sb.Append("=");
        sb.Append(value);
    }
    return sb;
}

#region "FS library methods"
public static string[] ToLower(string[] Strings)
{
    if (Strings != null)
    {
        for (int i = 0; i < Strings.Length; i++)
        {
            Strings[i] = Strings[i].ToLower();
        }
    }
    return Strings;
}
#endregion //"FS library methods"
#region "showWindow"

// http://pinvoke.net/default.aspx/user32.BringWindowToTop
[DllImport("user32.dll")]
static extern bool BringWindowToTop(IntPtr hWnd);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);

//from http://pinvoke.net/default.aspx/user32.SwitchToThisWindow 
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);

/// <summary>Enumeration of the different ways of showing a window using 
/// ShowWindow</summary>
private enum WindowShowStyle : uint
{
    Hide = 0,
    ShowNormal = 1,
    ShowMinimized = 2,
    ShowMaximized = 3,
    Maximize = 3,
    ShowNormalNoActivate = 4,
    Show = 5,
    Minimize = 6,
    ShowMinNoActivate = 7,
    ShowNoActivate = 8,
    Restore = 9,
    ShowDefault = 10,
    ForceMinimized = 11
}
#endregion

Try It

Now Run the Setup project and you will notice that during the installation process, your Setup Helper will pop up and prevent the Setup from continuing until you will close the application.

8.png

After the setup is complete, you will see your setup output as below:

9.png

Summary

As you saw in this article, Visual Studio Setup Project can be extended a lot more and this can be good for many applications.

History

  • 16th January, 2011: Initial post

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

Shai Raiten
Architect Sela
Israel Israel
Member
Shai Raiten is VS ALM MVP, currently working for Sela Group as a ALM senior consultant and trainer specializes in Microsoft technologies especially Team System and .NET technology. He is currently consulting in various enterprises in Israel, planning and analysis Load and performance problems using Team System, building Team System customizations and adjusts ALM processes for enterprises. Shai is known as one of the top Team System experts in Israel. He conducts lectures and workshops for developers\QA and enterprises who want to specialize in Team System.
 
My Blog: http://blogs.microsoft.co.il/blogs/shair/

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

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questiongreat !memberWrangly3 Jan '13 - 1:55 
QuestionTime Bombmemberjalindar.sabale17 Nov '12 - 23:58 
GeneralThanks alot!memberThilinalees8 Oct '12 - 0:33 
GeneralMy vote of 4memberhari1911321 Sep '12 - 6:26 
GeneralRe: My vote of 4mvpShai Raiten29 Sep '12 - 20:35 
QuestionOnBeforeInstall eventmembersten lembo27 Aug '12 - 2:48 
AnswerRe: OnBeforeInstall eventmvpShai Raiten29 Sep '12 - 20:36 
Questionadd custom dialog in maintenance dialogmemberjoehom13 Aug '12 - 20:50 
QuestionAdding of DB script files.memberMohammed Hameed14 Jun '12 - 2:43 
AnswerRe: Adding of DB script files.mvpShai Raiten6 Jul '12 - 21:47 
GeneralMy vote of 5memberMohammed Hameed14 Jun '12 - 2:42 
GeneralMy vote of 5memberLukann1 May '12 - 9:45 
QuestionAmazingmemberak1624 Apr '12 - 4:19 
Questionneed helpmemberSebastian T Xavier19 Apr '12 - 3:31 
GeneralMy vote of 5membershanmuga priya8 Mar '12 - 19:21 
QuestionA vote of 5 and a (hopefully) helpful linkmemberDon Kackman28 Feb '12 - 10:30 
GeneralMy vote of 5memberpurvapatel10 Feb '12 - 2:06 
GeneralRe: My vote of 5mvpShai Raiten29 Feb '12 - 3:20 
QuestionHow to change startup info for the setup projectmemberMember 820215825 Nov '11 - 1:57 
QuestionHow could i make opened window as Modal?memberSunasara Imdadhusen28 Aug '11 - 21:55 
AnswerRe: How could i make opened window as Modal?mvpShai Raiten29 Sep '12 - 20:37 
GeneralMy vote of 5memberjawed.ace19 Jun '11 - 21:51 
GeneralRe: My vote of 5memberShai Raiten20 Jun '11 - 5:36 
QuestionRe: My vote of 5memberJohnny7929 Jun '11 - 8:32 
AnswerRe: My vote of 5memberShai Raiten30 Jun '11 - 21:23 

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 16 Jan 2011
Article Copyright 2011 by Shai Raiten
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid