DCSIMG
Extending Visual Studio Setup Project – Part 2 - Shai Raiten

Shai Raiten

 Subscribe

Extending Visual Studio Setup Project – Part 2

Extending Visual Studio Setup Project – Part 2

In my last post on that subject Extending Visual Studio Setup Project – Part 1 I showed how to create and use the basic features in Visual Studio Installer, this is the second part and more advanced.

Download Demo Project

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 , 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);
        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);
    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
{
    /// <summary>Hides the window and activates another window.</summary>
    /// <remarks>See SW_HIDE</remarks>
    Hide = 0,
    /// <summary>Activates and displays a window. If the window is minimized
    /// or maximized, the system restores it to its original size and
    /// position. An application should specify this flag when displaying
    /// the window for the first time.</summary>
    /// <remarks>See SW_SHOWNORMAL</remarks>
    ShowNormal = 1,
    /// <summary>Activates the window and displays it as a minimized window.</summary>
    /// <remarks>See SW_SHOWMINIMIZED</remarks>
    ShowMinimized = 2,
    /// <summary>Activates the window and displays it as a maximized window.</summary>
    /// <remarks>See SW_SHOWMAXIMIZED</remarks>
    ShowMaximized = 3,
    /// <summary>Maximizes the specified window.</summary>
    /// <remarks>See SW_MAXIMIZE</remarks>
    Maximize = 3,
    /// <summary>Displays a window in its most recent size and position.
    /// This value is similar to "ShowNormal", except the window is not
    /// actived.</summary>
    /// <remarks>See SW_SHOWNOACTIVATE</remarks>
    ShowNormalNoActivate = 4,
    /// <summary>Activates the window and displays it in its current size
    /// and position.</summary>
    /// <remarks>See SW_SHOW</remarks>
    Show = 5,
    /// <summary>Minimizes the specified window and activates the next
    /// top-level window in the Z order.</summary>
    /// <remarks>See SW_MINIMIZE</remarks>
    Minimize = 6,
    /// <summary>Displays the window as a minimized window. This value is
    /// similar to "ShowMinimized", except the window is not activated.</summary>
    /// <remarks>See SW_SHOWMINNOACTIVE</remarks>
    ShowMinNoActivate = 7,
    /// <summary>Displays the window in its current size and position. This
    /// value is similar to "Show", except the window is not activated.</summary>
    /// <remarks>See SW_SHOWNA</remarks>
    ShowNoActivate = 8,
    /// <summary>Activates and displays the window. If the window is
    /// minimized or maximized, the system restores it to its original size
    /// and position. An application should specify this flag when restoring
    /// a minimized window.</summary>
    /// <remarks>See SW_RESTORE</remarks>
    Restore = 9,
    /// <summary>Sets the show state based on the SW_ value specified in the
    /// STARTUPINFO structure passed to the CreateProcess function by the
    /// program that started the application.</summary>
    /// <remarks>See SW_SHOWDEFAULT</remarks>
    ShowDefault = 10,
    /// <summary>Windows 2000/XP: Minimizes a window, even if the thread
    /// that owns the window is hung. This flag should only be used when
    /// minimizing windows from a different thread.</summary>
    /// <remarks>See SW_FORCEMINIMIZE</remarks>
    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 to continue until you will close the application.

image

After the setup is complete you will see you setup output as below

image

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.

Download Demo Project

Comments

Twitter Trackbacks for Extending Visual Studio Setup Project ??? Part 2 - Shai Raiten [microsoft.co.il] on Topsy.com said:

Pingback from  Twitter Trackbacks for                 Extending Visual Studio Setup Project ??? Part 2 - Shai Raiten         [microsoft.co.il]        on Topsy.com

# January 17, 2011 3:50 PM

Now You Can Find Mini Bridal Flower Girl Dresses in Adorable Styles | barbie girls games said:

Pingback from  Now You Can Find Mini Bridal Flower Girl Dresses in Adorable Styles | barbie girls games

# January 17, 2011 5:46 PM

Cheap Car Insurance-How To Select Cheap Car Insurance | online car insurance said:

Pingback from  Cheap Car Insurance-How To Select Cheap Car Insurance | online car insurance

# January 17, 2011 6:27 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: