GithubHelp home page GithubHelp logo

velopack / velopack Goto Github PK

View Code? Open in Web Editor NEW
344.0 9.0 25.0 211.54 MB

Installer and automatic update framework for cross-platform desktop applications

Home Page: https://velopack.io

License: MIT License

Rust 15.15% C# 84.73% PowerShell 0.07% Batchfile 0.05%
automatic-updates autoupdate desktop dotnet installer macos osx squirrel updater windows

velopack's Introduction

Velopack Logo

Nuget Nuget vPre Discord Build Codecov License Hits

Velopack is an installation and auto-update framework for cross-platform applications. It's opinionated, extremely easy to use with zero config needed. With just one command you can be up and running with an installable application, and it's lightning fast for your users, too.

Features

  • ๐Ÿ˜ Zero config โ€“ Velopack takes your compiler output and generates an installer, updates, delta packages, and self-updating portable package in just one command.
  • ๐ŸŽฏ Cross platform โ€“ Velopack supports building packages for Windows, OSX, and Linux, so you can use one solution for every target.
  • ๐Ÿš€ Automatic migrations - If you are coming from other popular frameworks (eg. Squirrel), Velopack can automatically migrate your application.
  • โšก๏ธ Lightning fast โ€“ Velopack is written in Rust for native performance. Delta packages mean your user only downloads what's changed between versions.
  • ๐Ÿ“” Language agnostic - With support for C#, C++, JS, Rust and more. Use a familiar API for updates no matter what language your project is.
cli_demo.mp4

Documentation

Community

Contributing

Testimonials

I have now got my external facing application using velopack. I am very impressed. Seems to work fabulously well and be much faster both in the initial build and in the upgrading of the software on the end user's machine than Squirrel was. It's amazing and the best installer I've ever used in over 30 years of development. Thanks so much! You are doing some great work! - Stefan (Discord)

Just wanted to say a huge thank you. I've been using Clowd.Squirrel for a couple of years now since Squirrel.Windows wasn't working for me. Just popped into that repository today to look for some documentation and noticed the release of Velopack. How unexpected! It works fantastic and is so much faster, wow! Thank you again, the amount of work that went into both Clowd.Squirrel and Velopack is staggering. It's very appreciated. - Kizari (Discord)

I've used a lot of installer frameworks and Velopack is by far the best. Everything is like magic: you run the installer, and then the app is just open, ready to use. Updates apply and relaunch in ~2 seconds with no UAC prompts. The installer creation process is painless and integrates easily with code signing, and the command-line tool makes it simple to upload your updater files. You don't need to futz with separate installer scripts in some weird language; you can build all those hooks into your main app! The support is also phenominal; every concern I've had has been addressed. This is the future of desktop installers. - RandomEngy (Discord)

velopack's People

Contributors

aarnott avatar anaisbetts avatar barrythepenguin avatar bitdisaster avatar caesay avatar christianrondeau avatar damieng avatar flagbug avatar geertvanhorrik avatar gojanpaolo avatar horb avatar humbertoc26 avatar johnthomson avatar keboo avatar kevfromireland avatar kizari avatar lennartajansson avatar luislhg avatar mungojam avatar mwcampbell avatar neilsorensen avatar nullif avatar patroza avatar peters avatar ran-intendu avatar robmen avatar shiftkey avatar shoelzer avatar thieum avatar willdean avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

velopack's Issues

Support localization of installer/update dialogs

It would be great if an option to provide translation files to the packaging library could allow for the installer to be set to current Windows language or otherwise default to English.
Currently info and error message boxes display strings that are hardcoded e.g "already installed" message, would be great if they could be used as placeholder instead and grab contents of a (for example) json file.

Support Machine-Wide installer by default

It would be great if a developer could specify an app to be Machine-Installed instead of User-Installed by default. We are deploying our apps into AD environments where users constantly switch computers they use and having to reinstall the app on each computer, due to it installing into AppData/Local in becoming a pain point.

Something like what Squirrel did would be awesome: https://github.com/Squirrel/Squirrel.Windows/blob/develop/docs/using/machine-wide-installs.md

Use a memory log target in Windows installer

If the Setup.exe crashes, there's no great way to see the logs, since there is no automatic file source. You can log to a file using the --log parameter, but it would be better if we logged to a memory source, and then popped an error dialog with a "Open Log" button. If the user clicks this button we should write the log to a temp file and open it in Notepad.

Failure to apply update when the application directory is locked by another process

Just a heads up here. I know its early in the project but I was a user of Squirrel.Clowd just trying out this new project. My project which worked perfectly fine with the previous squirrel is stuck in an update loop. It seems like from the logs, Its because the folder is in use.

For context, the app im porting is a ConsoleApp in .net 8. It has a specific "update" command. So powershell does have a lock on it when its being used.

Heres some relevant logs which show the issue

03:35:54 [INFO] Starting Velopack Updater (0.0.82)
03:35:54 [INFO]     Location: C:\Users\MyUserAccount\AppData\Local\MyApp\Update.exe
03:35:54 [INFO]     Verbose: false
03:35:54 [INFO]     Silent: false
03:35:54 [INFO]     Log File: None
03:35:54 [INFO] Command: Apply
03:35:54 [INFO]     Restart: true
03:35:54 [INFO]     Wait: true
03:35:54 [INFO]     Package: None
03:35:54 [INFO]     Exe Args: Some(["update"])
03:35:54 [INFO]     No Elevate: false
03:35:54 [INFO] Loaded manifest for application: MyApp
03:35:54 [INFO] Root Directory: C:\Users\MyUserAccount\AppData\Local\MyApp
03:35:54 [INFO] Reading parent process information.
03:35:54 [INFO] Waiting 60000ms for parent process (115776) to exit.
03:35:54 [WARN] Failed to wait for parent process to exit (Failed to wait for parent process to exit.).
03:35:54 [INFO] Attempting to open global system mutex: 'velopack-MyApp'
03:35:54 [INFO] No package specified, searching for latest.
03:35:55 [INFO] Found 1.0.0: 'C:\Users\MyUserAccount\AppData\Local\MyApp\packages\MyApp-1.0.0-full.nupkg'
03:35:55 [INFO] Found 1.0.1: 'C:\Users\MyUserAccount\AppData\Local\MyApp\packages\MyApp-1.0.1-win-full.nupkg'
03:35:55 [INFO] Checking application pre-requisites...
03:35:55 [INFO] Applying package to current: 1.0.1
03:35:55 [INFO] Running --veloapp-obsolete hook...
03:35:55 [INFO] Hook executed successfully (took 92.24911ms)
03:35:55 [INFO] Checking for running processes in: C:\Users\MyUserAccount\AppData\Local\MyApp
03:35:55 [WARN] Killing process: C:\Users\MyUserAccount\AppData\Local\MyApp\current\MyApp.exe (115776)
03:35:55 [WARN] Skipping killing self: C:\Users\MyUserAccount\AppData\Local\MyApp\Update.exe (110652)
03:35:55 [INFO] Renaming directory 'C:\Users\MyUserAccount\AppData\Local\MyApp\current' to 'C:\Users\MyUserAccount\AppData\Local\MyApp\current_jlgn8Qtx' to allow rollback...
03:35:55 [INFO] Checking for running processes in: C:\Users\MyUserAccount\AppData\Local\MyApp\current
03:35:55 [WARN] Retrying operation in 333ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:35:55 [WARN] Retrying operation in 666ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:35:56 [WARN] Retrying operation in 1000ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:35:57 [WARN] Last retry in 1000ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:35:58 [ERROR] Failed to apply package: Failed to rename directory 'C:\Users\MyUserAccount\AppData\Local\MyApp\current' to 'C:\Users\MyUserAccount\AppData\Local\MyApp\current_jlgn8Qtx' (The process cannot access the file because it is being used by another process. (os error 32)).
03:35:58 [INFO] Will try to elevate permissions and try again...
03:36:00 [INFO] Attempting to elevate: C:\Users\MyUserAccount\AppData\Local\MyApp\Update.exe ["apply", "--noelevate", "--restart", "--", "update"]
03:36:02 [INFO] Starting Velopack Updater (0.0.82)
03:36:02 [INFO]     Location: C:\Users\MyUserAccount\AppData\Local\MyApp\Update.exe
03:36:02 [INFO]     Verbose: false
03:36:02 [INFO]     Silent: false
03:36:02 [INFO]     Log File: None
03:36:02 [INFO] Command: Apply
03:36:02 [INFO]     Restart: true
03:36:02 [INFO]     Wait: false
03:36:02 [INFO]     Package: None
03:36:02 [INFO]     Exe Args: Some(["update"])
03:36:02 [INFO]     No Elevate: true
03:36:02 [INFO] Loaded manifest for application: MyApp
03:36:02 [INFO] Root Directory: C:\Users\MyUserAccount\AppData\Local\MyApp
03:36:02 [INFO] Attempting to open global system mutex: 'velopack-MyApp'
03:36:02 [INFO] No package specified, searching for latest.
03:36:02 [INFO] Found 1.0.0: 'C:\Users\MyUserAccount\AppData\Local\MyApp\packages\MyApp-1.0.0-full.nupkg'
03:36:02 [INFO] Found 1.0.1: 'C:\Users\MyUserAccount\AppData\Local\MyApp\packages\MyApp-1.0.1-win-full.nupkg'
03:36:02 [INFO] Checking application pre-requisites...
03:36:02 [INFO] Applying package to current: 1.0.1
03:36:02 [INFO] Running --veloapp-obsolete hook...
03:36:02 [INFO] Hook executed successfully (took 98.5044ms)
03:36:02 [INFO] Checking for running processes in: C:\Users\MyUserAccount\AppData\Local\MyApp
03:36:02 [WARN] Skipping killing self: C:\Users\MyUserAccount\AppData\Local\MyApp\Update.exe (107936)
03:36:02 [INFO] Renaming directory 'C:\Users\MyUserAccount\AppData\Local\MyApp\current' to 'C:\Users\MyUserAccount\AppData\Local\MyApp\current_PioLOhTH' to allow rollback...
03:36:02 [INFO] Checking for running processes in: C:\Users\MyUserAccount\AppData\Local\MyApp\current
03:36:02 [WARN] Retrying operation in 333ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:36:02 [WARN] Retrying operation in 666ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:36:03 [WARN] Retrying operation in 1000ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:36:04 [WARN] Last retry in 1000ms... (error was: Some(Os { code: 32, kind: Uncategorized, message: "The process cannot access the file because it is being used by another process." }))
03:36:05 [ERROR] Failed to apply package: Failed to rename directory 'C:\Users\MyUserAccount\AppData\Local\MyApp\current' to 'C:\Users\MyUserAccount\AppData\Local\MyApp\current_PioLOhTH' (The process cannot access the file because it is being used by another process. (os error 32)).
03:36:05 [ERROR] Error applying package: Failed to rename directory 'C:\Users\MyUserAccount\AppData\Local\MyApp\current' to 'C:\Users\MyUserAccount\AppData\Local\MyApp\current_PioLOhTH' (The process cannot access the file because it is being used by another process. (os error 32)).
03:36:05 [INFO] Verifying authenticode signatures of prospective launch binary...
03:36:05 [INFO] About to launch: 'C:\Users\MyUserAccount\AppData\Local\MyApp\current\MyApp.exe' in dir 'C:\Users\MyUserAccount\AppData\Local\MyApp\current'
03:36:05 [INFO] Args: CommandArgs { inner: [Regular("update")] }

Support for x86 platforms

I've been using clowd.squirrel and would like to migrate to velopack but I can't create an installer for 32 bit systems.
Will this come in the future or is 32bit support dropping completely

dotnet bootstrapping types aspnetcore and runtime results in 404 during installation

When providing net8.0-x64-aspnetcore or net8.0-x64-runtime to the --framework argument, the installer fails with a "Setup Error" as seen below.
image

aspnetcore logs:

16:04:02 [INFO] Checking application pre-requisites...
16:04:02 [INFO]     .NET 8.0.2 X64 AspNetCore is missing.
16:04:04 [INFO] Downloading 1 missing pre-requisites...
16:04:04 [ERROR] An error has occurred: https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/8.0/latest.version: status code 404

Extend Velopack.Build to support enhanced debugging

The Velopack.Build project provides msbuild integration, and it would be sweet if it was capable of modifying the build output to emit important files and folder structure (like Update.exe, sq.version, etc) so that the resulting app could be debugged by visual studio.

This diagnostics mode should default to ON in debug configuration, and OFF in release configuration, but can be overridden in the csproj.

The 3 things required for debugging to work is:

  • build output created in a {build}\current sub-folder.
  • Update.exe copied to {build}\Update.exe.
  • {build}\current\sq.version manifest created containing product name, version etc.

Improve MacOS privilege escalation

Current approach

Currently we use applescript (eg. do shell script ... with administrator privileges) if root is required (eg. the app is in /Applications). This is not recommended by apple, and requires that the application request a password each time the user installs an update. The dialog shown is a very generic "oascript is requesting escalation" dialog which we can't customise, and does not support fingerprint auth.

In general, it would be nice if we could avoid the prompt altogether, or barring that, show a nicer dialog and/or enable fingerprints.

A review of the available alternatives

AuthorizationExecuteWithPrivileges is pretty much the perfect solution - to execute a binary elevated by filepath & arguments, but this has been deprecated for a long time (since 10.7) and I believe it's no longer functional in recent os versions.

SMJobSubmit is the closest replacement I think, and it's still used by Sparkle despite also being deprecated since 10.10. According to the comment in the sparkle codebase:

SMJobSubmit is deprecated but is the only way to submit a non-permanent helper and allows us to submit to user domain without requiring authorization

I assume since it's still used by Sparkle this API is still functional, but I suppose it could be removed at any time.

SMJobBless is a more recent/recommended API, but it comes with it's own challenges. SMJobBless results in the helper binary being permanently copied into a system location, and being run permanently as a launchd service. You need to communicate with this service using IPC / XPC. If the process exits, it will automatically be restarted by the OS. Despite SMJobBless creating a strong 1-1 relationship between a root level helper and it's applet, this helper service will persist even if the app is removed. It's not possible for this helper to be shared between apps, because they are connected by code signing identity. I don't think it's acceptable or reasonable to install a system service once per Velopack app, that runs as root, all the time, even if we are not performing an update or the app has been removed. Additionally, SMJobBless was also deprecated (as of 13.0) and the only official way to uninstall a helper (SMJobRemove) is also deprecated (as of 10.10).

Custom launchd daemon could be an option. A custom daemon could be installed/updated automatically during our .pkg postinstall script using launchctl. This has many benefits over SMJobBless. The single daemon could be shared by all velopack apps, and be run on-demand when an app update is necessary. The daemon could be configured to start on-demand, either in response to an incoming TCP connection, directory watch, or even a queue directory (eg. task will run until queue directory is empty). A queue directory would work particularly good: any apps requiring updates would simply place the downloaded update into the queue directory, the daemon would automatically launch and move it into place and then quit.

SMAppService seems similar to SMJobBless, available on 13.0+, however the daemon/helper executable lives inside the app main bundle instead of a system directory, and therefore are removed when the .app is deleted. SMAppService also provides some other api's (eg. registering app to auto-start at login).

Conclusion

If we wish to rely on a "self contained" approach, then we should continue to rely on AppleScript on < 13.0 and implement an embedded daemon via SMAppService for 13.0+. This is complex to implement, and regularly subject to changing/deprecated API's, however is probably the most secure and reliable, since each app and it's update daemon are isolated and not impacted by other apps being installed.

If installing a root launchd daemon (using a queue directory) shared by all velopack apps is an acceptable solution, then this will reduce the complexity and improve the user experience of applying updates. The daemon can be installed and updated automatically any time a .pkg is run, and no prompts will need to be shown when installing updates (mimicking windows behavior). The drawback is that all apps share a single daemon, and if velopack/macos requirements change over time this could cause compatibility issues.

Also see

Support cross-compiling releases to other operating systems

Right now, Velopack only supports bundling packages while running on the same OS that your package is targeting. This issue is just here to track current blockers which need to be solved before cross-compiling can work.

To build packages:

  • On Windows, we use various Win32 API's, and depend on a variety of helper binaries that can't run elsewhere.
  • On Linux, we need AppImage and FUSE support
  • On macOS, we need a handful of native tools (productbuild, ditto, xcrun/notarytool, and so forth)

Building macOS packages on Anything Else - Because of the dependence on native mac tools, we will likely never be able to cross-compile to macOS.

Building Linux packages on Windows - It should be possible to run AppImage / FUSE on WSL, so we need to see how to detect that this is available and use it.

Building Linux packages on macOS - This is going to be difficult because it's not possible to run the AppImageTool on macOS, so we'd need to assemble an AppImage ourselves by downloading the corresponding runtime, creating a squashfs filesystem, and assembling the final package.

Building Windows packages on Anything Else - At the moment, we use a handful of native win32 api's, and native tools (zstd.exe, rcedit.exe, and so forth). Some of this functionality is cosmetic (such as changing an exe icon or resources). It may be possible to replace vital code with cross-platform equivalents, and just skip any non-vital/cosmetic functions. Of interest, I believe there is some cross-platform replacement for HostModel's ResourceManager going into .net9, so we may be able to benefit from that when it's ready. We could also include a build of https://github.com/mtrojnar/osslsigncode for signing

Updating after exiting app

The previous version before the last update was updating my app after a user had logged in and then asking if the user would like to update. On v.0.0.292 the updater doesn't start until a user exits the application. Also, the UpdateManager.ApplyUpdatesAndRestart is marked obsolete in the latest version. I am not sure if this has anything to do with it.

Thanks

Support min OS versions in release feed

Request came from Discord.

When bundling updates, and specifying a min os version (with --rid), update manager should ignore any versions which are not supported by the current operating system.

Support really large files

We don't really support really large files (eg. > 1gb) well at the moment.

  • Stop extracting entire file into memory before writing to file. Fixed in 95a6c9d
  • If building a package with a very large file, the progress appears to hang, because progress is currently calculated based on the number of files copied / zipped / etc. We should calculate progress based on the number of bytes processed, so that the progress output is constant and helpful. This applies to the package builder and the extracter/installer/updater.
  • If the total package size gets too large (eg. > 5gb) the SetupBundle class stops producing valid executables. They just fail to start. I'm not sure if this is because the binary is x86. If we can't fix we should throw an error in the pre-process stage.
  • Zstd does not support really large files, so if any file in the package is too big we should disable deltas and print a warning instead of throwing an error.

Improve wording around Setup Repair dialog

Continuing my testing. I don't have a Web server set up for my test so I just copied the setup EXE across. 1.0.1 is installed, but this is a newer version, 1.0.2, but it brings up a screen that says it is already installed suggesting that I repair the application install. If it is a later version could it please just automatically install the application?

I often have scenarios where I get people to reinstall the whole setup if it's failing to update to newer or I need to force a major update

Including only some files

I'm upgrading from Clowd.Squirrel 3.0, which I haven't yet shipped to customers, so I thought I would upgrade to this before shipping to customers later this week, as I've been so impressed with Clowd.Squirrel. just worked perfectly so far in my testing.

However it does seem to be designed a little differently.

Few points:

  1. In the previous version I could specify an already built nupkg file. This is useful to me because I can then choose which files I want to include. I just tried to do a .net publish and there's all sorts of stuff in there that I don't want.. Can I just put what I want in a folder to use?
  2. Did try and compile it using vpk, but I am building a WPF application and thus have no Program.Main, so it doesn't work "Failed to verify VelopackApp. Ensure you have added the startup code to your Program.Main(): VelopackApp.Build().Run();"
  3. I can't find a way to get my application signed, even if I could compile it. Doesn't seem to be any sort of signing parameters on the command line? As with Clowd.Squirrel, I only want to sign EXE's and not DLLs, presume that's a pack parameter
  4. The previous version had commandline parameters that allowed me to do certain things when it was being installed or uninstalled . Are those available somehow as I need to install other programs and set up my application icons

fyi: I'm seems like I'm running Velopack CLI 0.0.64-g250b6b8 currently.

Am I best just to ship with Clowd.Squirrel 3.0 for the moment?

Thanks!

Exception while trying to sign

System.NullReferenceException: Object reference not set to an instance of an object.
   at Velopack.ProcessStartExtensions.AppendArgumentListSafe(ProcessStartInfo psi, IEnumerable`1 args, String& debug) in ./Velopack/Internal/ProcessExtensions.cs:line 18
   at Velopack.Packaging.Exe.InvokeProcess(String fileName, IEnumerable`1 args, String workingDirectory, CancellationToken ct) in ./Velopack.Packaging/Exe.cs:line 61
   at Velopack.Packaging.Windows.CodeSign.SignPEFileWithTemplate(String filePath, String signTemplate) in ./Velopack.Packaging.Windows/CodeSign.cs:line 103
   at Velopack.Packaging.Windows.Commands.WindowsPackCommandRunner.SignFilesImpl(WindowsSigningOptions options, String rootDir, Action`1 progress, String[] filePaths) in ./Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs:line 208
   at Velopack.Packaging.Windows.Commands.WindowsPackCommandRunner.CodeSign(Action`1 progress, String packDir) in ./Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs:line 29
   at Velopack.Packaging.PackageBuilder`1.<>c__DisplayClass28_0.<<Run>b__3>d.MoveNext() in ./Velopack.Packaging/PackageBuilder.cs:line 124
--- End of stack trace from previous location ---
   at Velopack.Packaging.Progress.RunTask(String name, Func`2 fn) in ./Velopack.Packaging/Progress.cs:line 71
   at Velopack.Packaging.PackageBuilder`1.<>c__DisplayClass28_0.<<Run>b__1>d.MoveNext() in ./Velopack.Packaging/PackageBuilder.cs:line 123
--- End of stack trace from previous location ---
   at Velopack.Packaging.Progress.ExecuteAsync(ILogger logger, Func`2 action) in ./Velopack.Packaging/Progress.cs:line 43
   at Velopack.Packaging.PackageBuilder`1.Run(T options) in ./Velopack.Packaging/PackageBuilder.cs:line 115
   at Velopack.Vpk.Compat.RunnerFactory.CreateAndExecuteAsync[T](String commandName, T options) in ./Velopack.Vpk/Compat/RunnerFactory.cs:line 26

Using signtool seems to work fine. For the setup however after downloading Windows gives warning and tries to block.

Support wizard installer on Windows

The current installer for windows is a one-click installer which has very minimal UI.

It is desirable for some developers to provide an installer which allows the user to customise install location, install optional features, windows services, license acceptance dialogs, and so forth.

On MacOS, the built-in .pkg installer has a lot of this already, so this task would bring windows back up to feature parity with macos. The one-click installer should still be the default, but the solution here would allow a developer to customise the installer further.

Ideally, we will integrate with NSIS or WiX to provide the wizard installer, but since those are very complex tools, we should distil the user experience down to a limited subset of common features and make it very easy to use.

Some possible configuration options:

  • Where to allow installing shortcuts to, and whether to allow user choice
  • Where to install the application eg. appdata, or program files, or custom user choice
  • Firewall rules
  • Custom rtf/html/markdown pages (macos supports welcome, readme, license, conclusion).
  • Features: This needs some more thought. Perhaps to start out with we can support Windows Services as a required or optional feature. Later down the line, maybe custom features can invoke an exe with the usual --install hook. The benefit of this hook as a "feature" rather than the regular hook is that this could be run in a privileged context.

To support updating installs in privileged folders, the updater also needs to know how to prompt for UAC if we hit an access denied error. To support updating windows services, the updater will need to know how request UAC and to stop/start a service.

stuck in downloading .net 8.0.0 x64 windowsdesktop runtime

this is my Target

  <Target Name="CustomPostBuild" AfterTargets="PostBuildEvent">
    <GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
      <Output TaskParameter="Assemblies" ItemName="myAssemblyInfo" />
    </GetAssemblyIdentity>
    <RemoveDir Directories=".\Releases\; .\Feed\" />
    <MakeDir Directories="Feed" />
    <Exec Command="cd Feed &amp;&amp; vpk pack -u CargowiseClient -v $([System.Version]::Parse(%(myAssemblyInfo.Version)).ToString(3)) -p ..\publish -e Cargowise.Blazor.Client.Squirrel.Clowd.exe --framework net8.0-x64-desktop" />
  </Target>

when I click the setup.exe. just got stuck in
image

MacOS symlink's not being preserved

MacOS bundles can have symlinks which need to be preserved through the zipping/extracting/moving process. Need to write some solid tests for this and then work through any remaining issues.

VelopackApp check should handle `async Task Main()`

Unsure what has changed but I am getting the error on VPK that it cant find my Velopack.VelopackApp.Build().Run(); statement which is the very first thing Main does. It has been working so i'm unsure why i'm having issues now. I found this code that looks for the run statement from the IL code. Debugging it i see that theres only 7 instructions (which isnt true, i have around 97 instructions)

image
With async main it loads these instructions
image

Commenting out the async/await and making main non-async I properly load all instructions
image
image

Heres offending code in velopack

            foreach (var instr in entryPoint.CilMethodBody.Instructions) {
                if (instr.OpCode.Code is CilCode.Call or CilCode.Callvirt or CilCode.Calli) {
                    SerializedMemberReference operand = instr.Operand as SerializedMemberReference;
                    if (operand != null && operand.IsMethod) {
                        if (operand.Name == "Run" && operand.DeclaringType.FullName == "Velopack.VelopackApp") {
                            // success!
                            if (velopackVersion != null) {
                                log.Info($"Verified VelopackApp.Run() in '{entryPoint.FullName}', version {velopackVersion}.");
                                if (velopackVersion != VelopackRuntimeInfo.VelopackProductVersion) {
                                    log.Warn(exeFile + " was built with a different version of Velopack than this tool. " +
                                        $"This may cause compatibility issues. Expected {VelopackRuntimeInfo.VelopackProductVersion}, " +
                                        $"but found {velopackVersion}.");
                                }
                                return velopackVersion;
                            } else {
                                log.Warn("VelopackApp verified at entry point, but ProductVersion could not be checked.");
                                return null;
                            }
                        }
                    }
                }
            }

Unable to verify VelopackApp when VelopackApp.Build() wrapped in another method

Hey, after migrating from clowd.squirrel to velopack I was calling SquirrelAwareApp.HandleEvents not directly in main method - it was wrapped in another method. When updating to velopack I endup with this code:

    public static int Main(string[] args)
    {
        Log.Information("Starting up!");

        try
        {
            CreateAndRunHostBuilder(args);
            return 0;
        }
        catch (Exception ex)
        {
            return 1;
        }
    }

    private static void CreateAndRunHostBuilder(string[] args)
    {
        var hostBuilder = OfficeHost.CreateDefaultBuilder(args);
        VelopackApp.Build()
            .WithFirstRun(VelopackEventHandlers.OnAppInstall)
            .Run();

        var host = hostBuilder.ConfigureServices(x =>
            {
               //Registering services
            })
            .Build();

        host.Run();
    }

But this throws Unable to verify VelopackApp exception when trying vpk pack.
Its not big deal for me as I can just move the code but I can imagine in future lot of people will complain about this.
I was looking in the source code how the check is done and yeah Iam not sure if this is the "perfect" path to check (but seems better then the previous marking the project with SquirreAware app attribute.)

I you have any idea how we could improve that I am willing help.

A way to use a dynamic UpdateUrl ?

Hi,
Is there a way to avoid hard-coding UpdateUrl in Porgram.cs, to avoid having to toggle (and sometimes forget) changing it say from localhost to the live server?

Would it be possible to have the option of it always falling back to wherever Url the latest update was downloaded from?

Portable stub.exe is not being signed

All binaries are signed by my cert but stub.exe in Portable.zip root (Update.exe is also signed)

Also, how can I give a stub different more friendly name than main executable?

Support file associations

Registering file associations is platform-dependent, so it would be nice if Velopack could handle this.

There should be support in VelopackApp for handling a triggered association, eg.

VelopackApp.Build().OnFileAssociation((ext) => { ... }).Run()

There should be support in the command line tool to provide a list of associations to register, eg.

vpk pack ... --fileAssoc pdb,ext

On MacOS, we only need to write this to the Info.plist, so it will be very easy. On Windows, we'll need to write the associations to the nuspec, and handle registry modifications in the install/update/uninstall. If the associations have changed or added from one version to another they will need to be updated.

Support for Console / CLI Applications

The current support for Console / CLI applications is limited, as auto-updating them can interfere with scripting due to restarts can return flow control back to the script before any work is done.

Consider improving support by adding a stub launcher that does not return flow control until updates and the requested execution has been done.

Desirables for the launcher:

  • Perform updates on the application.
  • Arguments passthrough.
  • stdin / stdout / stderror passthrough.
  • Return code passthrough.
  • Not impacted by updates itself (e.g. lives in root (not current) directory).
  • (Plus, any other things that I might not have considered as I'm fairly new to this framework).

Additionally, when packaging the installer for such an application, optionally being able to add the application to PATH would be ideal.

Support for install without default shortcuts

One of our applications installs as a Windows Service. It does not have any UI requiring launch from a Desktop or Start Menu shortcut. It would be helpful to have an option to disable the creation of the default shortcuts to limit user confusion in this scenario.

Check DOTNET_ROOT for dotnet installations which may not exist at the default location

I have two sugesstions
command like this

vpk pack ... --framework net6.0-x64-desktop

generate instaler that

  1. Do not check DOTNET_ROOT environment variable (ev)

  2. Do not allow ueser to make instalation without net6

  3. In my opinion NET shoulb be detected in cascade way like DOTNET_ROOT localication from systen ev if not user if not just like now

  4. Instalation of NET (or any other reuqiment) sholud be skipable - in case of wrong detection of requied runtime

Pass first-run arguments via Setup.exe

I have to pass the args to my client app to start. But when I click the setup.exe, it seems that it would run my app automatically.
Is there any way I can pass my args to setup and then to my app?

Error bundling cross-compiled application which is unsupported for current CPU architecture

I've published the app using:

dotnet publish TodoSample.Client.Windows.csproj -c Release -o ./publish -r win-arm64

Later I run:

dotnet vpk pack -u TodoSample.Client.Windows -v 1.0.0 -p .\publish -e TodoSample.Client.Windows.exe -r win-x86 --framework net8.0.1-x86-desktop,webview2 --icon .\wwwroot\favicon.ico --packTitle TodoSample

Then I receive the following error:

[19:36:38 FTL] Command ExecutePackWindows had an exception.
    Win32Exception: An error occurred trying to start process
    'C:\Workspace\temp\TodoSample\src\Client\TodoSample.Client.Windows\publish\TodoSample.Client.Windows.exe' with
    working directory 'C:\Workspace\temp\TodoSample\src\Client\TodoSample.Client.Windows'. The specified executable is
    not a valid application for this OS platform.
      at bool StartWithCreateProcess(ProcessStartInfo startInfo)
      at Process Start(ProcessStartInfo startInfo)
      at string Output(ProcessStartInfo psi, int timeoutMs) in ProcessExtensions.cs:67
      at async Task Run(T options) in PackageBuilder.cs:83
      at async Task<int> CreateAndExecuteAsync<T>(string commandName, T options) in RunnerFactory.cs:26

It seems velopack tries to start the app, which is not possible, because arm64 won't run in x64 machine.
But what's the benefit of running the app?
The same issue is making my CD pipeline more complex, because I need to install some stuffs to make sure x86 version of the app runs on my agent which is X64.

Preserve S3 header file headers when updating releases.json

Background:
We're exposing our installer/updater hosted on S3 thru CloudFront for caching/edge-node purposes. Since Velopack updates the release-xxx.json files with new version info we need to set some headers in S3 so CloudFront knows when the file is updated and thus start serving new version of file(s).
Right now the vpk upload s3 command will overwrite the files with empty headers.

Proposed solution:

var metadata = await client.GetObjectMetadataAsync(bucket, key);

Existing code (above) already reads the metadata of the existing S3 file, that metadata should contain the existing headers, and can thus be re-added in PutObjectRequest, something like:
var req = new PutObjectRequest { BucketName = bucket, FilePath = f.FullName, Key = key, Headers = metadata.Headers, };

Allow skipping the VelopackApp builder check

I had no problem previously making builds for my wpf application but now I get this error
Screenshot 2024-01-29 at 5 41 08 PM
The only change I made was updating the velopack version to the latest.

My project generates its main() so I cannot add VelopackApp.Build().Run() to it, but I put it in the startup function that is defined in the app.xaml and it worked fine before but not anymore

When it was working I was on velopack version 0.143

Release notes of Velopack itself?

I'm not talking about embedding release notes in our apps updates, but I would like to see what's new when a new package of Velopack get released on nuget.org (both the Velopack lib and the vpk tool).

There's no release note on the documentation site, no release tab in github, no release section in the readme...

Otherwise I switched my app to use this tool for our deployment and I'm very happy with it so far, so thanks a lot for the efforts!

User-created files in %LocalAppData%/MyApp get deleted on update/reinstall ?

If I understand correctly, the default installation goes to %LocalAppData%/MyApp.

And it seems to me that the entire MyApp folder is removed on update or uninstall or reinstall.

This generates an unwelcome situation where if MyApp needs to save anything to the %LocalAppData%/MyApp at runtime (eg. customized user settings), these risk being deleted.

Is there a workaround to this without having the change MyApp itself?

Thanks :)

PDB files

vpk pack excludes PDB files and thers is no option to change this behavior.

Updating on other partition than C: fails

Hello there,

I've used Velopack to install my application on a different partition.

In this constellation the update process fails.

06:44:04 [INFO] Starting Velopack Updater (0.0.231)
06:44:04 [INFO] Location: E:\RoboWatch\Update.exe
06:44:04 [INFO] Verbose: false
06:44:04 [INFO] Silent: false
06:44:04 [INFO] Log File: None
06:44:04 [INFO] Command: Apply
06:44:04 [INFO] Restart: true
06:44:04 [INFO] Wait: true
06:44:04 [INFO] Package: Some("E:\RoboWatch\packages\RoboWatch-0.1.20-full.nupkg")
06:44:04 [INFO] Exe Args: None
06:44:04 [INFO] Loaded manifest for application: RoboWatch
06:44:04 [INFO] Root Directory: E:\RoboWatch
06:44:04 [INFO] Attempting to open global system mutex: 'velopack-RoboWatch'
06:44:04 [INFO] Reading parent process information.
06:44:04 [INFO] Waiting 60000ms for parent process (1244) to exit.
06:44:04 [INFO] Getting ready to apply package to RoboWatch ver 0.1.19: E:\RoboWatch\packages\RoboWatch-0.1.20-full.nupkg
06:44:04 [INFO] Applying package to current: 0.1.20
06:44:04 [INFO] Checking application pre-requisites...
06:44:04 [INFO] Running --veloapp-obsolete hook...
06:44:04 [INFO] Hook executed successfully (took 102.1527ms)
06:44:04 [INFO] Checking for running processes in: E:\RoboWatch
06:44:04 [WARN] Skipping killing self: E:\RoboWatch\Update.exe (10880)
06:44:04 [INFO] Extracting bundle to C:\Users\ME\AppData\Local\Temp\velopack_Qw1n3KqY
06:44:04 [INFO] Extracting 1233 app files to current directory...
06:44:15 [INFO] Checking for running processes in: E:\RoboWatch
06:44:15 [WARN] Skipping killing self: E:\RoboWatch\Update.exe (10880)
06:44:15 [INFO] Replacing bundle at E:\RoboWatch\current

I have made sure, that there are no other processes accessing the directory to rule out my problem is a duplicate of #4 .

As far as I understands, this is rooted in the updater using the function fs::rename (src/Rust/src/commands/apply_windows_impl.rs:49) which cannot operate on two seperate partitions.

I can think of two different approaches, copying the updated files instead of renaming them or locating the temporary files inside the target directory.

Since I don't have any experience in Rust, let alone replacing the velopack package with a fork, I'm afraid I can not offer to implement and test these changes myself.

Support deploying CPU architecture agnostic dotnet applications

I'm aiming to publish my .NET application in a portable architecture that encompasses solely IL (Intermediate Language). Upon deployment, the application will be dynamically compiled into optimized CPU architecture-specific and OS-tailored machine code via Just-In-Time (JIT) compilation. As a result, such an app would necessitate three distinct dependencies (e.g., dotnet desktop runtime 8.0.1) for x86, x64, and arm64 CPU architectures. It would be greatly beneficial if we could define a set of framework dependencies for each CPU architecture.

dotnet publish ... (There won't be anything like -r win-x64 in dotnet publish command)
dotnet vpk pack --framework-x86 net8.0.1-x86-desktop --framework-x64 net8.0.1-x64-desktop --framework-arm64 net8.0.1-arm-desktop

Deltas for trivial updates

I am excited by this project. A possible great opportunity to move on from ClickOnce. Squirrel seems dead, but from the ashes you seem to have created something pretty exciting. Thanks for your efforts and may I also compliment you on the documentation & marketing site that you've put together. Looks great!

Anyway...

I created an absolute minimal WinForms application with .Net 8 to test using Velopack. I followed the instructions to build a first version and then installed it using the created setup exe file. No problems. I then make a super-trivial change, rebuild and republish. I look to the Releases folder to confirm that the full update is 92MB and the delta is 190KB. All looks good at this point.

For reference these are the build commands (based on your docs):
dotnet publish -c Release --self-contained -r win-x64
vpk pack -u YourAppId -v 1.0.13 -p .\bin\Release\net8.0-windows\win-x64\publish -e VelopackTest.exe --packTitle "Velopack Test Application"

When I run the installed application and call for an update, the update works, but the log file AppData\Local\MyAppID\Velopack.log appears to show both a patch and full update.

I see it appearing to patch VelopackTest.dll, but I also see it later referencing YourAppId-1.0.13-full.nupkg and stating that it is extracting 472 files. Am I just misinterpreting the log data?

14:59:00 [INFO] Starting Velopack Updater (0.0.349)
14:59:00 [INFO]     Location: C:\Users\XXXXXXX\AppData\Local\YourAppId\Update.exe
14:59:00 [INFO]     Verbose: false
14:59:00 [INFO]     Silent: false
14:59:00 [INFO]     Log File: None
14:59:00 [INFO] Command: Patch
14:59:00 [INFO]     Old File: "C:\\Users\\XXXXXXX\\AppData\\Local\\YourAppId\\packages\\VelopackTemp\\temp.1\\lib\\app\\sq.version"
14:59:00 [INFO]     Patch File: "C:\\Users\\XXXXXXX\\AppData\\Local\\YourAppId\\packages\\VelopackTemp\\temp.2\\lib\\app\\sq.version.zsdiff"
14:59:00 [INFO]     Output File: "C:\\Users\\XXXXXXX\\AppData\\Local\\YourAppId\\packages\\VelopackTemp\\temp.3"
14:59:00 [INFO] Loading Dictionary (Size: 407)
14:59:00 [INFO] Decoder loaded. Beginning patch...
14:59:00 [INFO] Patch applied successfully.
14:59:00 [INFO] Starting Velopack Updater (0.0.349)
14:59:00 [INFO]     Location: C:\Users\XXXXXXX\AppData\Local\YourAppId\Update.exe
14:59:00 [INFO]     Verbose: false
14:59:00 [INFO]     Silent: false
14:59:00 [INFO]     Log File: None
14:59:00 [INFO] Command: Patch
14:59:00 [INFO]     Old File: "C:\\Users\\XXXXXXX\\AppData\\Local\\YourAppId\\packages\\VelopackTemp\\temp.1\\lib\\app\\VelopackTest.dll"
14:59:00 [INFO]     Patch File: "C:\\Users\\XXXXXXX\\AppData\\Local\\YourAppId\\packages\\VelopackTemp\\temp.2\\lib\\app\\VelopackTest.dll.zsdiff"
14:59:00 [INFO]     Output File: "C:\\Users\\XXXXXXX\\AppData\\Local\\YourAppId\\packages\\VelopackTemp\\temp.3"
14:59:00 [INFO] Loading Dictionary (Size: 7680)
14:59:00 [INFO] Decoder loaded. Beginning patch...
14:59:00 [INFO] Patch applied successfully.
14:59:06 [INFO] Starting Velopack Updater (0.0.349)
14:59:06 [INFO]     Location: C:\Users\XXXXXXX\AppData\Local\YourAppId\Update.exe
14:59:06 [INFO]     Verbose: false
14:59:06 [INFO]     Silent: false
14:59:06 [INFO]     Log File: None
14:59:06 [INFO] Command: Apply
14:59:06 [INFO]     Restart: true
14:59:06 [INFO]     Wait: false
14:59:06 [INFO]     Wait PID: Some(14200)
14:59:06 [INFO]     Package: Some("C:\\Users\\XXXXXXX\\AppData\\Local\\YourAppId\\packages\\YourAppId-1.0.13-full.nupkg")
14:59:06 [INFO]     Exe Args: None
14:59:06 [INFO] Loaded manifest for application: YourAppId
14:59:06 [INFO] Root Directory: C:\Users\XXXXXXX\AppData\Local\YourAppId
14:59:06 [INFO] Attempting to open global system mutex: 'velopack-YourAppId'
14:59:06 [INFO] Waiting 60000ms for process (14200) to exit.
14:59:06 [INFO] Getting ready to apply package to YourAppId ver 1.0.12: C:\Users\XXXXXXX\AppData\Local\YourAppId\packages\YourAppId-1.0.13-full.nupkg
14:59:06 [INFO] Applying package to current: 1.0.13
14:59:06 [INFO] Checking application pre-requisites...
14:59:06 [INFO] Running --veloapp-obsolete hook...
14:59:06 [INFO] Hook executed successfully (took 118.2532ms)
14:59:06 [INFO] Checking for running processes in: C:\Users\XXXXXXX\AppData\Local\YourAppId
14:59:06 [WARN] Skipping killing self: C:\Users\XXXXXXX\AppData\Local\YourAppId\Update.exe (21768)
14:59:06 [INFO] Extracting bundle to C:\Users\XXXXXXX\AppData\Local\YourAppId\packages\tmp_RxGV3BPn
14:59:06 [INFO] Extracting 472 app files...
14:59:09 [INFO] Checking for running processes in: C:\Users\XXXXXXX\AppData\Local\YourAppId
14:59:09 [WARN] Skipping killing self: C:\Users\XXXXXXX\AppData\Local\YourAppId\Update.exe (21768)
14:59:09 [INFO] Replacing bundle at C:\Users\XXXXXXX\AppData\Local\YourAppId\current
14:59:09 [INFO] Bundle extracted successfully to C:\Users\XXXXXXX\AppData\Local\YourAppId\current
14:59:09 [INFO] Writing uninstall registry key...
14:59:09 [INFO] Running --veloapp-updated hook...
14:59:11 [INFO] Hook executed successfully (took 1556.3842ms)
14:59:11 [INFO] Checking for running processes in: C:\Users\XXXXXXX\AppData\Local\YourAppId
14:59:11 [WARN] Skipping killing self: C:\Users\XXXXXXX\AppData\Local\YourAppId\Update.exe (21768)
14:59:11 [INFO] Package applied successfully.
14:59:11 [INFO] Package version 1.0.13 applied successfully.
14:59:11 [INFO] About to launch: 'C:\Users\XXXXXXX\AppData\Local\YourAppId\current\VelopackTest.exe' in dir 'C:\Users\XXXXXXX\AppData\Local\YourAppId\current'
14:59:11 [INFO] Args: CommandArgs { inner: [] }

If needed, please let me know what additional information I could supply and I'll do my best to supply it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.