Integrating Overview
To integrate Velopack into your application, you must initialise the Velopack as early as possible in app startup, and you should add update checking code somewhere.
For .NET applications, you should first install the Velopack NuGet Package.
Application Startup
Velopack requires you add some code to your application startup to handle hooks. This is because Velopack will run your main binary at certain stages of the install/update process with special arguments, to allow you to customise behavior. It expects your app to respond to these arguments in the right way and then exit as soon as possible.
The simplest/minimal way to handle this properly is to add the SDK startup code to your Main()
method. This should be in the "main" binary (the one specified when packaging with --mainExe {exeName}
).
static void Main(string[] args)
{
VelopackApp.Build().Run();
// ... your other startup code below
}
There are a variety of options / callbacks you can specify here to customise Velopack, for example:
static void Main(string[] args)
{
ILogger log = CreateLogger();
VelopackApp.Build()
.WithBeforeUninstallFastCallback((v) => {
// delete / clean up some files before uninstallation
})
.WithFirstRun((v) => {
MessageBox.Show("Thanks for installing my application!");
})
.Run(log);
}
The full list of options for VelopackApp is available here. You can also read more about how hooks work.
A "FastCallback" requires that your application show no UI and exit quickly. When the callback returns, your application will exit. If you do not exit this callback quickly enough your process will be killed.
Configuring Updates
Updates can be accomplished by adding UpdateManager to your app:
private static async Task UpdateMyApp()
{
var mgr = new UpdateManager("https://the.place/you-host/updates");
// check for new version
var newVersion = await mgr.CheckForUpdatesAsync();
if (newVersion == null)
return; // no update available
// download new version
await mgr.DownloadUpdatesAsync(newVersion);
// install new version and restart app
mgr.ApplyUpdatesAndRestart(newVersion);
}
Updates can be done silently in the background, or integrated into your application UI. It's always up to you.
You can host your update packages basically anywhere, here are a few examples:
- Local directory:
new UpdateManager("C:\Updates")
- HTTP server, or S3, Azure Storage, etc:
new UpdateManager("https://the.place/you-host/updates")
- GitHub Releases:
new UpdateManager(new GitHubSource("https://github.com/yourName/yourRepo")
There are a variety of built-in sources (eg. GithubSource, SimpleWebSource) you can use when checking for updates, but you can also build your own by deriving from IUpdateSource.
Check for updates
CheckForUpdatesAsync
will read the provided update source for a releases.{channel}.json
file to retrieve available updates (Read about channels). If there is an update available, a non-null UpdateInfo will be returned with some details about the update. You can also retrieve any release notes which were provided when the update was packaged.
There are also some options which can be passed in to UpdateManager to customise how updates are handled, eg. to allow things like switching channels.
Download updates
DownloadUpdatesAsync
will attempt to download deltas (if available) and re-construct the latest full release. If there are no deltas available, or the delta reconstruction fails, the latest full release package will be downloaded instead. Note that if an option like AllowVersionDowngrade
is specified, the downloaded version might be older than the currently executing version.
Apply updates
Once the update has downloaded, you have a few options available. Calling ApplyUpdatesAndRestart
or ApplyUpdatesAndExit
will exit your app, install any bootstrap prerequisites, install the update, and then optionally restart your app right away.
If you do not want to exit your app immediately, you can call WaitExitThenApplyUpdates
instead, which will launch Update.exe and wait for 60 seconds before proceeding. If your app has not exited within 60 seconds it will be killed.
Lastly, if you do not call any of these "Apply" methods, when you re-launch your app, by default, Velopack will detect that there is a pending update and install it then. If you wish to disable this, you should call VelopackApp.Build().SetAutoApplyOnStartup(false)
.
It is recommended that you use one of the functions which explicitly applies a package (eg. ApplyUpdatesAndRestart
), and do not rely on the AutoApply behavior as a rule of thumb. The auto behavior will only apply a downloaded version if it is > the currently installed version, so will not work if trying to downgrade or switch channels, and if more than one instance of your process is running it could result in the update failing or those other processes being terminated.
How updates work
On Windows
In a typical Windows install the application structure will look like this:
%LocalAppData%
└── {packId}
├── current
│ ├── YourFile.dll
│ ├── sq.version
│ └── YourApp.exe
└── Update.exe
sq.version
is a special file created by Velopack which contains some metadata about your currently installed application. During install/uninstall, the entire {packId}
folder is replaced or removed. During updates, only the current
folder is replaced. If you store settings in the same folder as your main binary, they will be erased during updates.
Since current
is replaced with the new version during updates, it's not safe to store settings, logs, etc in the current
dir where your app lives. See Preserving Files for more info.
On Linux & Mac
On these platforms, the app is stored as a single (typically read-only) bundle like .app
or .AppImage
. The bundle is replaced during updates in a single atomic operation.
If you have any files you wish to persist (settings, logs, etc) you must find a directory elsewhere on the filesystem to store these files.