Grow from a Newbie to Pro in Creating the Installers
Tags: dotnet, csharp, wpf, installer
Published: 2020-03-12 07:17:21

---
title: Grow from a Newbie to Pro in Creating the Installers
published: true
date: 2020-03-03 12:00:14 UTC
tags: dotnet, csharp, wpf, installer
canonical_url: https://www.syncfusion.com/blogs/post/grow-from-a-newbie-to-pro-in-creating-the-installers.aspx
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/41j875916d5u4xwkil4p.png
---

Installers are the software components responsible for installing, maintaining, and uninstalling software. Installers give your users their first impression of your software product before they even start using it. So, creating an attractive and impressive experience is important.

Installers are programmed to perform a required set of operations automatically rather than doing them one by one manually. They obviously reduce the time spent on manual processes.

The installers are sharable and can be run in any number of machines without any restrictions. Removing the installed files can be done easily in a single click by uninstalling the installer from control panel.

In this blog, we are going to discuss creating an installer using the [WiX toolset](https://wixtoolset.org/). We’ll be:

- [Creating an MSI installer.](#create-an-msi)
- [Creating an executable installer.](#creating-a-simple-exe-installer)
- [Creating a customized UI installer.](#creating-a-custom-ui-installer)

## Prerequisites

You need the following tools before proceeding further:

- WiX toolset—Download the latest [WiX toolset](https://wixtoolset.org/releases/).
- Visual Studio and its corresponding [WiX toolset extension](https://wixtoolset.org/releases/).

## What is the WiX toolset?

The [WiX toolset](https://www.firegiant.com/wix/tutorial/) is an open-source project developed by Microsoft to build Windows installation packages based on XML source code. The WiX project supports:

- Shipping files of larger sizes.
- Performing custom actions.
- Outperforming registry actions.

The rest of this blog will demonstrate the step-by-step procedure to create WiX and bootstrapper applications. Download the complete source for these sample applications [on our website](https://www.syncfusion.com/downloads/support/directtrac/general/ze/SampleApplication741900061).

## Create an MSI using WiX toolset

1. Open Visual Studio and create a new project by clicking **File->New->Project**.
2. The Create a new project dialog will open. In the search box, search for WiX and select the **Setup Project for WiX v3 ![Create a new project](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Create-a-new-project.png)**
3. Provide a name for the project and click **Create**. Here I have named the project _SampleWixApplication_. ![Configure a new project](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Configure-a-new-project.png)

The project will be created. ![Code of new project](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Code-of-new-project.png)

4. In this example, we are shipping a text file to the Program Files location. Provide the product ID and manufacturer at the top of the application. You can create the product ID in Visual Studio by clicking **Tools-> Create GUID**. ![Create GUID](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Create-GUID.png) ![Product.wxs code changes](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Product.wxs-code-changes.png)

5. In the **TARGETDIR** tag, remove the closing tag of **INSTALLFOLDER** and include the code to create a new directory inside the **INSTALLFOLDER** directory tag.
```xml
<Directory Id="INSTALLFOLDER" Name="SampleWixApplication" >
<Directory Id="dir_sample" Name="Sample" />
</Directory>    
```

1. Remove the default component group inside the **Fragment** In the **ComponentGroup** tag inside the **Fragment** , include the code for shipping the text file.

**Product.wxs:**

```xml
<ComponentGroup Id="ProductComponents_text" Directory="dir_sample">
    
<Component Id="comp_samplefile1" Guid="{81C0887C-29BC-4632-8290-1B85BC0FA811}" KeyPath="yes" >
 
<File Id="file_samplefile1" Source="C:\Users\syncfusion\Documents\ReadMe.txt" />
     </Component>
 
</ComponentGroup>
```

1. In the **Feature** tag, remove the default component group reference and include the **ComponentGroupRef** ID as a reference for the component to be shipped.

**Product.wxs:**

```xml
<ComponentGroupRef Id="ProductComponents_text" />
```

1. Build the application and the MSI will be created along with cab files in the application’s output location. If you wish to copy the output .msi file to another location, copy the .cab file also, as it should be placed parallel to the .msi file.

**Output location:**

C:\Users\%%username%%\Documents\SampleWixApplication\SampleWixApplication\bin\

Release\SampleWixApplication.msi ![msi file on the output window](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/msi-file-on-the-output-window.png)

**Note** : We can embed the cab files in the MSI package itself by replacing the MediaTemplate tag with the following code snippet. ![customizing media template](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/customizing-media-template.png)

1. Run the MSI file and the text file will be shipped to the location specified. ![Installed location](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Installed-location.png)

You can find the installed information in the Control Panel. ![installed application on control panel](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/installed-application-on-control-panel.png)

## Creating a simple .exe using WiX Bootstrapper with default UI

In the bootstrapper application, we can convert the MSI file into an executable (.exe) application:

1. Open Visual Studio.
2. Create a new project by clicking **File->New->Project**.
3. In the Create a new project dialog, search for WiX and select the **Bootstrapper Project for WiX v3 ![Create a new project1](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Create-a-new-project1.png)**
4. Provide a name for your project and click **Create**. ![Configure a new project1](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Configure-a-new-project1.png)

Project will be created ![Code of new project1](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Code-of-new-project1.png)

1. Provide the manufacturer and the .msi file location you want to pack inside the Chain tag. ![Include the MSI](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Include-the-MSI.png)

**Bundle.wxs:**

```xml
<!--MSI file to be packed-->
<MsiPackage Id="Sample" Name="Wixdata" SourceFile="C:\SampleWixApplication\SampleWixApplication.msi" />
```

1. Build the application and the .exe will be created in the application output location. ![Executable installer created](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Executable-installer-created.png)
2. Run the .exe and the default UI will be displayed. ![Execution of the installer](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Execution-of-the-installer.png)
3. Once installed, you can find installation information in the control panel. ![installed application on control panel1](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/installed-application-on-control-panel1.png)

## Creating a custom UI installer

Creating a custom UI installer involves the creation of two different projects:

- Creating a custom UI for the bootstrapper application.
- Integrating the custom UI with the bootstrapper project.

### Creating a custom UI for the bootstrapper application

1. Open Visual Studio and create a new project by clicking **File->New->Project**.
2. The Create a new project window will open. In that, select the **WPF App (.NET Framework)** option and click **Next**. ![Create a new project2](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Create-a-new-project2.png)
3. Provide a name for your project and click **Create**. ![Configure a new project2](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Configure-a-new-project2.png)

Now the project will be created. ![Code of new project2](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Code-of-new-project2.png)

1. Delete the App.xaml and App.xaml.cs files, as they are not required.
2. Double-click the **Properties** option and change the **Output type** of the application to **Class Library**.

1. ![Changing the output type of the project](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Changing-the-output-type-of-the-project.png)In the MainWindow.xaml, provide the required design for the installer. In this example, we have provided a simple design for Install and Uninstall. ![design the installers](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/design-the-installers.png)

The following is the code snippet for the design.

**MainWindow.xaml:**

```xml
<Window x:Class="CustomBootstrapperApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CustomBootstrapperApplication"
        mc:Ignorable="d"
        Title="My Sample Bootstrapper Application" Width="450"  Height="450" WindowStartupLocation="CenterScreen" Foreground="#F05662"  ResizeMode="CanMinimize" FontFamily="Segoe UI" Background="Black">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="AdditionalStyles.xaml"/>
            </ResourceDictionary.MergedDictionaries>            
        </ResourceDictionary>
    </Window.Resources>
    <Grid Background="#f7f7f7">
        <Label Content="WELCOME TO THE TEST" HorizontalAlignment="Left" Margin="40,40" FontStyle="Normal" Foreground="#606060" FontSize="20px"></Label>
        <Label Content="BOOTSTRAP" HorizontalAlignment="Left" Margin="40,60" FontWeight="Bold" FontSize="44px" Foreground="#F05662"></Label>
        <Label Content="APPLICATION" HorizontalAlignment="Left" Margin="40,105" FontWeight="Bold" FontSize="44px" Foreground="#F05662"></Label>
        <StackPanel Height="300" Width="400" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,150,0,0">
            <ProgressBar x:Name="progressBar" Height="20" Width="350" Background="White" VerticalAlignment="Bottom" Margin="0,80,0,0" Style="{StaticResource ProgressBarstyle}"/>
            <Label x:Name="process" Content="" FontStyle="Normal" Margin="20,0,0,0" Foreground="#606060" FontSize="14px"/>
            <StackPanel Orientation="Horizontal" Margin="0,100,0,0" HorizontalAlignment="Right">
                <Button Content="EXIT" Height="35" Width="120"  Click="Exit_Button_Click" Background="White" Foreground="#F05662" BorderBrush="Red" Style="{DynamicResource PrimaryButtonStyle}"/>
                <Button Content="INSTALL" Height="35" Width="120" Margin="20,0,0,0"  Visibility="Visible"  Name="Install_Button" Click="Install_Button_Click" Background="#F05662" Style="{DynamicResource PrimaryButtonStyle}" BorderBrush="Red"/>
                <Button Content="UNINSTALL" Visibility="Visible" Height="35" Width="120" Margin="20,0,0,0" Style="{DynamicResource PrimaryButtonStyle}" Name="Uninstall_Button" Click="Uninstall_Button_Click" Background="#F05662" BorderBrush="#F05662" />
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>
```

1. As we have added styles to the design, add the XAML file to the project and include the necessary code for the design. Right-click the project, click **Add->New Item** and search for xaml in the search box. Select **Resource Dictionary (WPF)**, provide name for the file, and click **Add**. ![Add a resource dictionary](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Add-a-resource-dictionary.png)

**AdditionalStyles.xaml:**

```xml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:CustomBootstrapperApplication">
 
    <Style x:Key="PrimaryButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="#0450CC"/>
        <Setter Property="BorderBrush" Value="#0450CC"/>
        <Setter Property="Foreground" Value="#FFFFFF"/>
        <Setter Property="BorderThickness" Value="0.5"/>
        <Setter Property="HorizontalContentAlignment" Value="Center"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="HorizontalAlignment" Value="Right"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Padding" Value="1"/>
        <Setter Property="FontSize" Value="13"/>
        <Setter Property="FontWeight" Value="SemiBold"/>
        <Setter Property="FontFamily" Value="Resources\Font\#ASAP"/>
        <Setter Property="Focusable" Value="True"/>
        <Setter Property="Width" Value="84"/>
        <Setter Property="Height" Value="32"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border x:Name="border" CornerRadius="14" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
                        <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Background" TargetName="border" Value="#F05662"/>
                            <Setter Property="BorderBrush" TargetName="border" Value="#F05662"/>
                            <Setter Property="Opacity" Value="0.5"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
 
    <!--Control colors.-->
    <Color x:Key="WindowColor">#FFE8EDF9</Color>
    <Color x:Key="ContentAreaColorLight">#FFC5CBF9</Color>
    <Color x:Key="ContentAreaColorDark">#FF7381F9</Color>
 
    <Color x:Key="DisabledControlLightColor">#FFE8EDF9</Color>
    <Color x:Key="DisabledControlDarkColor">#FFC5CBF9</Color>
    <Color x:Key="DisabledForegroundColor">#FF888888</Color>
 
    <Color x:Key="SelectedBackgroundColor">#FFC5CBF9</Color>
    <Color x:Key="SelectedUnfocusedColor">#FFDDDDDD</Color>
 
    <Color x:Key="ControlLightColor">White</Color>
    <Color x:Key="ControlMediumColor">#FFF05662</Color>
    <Color x:Key="ControlDarkColor">#FFF05662</Color>
 
    <Color x:Key="ControlMouseOverColor">#FF3843C4</Color>
    <Color x:Key="ControlPressedColor">#FF211AA9</Color>
 
 
    <Color x:Key="GlyphColor">#FF444444</Color>
    <Color x:Key="GlyphMouseOver">sc#1, 0.004391443, 0.002428215, 0.242281124</Color>
 
    <!--Border colors-->
    <Color x:Key="BorderLightColor">#FFCCCCCC</Color>
    <Color x:Key="BorderMediumColor">#FF888888</Color>
    <Color x:Key="BorderDarkColor">#FF444444</Color>
 
    <Color x:Key="PressedBorderLightColor">#FF888888</Color>
    <Color x:Key="PressedBorderDarkColor">#FF444444</Color>
 
    <Color x:Key="DisabledBorderLightColor">#FFAAAAAA</Color>
    <Color x:Key="DisabledBorderDarkColor">#FF888888</Color>
 
    <Color x:Key="DefaultBorderBrushDarkColor">Black</Color>
 
    <!--Control-specific resources.-->
    <Color x:Key="HeaderTopColor">#FFC5CBF9</Color>
    <Color x:Key="DatagridCurrentCellBorderColor">Black</Color>
    <Color x:Key="SliderTrackDarkColor">#FFC5CBF9</Color>
 
    <Color x:Key="NavButtonFrameColor">#FF3843C4</Color>
 
    <LinearGradientBrush x:Key="MenuPopupBrush"
                     EndPoint="0.5,1"
                     StartPoint="0.5,0">
        <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="0" />
        <GradientStop Color="{DynamicResource ControlMediumColor}"
                Offset="0.5" />
        <GradientStop Color="{DynamicResource ControlLightColor}"
                Offset="1" />
    </LinearGradientBrush>
 
    <LinearGradientBrush x:Key="ProgressBarIndicatorAnimatedFill"
                     StartPoint="0,0"
                     EndPoint="1,0">
        <LinearGradientBrush.GradientStops>
            <GradientStopCollection>
                <GradientStop Color="#F05662"
                    Offset="0" />
                <GradientStop Color="#F05662"
                    Offset="0.4" />
                <GradientStop Color="#F05662"
                    Offset="0.6" />
                <GradientStop Color="#F05662"
                    Offset="1" />
            </GradientStopCollection>
        </LinearGradientBrush.GradientStops>
    </LinearGradientBrush>
    <Style x:Key="ProgressBarstyle"
       TargetType="{x:Type ProgressBar}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ProgressBar}">
                    <Grid MinHeight="10"
              MinWidth="200"
              Background="{TemplateBinding Background}">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Determinate" />
                                <VisualState x:Name="Indeterminate">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Duration="00:00:00"
                                                 Storyboard.TargetName="PART_Indicator"
                                                 Storyboard.TargetProperty="Background">
                                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <SolidColorBrush>Transparent</SolidColorBrush>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames>
 
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="PART_Track"
                  CornerRadius="2"
                  BorderThickness="1">
                            <Border.BorderBrush>
                                <SolidColorBrush Color="#F05662" />
                            </Border.BorderBrush>
                        </Border>
                        <Border x:Name="PART_Indicator"
                  CornerRadius="2"
                  BorderThickness="1"
                  HorizontalAlignment="Left"
                  Background="{TemplateBinding Foreground}"
                  Margin="3">
                            <Border.BorderBrush>
                                <LinearGradientBrush StartPoint="0,0"
                                   EndPoint="0,1">
                                    <GradientBrush.GradientStops>
                                        <GradientStopCollection>
                                            <GradientStop Color="{DynamicResource BorderLightColor}"
                                  Offset="0.0" />
                                            <GradientStop Color="{DynamicResource BorderMediumColor}"
                                  Offset="1.0" />
                                        </GradientStopCollection>
                                    </GradientBrush.GradientStops>
                                </LinearGradientBrush>
 
                            </Border.BorderBrush>
                            <Grid ClipToBounds="True"
                  x:Name="Animation">
                                <Rectangle x:Name="PART_GlowRect"
                         Width="100"
                         HorizontalAlignment="Left"
                         Fill="{StaticResource ProgressBarIndicatorAnimatedFill}"
                         Margin="-100,0,0,0" />
                            </Grid>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0,1"
                           StartPoint="0,0">
                    <GradientStop Color="{DynamicResource ControlLightColor}"
                      Offset="0" />
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                      Offset="1" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="Foreground">
            <Setter.Value>
                <LinearGradientBrush EndPoint="0.5,1"
                           StartPoint="0.5,0">
                    <GradientStop Color="{DynamicResource ControlMediumColor}"
                      Offset="0" />
                    <GradientStop Color="{DynamicResource ControlDarkColor}"
                      Offset="1" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
```

1. Add BootstrapperCore.dll and Microsoft.Deployment.WindowsInstaller.dll as references from the WiX installed location. ![Adding BootstrapperCore and WindowsInstaller](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Adding-BootstrapperCore-and-WindowsInstaller.png) ![Adding BootstrapperCore and WindowsInstaller as reference](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Adding-BootstrapperCore-and-WindowsInstaller-as-reference.png)
2. In the MainWindow.xaml.cs file, include the namespace for the bootstrapper.

**MainWindow.xaml.cs:**

```csharp
using Microsoft.Tools.WindowsInstallerXml.Bootstrapper;
```

![include the namespace for the bootstrapper](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/include-the-namespace-for-the-bootstrapper.png)  
Include the necessary bootstrapper events, properties, and methods for different button-click events in the MainWindow.xaml.cs file:

- **_DetectPackageComplete_** —This event checks whether the package is already installed or not.
- **_PlanComplete_** —This event is triggered when planning to install is done. It informs the burn to proceed with the installation.
- **_ExecuteBegin_** —This event is triggered when the bootstrapper engine has started installing or uninstalling the packages.
- **_ExecuteComplete_** —This event is triggered when the bootstrapper engine has completed installing or uninstalling the packages.
- **_ExecuteProgress_** —This event gets fired by the engine while executing on payload.

**MainWindow.xaml.cs:**

```csharp
using Microsoft.Tools.WindowsInstallerXml.Bootstrapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
 
namespace CustomBootstrapperApplication
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool isInstall;
        /// <summary>
        /// Initializes a new instance of the MainView class.
        /// </summary>
        public MainWindow(BootstrapperApplication bootstrapper)
        {
            InitializeComponent();
            this.Bootstrapper = bootstrapper;
            this.Bootstrapper.DetectPackageComplete += this.OnDetectPackageComplete;
            this.Bootstrapper.PlanComplete += this.OnPlanComplete;
            this.Bootstrapper.ExecuteProgress += this.OnExecuteProgress;
            this.Bootstrapper.ExecuteComplete += this.OnExecuteComplete;
            this.Bootstrapper.ExecuteBegin += this.OnExecuteBegin;
        }
        public BootstrapperApplication Bootstrapper { get; private set; }
 
        private void Exit_Button_Click(object sender, RoutedEventArgs e)
        {
            CustomUI.BootstrapperDispatcher.InvokeShutdown();
        }
 
        private void Install_Button_Click(object sender, RoutedEventArgs e)
        {
            isInstall = true;
            Install_Button.Visibility = Visibility.Collapsed;
            process.Content = "Waiting to Install...";
            Bootstrapper.Engine.Plan(LaunchAction.Install);
        }
 
        private void Uninstall_Button_Click(object sender, RoutedEventArgs e)
        {
            isInstall = false;
            Uninstall_Button.Visibility = Visibility.Collapsed;
            process.Content = "Waiting to Uninstall...";
            Bootstrapper.Engine.Plan(LaunchAction.Uninstall);
        }
 
        private void OnExecuteComplete(object sender, ExecuteCompleteEventArgs e)
        {
             
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
                      delegate ()
                      {
                          if (isInstall)
                          {
                              process.Content = "Installed";
                          }
                          else
                          {
                              process.Content = "Uninstalled";
                          }
                      }));
 
        }
        private void OnExecuteBegin(object sender, ExecuteBeginEventArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
                      delegate ()
                      {
                          if (isInstall)
                          {
                              process.Content = "Installing...";
                          }
                          else
                          {
                              process.Content = "Uninstalling...";
                          }
                      }));
        }
 
        private void OnDetectPackageComplete(object sender, DetectPackageCompleteEventArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
                      delegate ()
                      {
                          if (e.PackageId == "Sample")
                          {
                              if (e.State == PackageState.Absent)
                              {
                                  Install_Button.Visibility = Visibility.Visible;
                                  Uninstall_Button.Visibility = Visibility.Collapsed;
 
                              }
 
                              else if (e.State == PackageState.Present)
                              {
                                  Uninstall_Button.Visibility = Visibility.Visible;
                                  Install_Button.Visibility = Visibility.Collapsed;
 
                              }
                          }
                      }));
        }
 
        private void OnPlanComplete(object sender, PlanCompleteEventArgs e)
        {
            if (e.Status >= 0)
                Bootstrapper.Engine.Apply(System.IntPtr.Zero);
        }
 
        private void OnExecuteProgress(object sender, ExecuteProgressEventArgs e)
        {
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(
                      delegate ()
                      {
                          progressBar.Value = e.ProgressPercentage;
                      }));
        }
    }
}
```

1. Add a class file and include the changes for initializing the custom UI, determining the installation conditions and displaying the UI. ![Add a new class Custom UI](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Add-a-new-class-Custom-UI.png)

**CustomUI.cs:**

```csharp
using Microsoft.Tools.WindowsInstallerXml.Bootstrapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
 
namespace CustomBootstrapperApplication
{
    class CustomUI : BootstrapperApplication
    {
        static public Dispatcher BootstrapperDispatcher { get; private set; }
 
        // public static MainWindow view;
 
        protected override void Run()
        {
            this.Engine.Log(LogLevel.Verbose, "Launching Custom UI");
            BootstrapperDispatcher = Dispatcher.CurrentDispatcher;
 
            MainWindow view = new MainWindow(this);
            view.Bootstrapper.Engine.Detect();
            view.DataContext = view;
            view.Closed += (sender, e) => BootstrapperDispatcher.InvokeShutdown();
            view.Show();
 
            Dispatcher.Run();
            this.Engine.Quit(0);
        }
    }
}
```

1. Add a config file to include the required configurations for the installer. Include the Assembly Name in the **assemblyName** Set **copy local** to **true** for this file.

**BootstrapperCore.config:**

```xml
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="wix.bootstrapper" type="Microsoft.Tools.WindowsInstallerXml.Bootstrapper.BootstrapperSectionGroup, BootstrapperCore">
      <section name="host" type="Microsoft.Tools.WindowsInstallerXml.Bootstrapper.HostSection, BootstrapperCore" />
    </sectionGroup>
  </configSections>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0" />
  </startup>
  <wix.bootstrapper>
    <host assemblyName="CustomBootstrapperApplication">
      <supportedFramework version="v4\Full" />
      <supportedFramework version="v4\Client" />
    </host>
  </wix.bootstrapper>
</configuration>
```

![Add a new applicaion configuration file](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Add-a-new-applicaion-configuration-file.png) ![Customizing host tag](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Customizing-host-tag.png)

1. In the AssemblyInfo.cs file, include the bootstrapper namespace and the changes to make this class a bootstrapper application. The structure will be {assemblyname.class}.

**AssemblyInfo.cs:**

```csharp
using Microsoft.Tools.WindowsInstallerXml.Bootstrapper;
[assembly: BootstrapperApplication(typeof(CustomBootstrapperApplication.CustomUI))]
```

![Adding a namespace to the AssemblyInfo](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Adding-a-namespace-to-the-AssemblyInfo.png) ![Add code example in the Assembly Info](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Add-code-example-in-the-Assembly-Info.png)

1. Now, compile the project and it will be compiled successfully.

### Integrating the custom UI with the bootstrapper project

1. Refer to the [previous steps](#_Creating_a_sample) to create a bootstrapper project. In the bootstrapper project, change the bootstrapper application reference ID to “ **ManagedBootstrapperApplicationHost** ”.

**Bundle.wxs:**

```xml
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost" >
```

![Customize the bundle](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Customize-the-bundle.png)

1. Include the necessary source files for the custom design. The files will be present in the output location of the CustomBootstrapperApplication.

**Bundle.wxs:**

```xml
<Payload SourceFile="C:\Users\syncfusion\Downloads\Output\BootstrapperCore.config"/>
<Payload SourceFile="C:\Users\syncfusion\Downloads\Output\CustomBootstrapperApplication.dll"/>      
<Payload SourceFile="C:\Users\syncfusion\Downloads\Output\Microsoft.Deployment.WindowsInstaller.dll"/>
```

![Add necessary payload to the bundle](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Add-necessary-payload-to-the-bundle.png)

1. Include the default variables for the advanced WiX functionality.

**Bundle.wxs:**

```xml
<WixVariable Id="WixMbaPrereqPackageId" Value="" />
<WixVariable Id="WixMbaPrereqLicenseUrl" Value="" />
```

![Add Wix functionality](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Add-Wix-functionality.png)

1. Include the MSI to be packed and compile the project.

**Bundle.wxs:**

```xml
<MsiPackage SourceFile="C:\Users\syncfusion\Downloads\MSI\SampleWixApplication.msi" Id="Sample" />
```

![Include the MSI](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/Include-the-MSI-1.png)

1. Now, the application will be created with our custom design. ![customized installers](https://www.syncfusion.com/blogs/wp-content/uploads/2020/03/customized-installers1.png)

## Conclusion

I hope you now have a clear idea of creating a simple MSI installer, a simple executable for the MSI installer, and a customized installer with a better user interface. Please share your feedback as a comment to this blog.

Syncfusion has 1,600 components and frameworks for [WinForms](https://www.syncfusion.com/winforms-ui-controls), [WPF](https://www.syncfusion.com/wpf-ui-controls), ASP.NET ([Web Forms](https://www.syncfusion.com/jquery/aspnet-web-forms-ui-controls), [MVC](https://www.syncfusion.com/aspnet-mvc-ui-controls), [Core](https://www.syncfusion.com/aspnet-core-ui-controls)), [UWP](https://www.syncfusion.com/uwp-ui-controls), [Xamarin](https://www.syncfusion.com/xamarin-ui-controls/), [Flutter](https://www.syncfusion.com/flutter-widgets), [JavaScript](https://www.syncfusion.com/javascript-ui-controls), [Angular](https://www.syncfusion.com/angular-ui-components), [Blazor](https://www.syncfusion.com/blazor-components), [Vue](https://www.syncfusion.com/vue-ui-components), and [React](https://www.syncfusion.com/react-ui-components). Use them to boost your application development speed.

The post [Grow from a Newbie to Pro in Creating the Installers](https://www.syncfusion.com/blogs/post/grow-from-a-newbie-to-pro-in-creating-the-installers.aspx) appeared first on [Syncfusion Blogs](https://www.syncfusion.com/blogs).