How to create installer for ASP.NET Core / Angular web app?

Viewed 714

We created an "on-prem" web app and I have been tasked with creating an installer for the app that will programmatically allow the user to choose between a SQLite or SQL Server implementation. I have zero clue on how to do this and have not found any good articles with clear direction.

All I have done is write the following code in my Startup.cs file to choose between two connection strings located in my appsettings.json file. Does anyone know the best way to create/implement an installer? Are there open source solutions for this kind of thing? I feel so lost on this one....

protected virtual IServiceCollection ConfigureDbContext(IServiceCollection services)
        {
            var isSqlServerConnection = Configuration.GetValue<bool>("UseSql");

            if (isSqlServerConnection)
            {
                services.AddDbContext<SecurityDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("Default")).UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll),
                ServiceLifetime.Transient);

                services.AddDbContext<StorageContext>(options =>
                options.UseSqlite(Configuration.GetConnectionString("Default")).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking),
                ServiceLifetime.Transient);
            }
            else
            {
                services.AddDbContext<SecurityDbContext>(options =>
                options.UseSqlite(Configuration.GetConnectionString("Sqlite")).UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll),
                ServiceLifetime.Transient);

                services.AddDbContext<StorageContext>(options =>
                options.UseSqlite(Configuration.GetConnectionString("Sqlite")).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
             , ServiceLifetime.Transient);
            }

            return services;
        }
2 Answers

Create an installer with Visual Studio

  1. Close all but one instance of Visual Studio.
  2. In the running instance, access the menu Tools->Extensions and Updates.
  3. In that dialog, choose Online->Visual Studio Marketplace->Tools->Setup & Deployment.
  4. From the list that appears, select Microsoft Visual Studio 2017 Installer Projects.
  5. Once installed, close and restart Visual Studio. Go to File->New Project and search for the word Installer. You'll know you have the correct templates installed if you see a list that looks something like this:

vs example

  1. Create an installer using a Setup Project to suite your needs. You can easily create a page on the installer where the user chooses SQLite or SQL Server as the data backed for example.

Here are some additional resources on creating an installer and the extension you'd need. You may need another version of the extension depending on your Version of Visual Studio.

https://marketplace.visualstudio.com/items?itemName=VisualStudioClient.MicrosoftVisualStudio2017InstallerProjects

https://codeteddy.com/2016/04/04/creating-an-msi-package-for-c-windows-application-using-a-visual-studio-setup-project/

https://www.add-in-express.com/docs/net-msi-setup-project.php

You can also use "Inno Setup" to create your installer. There are plenty of sample code out there. Basically you need to do a few things.

Preparation: Create your own tool to write info to your appSettings.json. The exe should take in parameters as arguments and generate a appSetting.json file based on those arguments.

  1. In the inno setup files section, set the path to your built artifacts, and your own json generation tool.

//Sample Code

[Files]
    Source: bin\*; DestDir: {app}\bin; Flags: recursesubdirs uninsneveruninstall; Components: Main
    Source: Utilities\AppSettingGenerator.exe; DestDir: {app}\Utilities\AppSettingGenerator.exe; Components: " Main"; Tasks: ; Flags: uninsneveruninstall; 
  1. create a screen to let user select the database engine, sqllite or Sql server.
  2. Create another screen to setup the connection strings.

//Sample Code. Create installer screens.

procedure FormCreatePage(PreviousPageId: Integer);
begin
    pgeInstallType := CreateInputOptionPage(    wpWelcome,
                                                'Select Installation Type',
                                                'Which type of installation do you want to run?',
                                                'Select the type of installation that you would like to run. Click Next when you are ready to continue.',
                                                true,
                                                false
                                             );

    pgeInstallType.Add('Sqllite');
    pgeInstallType.Add('Sql Server');

    pgeInstallType.Values[0] := true;

    
    pgeInput1 := CreateCustomPage(  PreviousPageId,
                                    'Configure Sql Server Connection',
                                    'Please verify the details for those sections highlighted in red before continuing.'
                                 );

    pgeInput2 := CreateCustomPage(  pgeInput1.ID,
                                    'Configure Sql lite Connection',
                                    'Please verify the details for those sections highlighted in red before continuing.'
                                 );
end;

//Sample code. Create UI controls to let user key in the Sql Server connection

pnlSQL := TPanel.Create(pgeInput1);
    with pnlSQL do
        begin
            Parent := pgeInput1.Surface;
            Left := ScaleX(0);
            Top := ScaleY(30);
            Width := ScaleX(413);
            Height := ScaleY(125);
            BevelInner := bvLowered;
        end;

    { lblPnlSQL }
    lblPnlSQL := TLabel.Create(pgeInput1);
    with lblPnlSQL do
        begin
            Parent := pnlSQL;
            Left := ScaleX(340);
            Top := ScaleY(5);
            Width := ScaleX(70);
            Height := ScaleY(13);
            AutoSize := False;
            Caption := 'SQL Server';
            Font.Height := ScaleY(-11);
            Font.Style := [fsBold, fsItalic];
        end;

    { lblSrvName }
    lblSrvName := TLabel.Create(pgeInput1);
    with lblSrvName do
        begin
            Parent := pnlSQL;
            Left := ScaleX(5);
            Top := ScaleY(5);
            Width := ScaleX(66);
            Height := ScaleY(13);
            Caption := 'Server Name:';
            Font.Height := ScaleY(-11);
        end;

    { lblUserID }
    lblUserID := TLabel.Create(pgeInput1);
    with lblUserID do
        begin
            Parent := pnlSQL;
            Left := ScaleX(5);
            Top := ScaleY(25);
            Width := ScaleX(40);
            Height := ScaleY(13);
            Caption := 'User ID:';
            Font.Height := ScaleY(-11);
        end;

    { lblPassword }
    lblPassword := TLabel.Create(pgeInput1);
    with lblPassword do
        begin
            Parent := pnlSQL;
            Left := ScaleX(5);
            Top := ScaleY(46);
            Width := ScaleX(50);
            Height := ScaleY(13);
            Caption := 'Password:';
            Font.Height := ScaleY(-11);
        end;

    { lblDBName }
    lblDBName := TLabel.Create(pgeInput1);
    with lblDBName do
        begin
            Parent := pnlSQL;
            Left := ScaleX(5);
            Top := ScaleY(67);
            Width := ScaleX(80);
            Height := ScaleY(13);
            Caption := 'Database Name:';
            Font.Height := ScaleY(-11);
        end;
  1. Call your appsettingGenerator tool after the parameters are entered on the installer screen.

//Sample Code. Call it at nextbuttonClick and check whether the current page is correct

function NextButtonClick(CurPageID: Integer): Boolean; 
var     i: Integer; 
begin 
  if CurPageID = pgeInput2.ID then      
  begin                                 
    RunExe(gUtilAppsettingGenerator,' -dbuid "' + txtUserID.Text + '"
     -dbpass "' + txtPassword.Text + '" -c "server=' + txtSrvName.Text + ';database='    + txtDBName.Text + '" -dbinst "' + txtDSN.Text + '"', ewWaitUntilTerminated, true); 

end;
Related