Microsoft-ui-xaml: Discussion: Simplify WinUI3 deployment for unpackaged Win32 desktop app

Created on 20 May 2020  路  33Comments  路  Source: microsoft/microsoft-ui-xaml

Discussion: Simplify WinUI3 deployment for unpackaged Win32 desktop app.

Today (and this has been like that for about 20 years...) if I want to write any kind of UI App for Windows (and want to stick with Microsoft tech and languages), I will use one of these:

  • A plain C++ Window Win32 app
  • A Winforms .NET app (C#)
  • A WPF .NET app (C#)

With these technologies, it basically "_just works_".

Note: I favor .NET thanks to its wonderful "Any CPU" compilation feature, to really support any Windows OS w/o pain.

Today, I want to replace old these legacy technologies by WinUI.

The issue:

I've been attended the WinUI Community Call of May 20 2020, and if I understand correctly, the envisaged deployment scenarios for WinUI desktop apps are:

  • packaged app where my app will reference another "WinUI" package => fine, seems pretty easy and (hopefully) seamless for end-user
  • unpackaged app where my app (even in PublishSingleFile mode) will have to ship with possibly hundreds of .dlls and other files that I can't control => huh???

What I'd like is really get rid of Winforms and WPF, but still be able to ship Windows UI apps with a simple deployment model.

This is far from being a cosmetic or nitpicking issue. Not even mentioning the x86 vs x64 problem, try to compile the "Visual layer samples for desktop applications" here https://github.com/microsoft/Windows.UI.Composition-Win32-Samples and you'll see there are already issues with Win2D and the VCRTForwarders because packages and references have not been updated, etc. It doesn't "_just work_". And of course tech support is more important if you have more files to ship.

Proposal:

In an ideal world, I'd like the whole "runtime" payload to be included with the app itself.

But let's be reasonable. It think would be ok for example if when the user starts the app, some download happens to install what's needed to make it work (like when you don't have old .NET frameworks, they are installed automagically) with some sort of bootstrapper technology. And maybe in some future, Windows will have these packages already installed (again, like .NET Framework)

To me it's really a showstopper. The package app model is ok, but most of the times, we don't write packaged apps. If Win32+WinUI deployment is not simple enough I will only move to WinUI for packaged apps.

area-NugetPackage discussion winui3preview

Most helpful comment

@stevenbrix - well the other techs are really the legacy ones : Winforms, WPF, or plain/old Win32/desktop development. They're all very fast to compile, very easy to copy ("deploy") and run. But they are legacy.

For example, today, I can use the Microsoft.Windows.SDK.Contracts nuget with an "old" .NET Framework 4.8, C# 7. From there I can use Windows.UI.Composition which is a dual API, so is allowed in desktop apps, and write my own Direct2D interop layer in C# (w/o Win2D) and benefit from all performance (flip sequential swapchain, etc.). With this type of project, I have a size of 3rd party assemblies reduced to 0K. My compilation Time is 2sec with Visual Studio 2019. Potential deployment issues/risk to customers: 0%. But I don't have all the features that's inside WinUI 3, so I have to write lots of "framework" code.

BTW, initially (Windows XP time if I remember correctly), the first .NET apps required .NET to be installed on Windows before they can run. But it was quite a simple process, just install the .NET redist of that time and off you ran. And then, Windows integrated .NET in its core (sort of), so that part wasn't necessary. Even today, if you run an old .NET 2.x app, Windows will ask and install quite seamlessly the required .NET 2 redist. All these were/are quite transparent for everyone: the developer because it already has the .NET runtime, the user because it's basically one dialog and click away from running (an experience similar to what we have with UWP packaged app from the store).

All 33 comments

As you alluded to, this can be accomplished in .NET apps through PublishSingleFile.

There isn鈥檛 a way to accomplish something similar in C++. if you want an unpackaged Win32 app in c++, you need to ensure the .dlls are copied next to the exe.

@stevenbrix - PublishSingleFile will put everything in a single file? including all native dlls that I can see today in my, say, win-x64 directory? Or are you just talking about the .NET Core side of things (which doesn't answer my overall "deployment" question with regards to what can be done today with legacy techs).

With WinForms and WPF in .NET Core there is a "shared runtime" package one can install and target so one doesn't have to deploy the DLLs. Would it make sense to provide a set of WinUI DLLs in the shared runtime package as well? (If WinUI releases faster than the runtime you'd still have to deploy DLLs if you need a newer version than the runtime package you target contains.)

@weltkante - absolutely, that's exactly my point, a super simple deployment is an absolute must. I personally can't invest on WinUI today w/o any confidence in that area. I'd love to.

"copy -> run"
This is very similar to the experience of existing users.
The existing app was very simple and I hope it will be the same on the Win32 desktop.

@smourier I'm a bit confused by your requirements. Where are you trying to deploy the unpackaged app? Are you just trying to run it on your machine, or do you want to place it on a different machine?

/cc @mikehillberg and @jevansaks

@stevenbrix - I don't want to "deploy" an unpackaged desktop app (as in UWP "deploy"). I'd like it to be very simple to use it, for example just copying an .exe, without having to deploy 300 satellite dll like what's demonstrated in the current WinUI 3 preview. That's what frightens me.

I don't see this as a "requirement", this is what we have today with .NET Winforms, WPF, or with Plain Win32 app using any language or tool: C/C++, MFC, Delphi, QT, whatever. All these tools can produce one binary that can be copied to any Windows (almost, ok, let's say version 10+) machine.

@smourier I'm using the term "deploy" generally to refer to getting an app on a machine and running it. I'm not using it to distinguish between packaged/unpackaged. Is there a different term that I should be using?

In an ideal world, I'd like the whole "runtime" payload to be included with the app itself.

From this part of your proposal, it seems like PublishSingleFile is exactly what you want, or am I missing something?

As for C++ apps, we don't support static linkage of our libraries. I'm assuming that's how frameworks like Delphi or QT work to produce a single .exe file?

@stevenbrix - About PublishSingleFile, you already asked above, and I believe I already answered. Will this include all the ~300 dll (and also non binary files) that I have today aside my WinUI 3 .exe?

A single .exe can be produced differently than using static lib. Anyway, I'm not looking strictly for a single .exe, I'm looking for a "decent" way of deploying an unpackaged app. Today it's almost 300 files (for around 170MB) . This is not what I'd call "decent" for something that's not "packaged" or from some kind of store.

We need the dependent binaries somewhere. I think we are talking about these options.

  1. Loose files next to the exe
  2. In the exe itself using PublishSingeFile
  3. As a framework package installed through the store (or some installer), and the app takes a dependency on the package.

@smourier, are you asking if there is some 'installer' option for unpackaged apps similar to msi ?

Sorry, yeah PublishSingleFile will create a single .exe file without all the .dll's next to it. See this blog post for more on that https://www.hanselman.com/blog/MakingATinyNETCore30EntirelySelfcontainedSingleExecutable.aspx

@stevenbrix - ok, so, making sure I understand, it means I will have a 170MB or so for a "hello world" app (with say, 1% of it taken by the hello world code)?

@ranjeshj - Maybe, I mean some support file that I don't have to ship with my binaries (bootstrapper, msi, runtime, nuget, winget, call it the way you want, possibly on the internet) and that will "just work" when I run my app.

It's not only a size or number of binaries problem, it has also other implications in dev, like compilation time. A not so small C# program today is around 1 or 2 sec. compilation time on a decent PC, not what I observe with WinUI 3 preview today.

@marb2000 @MikeHillberg @Austin-Lamb as FYI

so, making sure I understand, it means I will have a 170MB or so for a "hello world" app (with say, 1% of it taken by the hello world code)?

If you use PublishTrimmed it will reduce a Hello World app from around 70MB to 28MB, and the WARP tool can take it down to 13MB. Definitely not ideal, and if the benefits of this deployment model don't outweigh the costs of the slight size increase of your app, then we can discuss something else.

A not so small C# program today is around 1 or 2 sec. compilation time on a decent PC, not what I observe with WinUI 3 preview today.

I definitely sympathize with you. There are 2 major buckets that are causing slow compilations times:

  • XAML Compiler.
  • MSIX packaging

There's nothing special about Desktop/Preview1, we've had painfully slow compilation times with UWP for some time. Since you're asking about unpackaged apps, the MSIX portion isn't really relevant to this discussion.

I'm sorry if the answers I'm giving aren't what you want, I'm really trying to understand what it is that you're after, so please bear with me. Is there an example of some other tech that you have in mind that you'd like us to model this after?

@stevenbrix - well the other techs are really the legacy ones : Winforms, WPF, or plain/old Win32/desktop development. They're all very fast to compile, very easy to copy ("deploy") and run. But they are legacy.

For example, today, I can use the Microsoft.Windows.SDK.Contracts nuget with an "old" .NET Framework 4.8, C# 7. From there I can use Windows.UI.Composition which is a dual API, so is allowed in desktop apps, and write my own Direct2D interop layer in C# (w/o Win2D) and benefit from all performance (flip sequential swapchain, etc.). With this type of project, I have a size of 3rd party assemblies reduced to 0K. My compilation Time is 2sec with Visual Studio 2019. Potential deployment issues/risk to customers: 0%. But I don't have all the features that's inside WinUI 3, so I have to write lots of "framework" code.

BTW, initially (Windows XP time if I remember correctly), the first .NET apps required .NET to be installed on Windows before they can run. But it was quite a simple process, just install the .NET redist of that time and off you ran. And then, Windows integrated .NET in its core (sort of), so that part wasn't necessary. Even today, if you run an old .NET 2.x app, Windows will ask and install quite seamlessly the required .NET 2 redist. All these were/are quite transparent for everyone: the developer because it already has the .NET runtime, the user because it's basically one dialog and click away from running (an experience similar to what we have with UWP packaged app from the store).

Thanks @smourier, that really helped connect the dots. I now better understand the type of model that you are looking for.

But it was quite a simple process, just install the .NET redist of that time and off you ran. And then, Windows integrated .NET in its core (sort of), so that part wasn't necessary. Even today, if you run an old .NET 2.x app, Windows will ask and install quite seamlessly the required .NET 2 redist.

So as @weltkante mentioned, this does exist today with .NET5 (at least in some form). If you try to run an app and the runtime isn't installed, you'll get a popup notifying you to go and install it with a link that you can click. It does require the user to have admin privileges to run the installer.

From the spec on single file publishing, it looks like you should be able to have a single .exe file that contains the WinUI dependencies, but not the .NET runtime (see the part on "Framework Dependent Publish"): https://github.com/dotnet/designs/blob/master/accepted/2020/single-file/design.md#user-experience

One of the benefits of WinUI3 is that we are decoupling from the OS, so that new features can work downlevel. The downside is that you do have to pay the extra cost of WinUI being bundled with your app, but at least you wouldn't have the entire .NET runtime. Does that satisfy your needs?

@stevenbrix - I'm not sure yet :-) , the preview does not demonstrate these aspects. I understand the "cross platform" benefit, but I don't really want to pay for its probable burden if I'm only targeting (more than 1 billion?) Windows boxes. And AFAIK, from a high level, this "bundle" could also be just there, already installed, in the Windows case.

For example, UWP is very attractive (modern UI, performance, D2D integration, etc.) but I don't want to pay the "sandbox" + "package" + "compilation price", unless I need to ship it to the store (because the store in itself adds value). If developing a desktop app (with WinUI 3) brings me the same kind of constraints (w/o the sandbox I believe), then I doubt I will use WinUI 3 very often.

I guess "The devil is in the detail".

@smourier Thanks for your feedback and open this necessary discussion.

You have a very fair point about the WinUI deployment in Desktop apps just doing an Xcopy (no using packaging/deployment mechanism like MSIX, MSI, or ClickOnce).

The current disk footprints for C++ and .NET basic apps are approx :

  • .NET: 270 files
  • C++: 60 files

I believe there are rooms for improvement for these disk footprints.

For instance, .NET WinUI 3 apps should be compatible with the .NET publish features like:

  • PublishSingleFile: place everything in one EXE
  • PublishTrimmed: remove unused .NET assemblies

Unfortunately, we don't have a story like .NET for C++ yet. Any feedback/guidance is welcome here.馃檹

One thing that we can do to reduce the footprint of C++ and .NET apps is to deploy the WinUI 3 runtime in a shared folder (similar to .NET Core that is using %ProgramFiles%dotnetsharedMicrosoft.NETCore.App). This mode is called _framework-dependent_, reusing the .NET argot. That means that all the WinUI 3 apps that opt-in for this mode will use the latest minor-version of the shared folder. However, the Plan-of-Record is that for 2020 the WinUI 3 runtime deployment is _self-contained_ (again taking the term from .NET argot).

We are eager to listen to customers with scenarios where not having self-contained is a blocker so that we can adjust the prioritization of this feature against others.

Does "Hosted App Model" help here? Can that concept be applied here to have the "just works" effect? https://blogs.windows.com/windowsdeveloper/2020/03/19/hosted-app-model or is this too round about/missing the point?

Just happy to see WinUI 3 for Win32 to be self-contained without packaging. Current UWP app does look fancy and beautiful but not every UWP apps is suitable for store publishing, and side-loading UWP app is difficult and painful for most of the end-user.

@myokeeh - Thanks for pointing that article that I hadn't seen. It's a bit like the reverse of a runtime way. Well, that's another brick that could be used maybe, something like a universal "WinUI Host". Why not if it has all the benefit we want (fast compilation, xcopy deployment, etc.).

@marb2000 - thanks for the clarification about self-contained.

As a Windows developer, what I would expect is just use Win32 (or WinRT) and use WinUI 3 without any dependency.

If you look at the picture here: https://docs.microsoft.com/en-us/windows/uwp/composition/visual-layer, today, right now, I can use all 3 layers with zero dependency, .NET (not necessarily .NET core) or C++ or any language that likes Windows (using a combination of Win32 and WinRT), so, why can't I do that tomorrow with WinUI 3 (which will replace the current "Framework Layer") ? Why do I even need to "publish" or "package" something? Or suffer increased compilation time? Because that (fundamental) part has gone cross-platform, we can't program Windows like we used to?

IMHO, the scenarios you describe will not ease adoption of WinUI 3 as a complete replacement from what was before (I can at least speak for me). It's not necessarily a "blocker" as such, but it will still be so much simpler in most aspects to use legacy techs, tools, languages.

It may be worth to look at what the Edge-Chromium team does with the WebView2 distribution model. See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#microsoft-edge-webview2-runtime

When I replace "WebView2" with "WinUI" and "Edge browser" with "WinUI-Runtime" it is almost the description of a perfect distribution model for me:

  1. have the option to use/reference a shared Runtime which just needs to be installed once and which is maintained by the OS by applying updates ("evergreen distribution model"). Quote: "Installing the runtime once will support many WebView2 applications running on the client machine".
  2. or choose a fixed version of WinUI for restricted environments which gets bundled with your application

Option 1 would require rock-solid versioning concept (like semantic versioning) to prevent breaking of apps in the future.

As WebView2 is also part of "Project Reunion" I think it makes sense to offer similar distribution models for the different components of this project.

and side-loading UWP app is difficult and painful for most of the end-user.

@tlaster could you file an issue in https://github.com/microsoft/ProjectReunion repo detailing the trouble you are having?

@smourier
_> If you look at the picture here: https://docs.microsoft.com/en-us/windows/uwp/composition/visual-layer, today, right now, I can use all 3 layers with zero dependency,_

You can do this because the framework is shipped within the OS. So, your app depends on the version of the OS. For example, the system XAML framework is on C:WindowsSystem32Windows.UI.Xaml.dll. But WinUI is no part of the OS, so your app needs that the target machine has the WinUI runtime installed.

WinUI product has several options here that are no exclusives:

  1. Deploy the WinUI runtime within the app. For example, ala .NET core self-contained way.
  2. Deploy the WinUI runtime using the Framework Package mechanism, like UWP apps is servicing updates.
  3. Install the WinUI runtime in a shared folder and all the WinUI apps use this shared folder. For example, ala .NET core self-dependent way.
  4. Deploy WinUI within the OS as OS extension, like the .NET Framework today.
  5. WinUI is part of the OS, like system XAML being deployed in system32 (Windows.UI.Xaml.dll).

All these options have tradeoffs. So far, the options 1 and 2 are the ones that we are planning for 2020. So far, option 2 will require you use MSIX as deployment mechanism. But, we are investigating the rest.

_> Why do I even need to "publish" or "package" something? Or suffer increased compilation time? Because that (fundamental) part has gone cross-platform, we can't program Windows like we used to?_

For Preview 3 or 4, you will be able to use copy/xcopy to 'deploy' your app. You won't need to package your app, as it's happening today. You won't pay the cost of packaging, but keep in mind the WinUI runtime has to be deployed within the app.

I'm confused how this thread got so out-of-hand. The author indicated that the primary weakness with "packaged apps" had to do with speed. It's conflation with UWP due to an inconsistent vision and poor messaging from Microsoft.

UWP is very attractive (modern UI, performance, D2D integration, etc.) but I don't want to pay the "sandbox" + "package" + "compilation price"

WinUI 3 and .NET 5 with Framework Packaging, using a no-MSIX dev loop, should solve the entire problem. It even solves the "Any CPU" problem. Build the templates and help support this issue, and users will come.

@marb2000 - I known perfectly well about Windows.UI.Xaml.dll being part of the OS, but precisely, I didn't understand so clearly that "WinUI is no part of the OS" (and so, maybe never will, last point in your list). Thanks for clarifying that.

It's a big change from current techs, and also explains some current problems (dwm integration, back drop brush, etc.).

I think it's an issue for wide adoption, and will not replace Win32/MFC/Winforms/WPF although it's fully designed to.

Microsoft.UI.Xaml (WinUI, yes this seems backwards but that's the naming) and Windows.UI.Xaml are cut from the same cloth. I'd be surprised if there are remaining current issues in the former that weren't already present in the latter, despite the latter's direct integration into Windows.

"Will not replace Win32/..."

Uh, what? If you like UWP, then you'll get the same XAML, no "compilation price," no sandbox, and the best one-click installation on Windows possible via MSIX with .NET 5 and WinUI 3.

Modern WPF and WinForms will also need to redistribute .NET 5, so it's not like there's anything different there. Unless you want to continue delivering .NET 4 apps, I guess.

It's hard to understand why you're picking an unpackaged app. What things would Microsoft need to do to convince you to package everything in an MSIX?

@smourier I agree with your proposal. In our company we have/had huge investments in .NET Framework and C++/CLI (bridge to native C++). We have recently migrated to WPF netcoreapp 3.1.

I was wondering why is there only a _Packaged (WinUI in Desktop app)_ project template. Our company is targeting only a few big companies, not a lot of users via Windows Store.
I'm exploring WinUI 3 mainly for SwapChainPanel (DirectX 11) support for Win32 (WPF) apps.
I haven't tried the unpackaged version up to this time, but I hope it will not be cumbersome to "deploy" it only on tens of machines.

This is a shout out from real industry/market.

Thank you very much

@tomasfabian, you're exactly the customer we want to hear from and understand more about. The current requirement for MSIX is a point-in-time issue, we fully plan on enabling unpackaged applications.

How do you deliver your application to customers? Are your apps framework-dependent or self-contained?

We've been trying to reduce the friction of MSIX, and it's no longer only for store deploy scenarios. At the same time, I totally get that it might not meet your needs to this day. If there are particular things you want to see, I'd recommend commenting on this issue: https://github.com/microsoft/ProjectReunion/issues/57

@tomasfabian Thanks for leave your feedback here.

Q: why is there only a Packaged (WinUI in Desktop app) project template?
A: It's something temporary. We are planning to support unpackaged Desktop WinUI apps in Preview 3

About the "exploring WinUI 3 mainly for SwapChainPanel (DirectX 11) support for Win32 (WPF) apps." It's no clear to me what do you want to explore. Are you planning to host the WinUI's SwapChainPanel control in your WPF app?

@marb2000 We are most specifically interested in displaying (video) content rendered by DirectX11 or DirectX12 in a similar fashion as D3DImage does with DX9. We found out in the WPF repository that its targeting only DX9.
I'm talking in a theorethical way right now, since I haven't had enough time to explore the whole WinUI 3 ecosystem.
We would like to also test if there is a performance / penalty cost for marshaling between DX11 and DX9 in XAML islands, but this is probably not relevant for this forum.

@stevenbrix we are using CHOCOLATEY currently
Edit:
Our apps are framework dependent. We haven't used self-contained desktop apps up to this time. But in case that Docker enables access to the graphical card....

Was this page helpful?
0 / 5 - 0 ratings