Developing Portable Applications

A portable application is self-contained in that it does not access resources outside of the folder in which it is installed and does not require access to the Windows registry. Such applications are designed to be deployed from Zip files or run from portable media such as flash drives.

Portable applications can also be run from a user's home folder and permit an application to be used where the user has insufficient privileges to install software using more conventional methods.

By default QuickSharp applications use local application data folders to store resources and access the registry to persist configuration settings between sessions. By providing the right components and bootstrap settings a driver program can be created to create a portable QuickSharp application.

Creating a portable driver

Creating a portable driver requires two changes to the normal QuickSharp driver setup. First, the application must be instructed to use its installation directory instead of the local application data folder; second, an alternative persistence manager must be used in place of the Windows registry to persist session data to a location local to the application.

Changing the data directory is simply a matter of setting a property in the application's client profile, for example:

profile.DisableUserHome = true;

Replacing the registry will require an alternative storage engine, in this case a SQLite database.

Using the SQLite persistence manager

SQLite is an open source, SQL-based database engine and consists of a single file System.Data.SQLite.dll. This can be obtained from the QuickSharp installation directory or the QuickSharp SDK and is available in x86 and x64 versions for 32- and 64-bit versions of Windows. Although the data provider is a .NET assembly it contains an embedded version of the SQLite database engine which is a native code application. Thus, it is important to use the the version appropriate for your system.

To make use of the SQLite data provider a QuickSharp persistence provider is also required; the SDK contains the file QuickSharp.Persistence.SQLite.dll which is a drop-in replacement for the built-in registry provider.

Building the application

To build a minimal portable application you will need the following files:

QuickSharp.Core.dll
QuickSharp.Persistence.SQLite.dll
WeifenLuo.WinFormsUI.Docking.dll
System.Data.SQLite.dll

Start QuickSharp and copy these files into a new workspace. From the New From Template menu select New QuickSharp Driver and save it as PortableApp.cs or whatever you prefer. Change the code to match this example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Reflection;
using QuickSharp.Core;
using QuickSharp.Persistence.SQLite;

[assembly: AssemblyTitle("PortableApp")]
[assembly: AssemblyDescription("Portable QuickSharp Application")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Portable QuickSharp Application")]
[assembly: AssemblyCopyright("Copyright © 2011")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

//$/r:QuickSharp.Core.dll
//$/r:QuickSharp.Persistence.SQLite.dll

//$/t:winexe
//& RunInOwnWindow

namespace QuickSharp
{
    public static class Program
    {
        [STAThread]
        public static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.ThreadException +=
                new ThreadExceptionEventHandler(ThreadException);

            ClientProfile profile = new ClientProfile();

            profile.ClientName = "PortableApp";
            profile.ClientTitle = "Portable QuickSharp Application";
            profile.CopyrightText = "Version 1.0.0.0";
            profile.ClientIcon = null;
            profile.AboutBoxImage = null;
            profile.AboutBoxTextColor = Color.Black;

            profile.DisableUserHome = true;
            profile.PersistenceProvider = "SQLITE";
            profile.PersistenceKey = "QuickSharp.Core.sqlite";

            profile.CommandLineArgs = args;

            ApplicationManager applicationManager =
                ApplicationManager.GetInstance();

            applicationManager.ClientProfile = profile;

            applicationManager.RegisterPersistenceProvider(
                "SQLITE", SQLitePersistenceManager.GetInstance);

            try
            {
                Application.Run(new MainForm());
            }
            catch (Exception ex)
            {
                ErrorForm ef = new ErrorForm(ex, false);
                ef.ShowDialog();
            }
        }

        private static void ThreadException(object sender,
            System.Threading.ThreadExceptionEventArgs e)
        {
            ErrorForm ef = new ErrorForm(e.Exception, true);
            if (ef.ShowDialog() == DialogResult.OK)
                Application.Exit();
        }
    }
}

All being well you should be able to compile and run the application from the IDE; this should produce a minimal application running completely self-contained within the workspace. On exit, you should see the session database file QuickSharp.Core.sqlite, and the docking window configuration file QuickSharp.Core.config in the workspace.

The application can now be expanded by adding plugins.

Replacing the registry with a SQLite database will introduce a slight performance penalty and you might notice a delay when closing the options editor and on exiting the application. This is caused by the data being written to the database.

Setting the DisableUserHome property to true causes the local application data and application home folders to be combined; any resources that would previously have been installed in the local data folder such as images, templates, snippets and editor configuration files should now be installed in matching locations within the portable application directory. See the corresponding QuickSharp IDE folders for guidance on how to organise the resources required by your portable application.