Closed Aminator closed 3 years ago
The Win32 sandbox was already available on Windows 10X, check its session videos. Just now with the project frozen, who knows.
The Win32 sandbox was already available on Windows 10X, check its session videos. Just now with the project frozen, who knows.
That's worst technology ever - it's just Hyper-V virtual machine with lightweight Windows 10 version. It's just workaround and not related to UWP sandbox model.
@DjArt Whatever it might be, that shows sandboxing isn't going away. However I no longer have high hopes for UWP.
Reunion is the confirmation that future is somehow Windows 7 development model plus some goodies from UWP back into Win32 stack, and adoption remains to be seen.
I for one am slowly fed up from all rewrites that took place since Windows 8 introduction.
Thanks for the healthy discussion, and for keeping it civil. Limitations with localhost networking have their own issue (#113); please add your feedback there or add a new item if this doesn't cover it.
To the question of sandboxing, there are two key concepts here that often get intermingled due to oversimplification and confusing messaging... I do not fault anyone for getting things mixed up :-).
From a design standpoint, the sandbox is about controlling access to resources; it is entirely distinct from which APIs you can access (WinRT, .NET, etc.) and some of their respective design choices (async, for example). In practice, it turns out that the WinRT APIs are often the only APIs that understand how to work within the sandbox, but that's a historical decision that Project Reunion is explicitly trying to undo. (The Microsoft Store's policy of banning "unsupported APIs" also comes into play, which is another complication we're trying to work through... but that has nothing to do with how apps behave at runtime; it's purely a policy decision around which apps can be listed in the Store).
Take file access for example (Issue #8).
The AppContainer sandbox simply controls which files an app has access to. An app with no capabilities can't access any user files; an app with the picturesLibrary
capability can access only your photos; and an app with the broadFileSystemAccess
capability can access all your files. I hope everyone agrees this is a good thing :-). Of course that's the Platonic Ideal, and reality isn't quite as rosy (What if I don't store my photos in the Pictures Library? Why does broadFileSystemAccess
not have a popup prompt? etc.) but they are mostly implementation issues that can be fixed; they're not fundamental design flaws.
From an API perspective, things aren't nearly as good. None of the existing APIs, like CreateFile
, System.IO
, fopen
or std::fstream
work for user files. Not a single line of existing file-manipulation code works in an AppContainer. You must re-write the code to use Windows.Storage
because that's the only API that was designed to work within the sandbox. And the Windows.Storage
API made design decisions that cause it to be slow, heavily async, and have various other limitations that make it unpalletable to many app developers. We improved the situation somewhat with the ...FromApp
APIs (Win32 APIs that are also designed to understand the sandbox) and then we layerd API Redirection on top of that (to allow some degree of code re-use) but it's still not enough for various reasons. Hence Issue #8 which is saying "we want to make any file access API work within the sandbox" so you can use your existing code and not have to re-write and re-architect to use async WinRT APIs.
But the sandbox doesn't require WinRT. The sandbox doesn't require async code. The sandbox just says "though shalt respect the user's privacy choices."
(And yes, the Windows 10X "Win32 Container" is a different technology than AppContainer).
As to the problems with .NET Native / CoreCLR... sorry you are having those problems. They are best raised over in the .NET repos.
@m98770
anything that tries to modify the system should be restricted from sandbox/pure UWP apps, but other than all that, developers should be given freedom to produce something useful beyond "some data fetching from the internet and displaying" clients.
Can you give some examples? Based on my previous comment above, if possible please try to separate out "sandbox issues" (where you want to access a resource but the AppContainer won't let you) from "API issues" (where you want to use an API or library but it's not supported).
@mcosmin222
Bugs that have been reported, such as the inability to use MediaPlaybackList with IBasicVideoEffect (due to MediaPlaybackItems getting randomly skipped) are never fixed
Can you please file an issue for this (if there isn't one already?)
The worst part is that the UWP app model makes you dependent on winRT to get things done. If you are missing/limited on a feature, well then though luck. At least with a fully featured .net API you could implement your own.
The UWP "app model" (that's another long topic... LOL) doesn't depend on WinRT; it's just that often the WinRT APIs are the only ones that work properly. It may seem like I'm splitting hairs or trying to defend the indefensible, but my goal is not to claim the system is perfect or that none of these issues exist. My goal is to help everyone understand the different overlapping parts of the technology so we can have productive conversations about which specific things are broken and thus need fixing. There's nothing fundamentally broken about the "app model" that wouldn't allow you to use any API you wanted to, it's "just work" (in some cases a lot of work haha) to make that happen. We want to let developers use the APIs they know and love (Win32, CRT, STL, .NET, etc.) which I think would address some of your feedback. Letting us know which specific APIs (or resources) are important to you helps us prioritize the work.
And last but not least, why all the async methods? Why not provide both async and sync methods? async does not make you inherently fast, quite the opposite.
There are two basic reasons. I am not defending them, just letting you know. And yes, I 100% agree that async code can make apps slower, introduces reentrancy bugs, makes debugging harder, and so on.
The first reason was the support for JavaScript and WWAs. JavaScript (and the web in general) has no concept of explicit threads (or at least, they didn't 10 years ago). Whilst a .NET or C++ developer could put long-running calls onto a background thread, JavaScript developers couldn't, and so async was a way to let web developers have responsive apps. This is a valid argument for having async methods, but doesn't explain why there aren't also sync methods.
The second reason, which does explain why there are no sync methods, was a desire to raise the quality of UX in Windows apps. We've all had cases where an app has ghosted over with "FooApp - (not responding)" in the title bar, and the idea was to eliminate those classes of bugs where an app made a long-running call on its UI thread, causing the entire app to hang and the user to have a bad experience. Thus the "sync calls can hang, all hangs are bad, hence all sync calls are illegal" point of view that lead to a heavily-async design pattern. This was a noble goal, made with the user in mind, but in hindsight didn't necessarily work out as well as intended.
@jtorjo, It's a minor point, but I might be able to shed some light on this: " I see the stack trace, but on async code I never get the whole stack. And I NEVER EVER get the line that caused the crash. Trust me, I've analyzed stack traces from AppCenter for over 6 months now."
I'm guessing a bit, but this may be what you're seeing Back when we were building Windows Runtime API infrastructure in Windows 8, we recognized that with everything being async, debugging was going to be challenging, so we built something called "async causality tracing" to support debuggers and provide a more useful view of the sequence of events leading up to a crash. It uses ETW tracing and stack capture to build up a history of stacks that led to the current async operation, and the debugger stitches them back together. Such a stack never actually existed, but it approximates the logical sequence of events. That features is typically only enabled by the debugger since it incurs non-trivial overhead to capture stacks & context information on each async operation, and maintain a useful history of async operations.
I know that doesn't help you solve your problem, but I hope it provides a bit more insight as to why you might see something different in a local debugger vs. a crash dump in AppCenter.
You might be able to add some in-app analytics or otherwise use the causality ETW events to leave some breadcrumbs that you can follow when looking at crash dumps. I'm not certain if you'll be able to turn on the trace from within the application though. You can see what the events look like by inspecting them in Windows Device Portal or xperf. Look for the trace provider Microsoft-Windows-AsynchronousCausality in the ETW logging tool. I hope that's helpful.
@BenJKuhn Thanks for the insight!
@mcosmin222 said earlier in this thread "And last but not least, why all the async methods? Why not provide both async and sync methods? ..."
Personally I'm really tired of having to come up with weird workarounds to the WinRT (async) system. In the future, I really really think you should provide sync counterparts for most methods. Otherwise, this async mambo jambo will end up biting everyone in the ass. I'm not against async per-se, I'm against not having an alternative.
Because when I get to run the app in Release, there will be issues, and, as you said, debugging those is pretty close to impossible. However, having a clear stack trace will make this child's play.
Let me give you an example of async madness (this is the latest, but I have countless): there's a function CanvasBitmap.LoadAsync
- which you guessed, loads the bitmap from a stream asynchronously. But, if I'm inside the CanvasControl.Draw
function, the LoadAsync
blocks the thread, and .Draw
never completes. This should NEVER EVER EVER happen.
Clearly, I found a workaround for it, but it took me ages- initially I thought CanvasBitmap.LoadAsync was broken. As I said, I have countless examples, where async
is not only not helpful, but really the opposite.
I'm really curious whose' "great" idea was to break up everything in order to support Javascript (if I understood correctly @ptorr-msft explanations).
I'm not a dreamer (anymore), so I know we'll live with this current state of events for years to come. But hopefully our grand children or grand grand children will be able to have sync counterparts.
@jtorjo So with you on this one. Recently used Xamarin,Essentials securestorage (async) on property getter and setters, Ugly stuff !! Best of all someone actually made the effort to include sync methods by adding a pull request on Github but was rejected eventually by James Montemagno. Problem with this mentality from MS is that it's not approachable for beginners and definitely not inclusive for the community that MS is trying to build. It's the same as a C# versus Visual Basic discussion. Stop the biasedness and embrace all the diversity in the community. Be "inclusive" and we will have a stronger community where everyone can express themselves.
So with you on this one. Recently used Xamarin,Essentials securestorage (async) on property getter and setters, Ugly stuff !! Best of all someone actually made the effort to include sync methods by adding a pull request on Github but was rejected eventually by James Montemagno. Problem with this mentality from MS is that it's not approachable for beginners and definitely not inclusive for the community that MS is trying to build.
Couldn't agree more:
Why Microsoft jumped whole heartedly into async/await while leaving sync in the dust I'll never understand. It certainly is not clear that it's better in all cases.
For older/experienced developers it could either be:
- Fine if you are writing a new code base
- Terrible if you are using existing code that was already doing long running operations on different threads like it should be anyway.
@robloo I know this wholeheartedly - basically, I ended up rewriting the whole UI - not for the faint hearted.
So with you on this one. Recently used Xamarin,Essentials securestorage (async) on property getter and setters, Ugly stuff !! Best of all someone actually made the effort to include sync methods by adding a pull request on Github but was rejected eventually by James Montemagno. Problem with this mentality from MS is that it's not approachable for beginners and definitely not inclusive for the community that MS is trying to build.
@Pinox I know - I've been crying against async for sooo long. But at some point I realized I need to move on and accept the fact that async is here to stay, and there's no way around it but to end up using it (I tried all sorts of stuff to add sync wrappers around, but they don't really work long term)
@Pinox I know - I've been crying against async for sooo long. But at some point I realized I need to move on and accept the fact that async is here to stay, and there's no way around it but to end up using it (I tried all sorts of stuff to add sync wrappers around, but they don't really work long term)
I use 99% async where I can , but in some instances like property getter and setters I prefer a sync method. So in Xamarin,Essentials most Preferences are sync and not async but the securestorage is async but not sync. This goes over my head , why the double standards especially when most of the underlying functionality in the native platforms are actually sync methods.
I can still understand it when someone request a feature and then the maintainer has to write the code, but when someone actually writes the code and put in a pull request that then gets rejected. It's the "small things" that adds up and makes it unpleasant.
For what it's worth, the new API design guidance for WinRT types since Windows.Foundation.UniversalApiContract
version 8.0 has been to introduce non -Async
methods based on demand, and that new APIs should come with both Foo.Bar()
and Foo.BarAsync()
methods. This guidance has been slowly being absorbed into API-making teams since then.
Per @BenJKuhn 's comment earlier, we recognized the challenges with this space for "normal" apps and that tooling - especially C++'s coroutines and C#'s SynchronizationContext
(and this handy await pattern) means it's easy to move code off the UX thread and not block... but you have to know how to do it.
Our new design guidance is that you the developer own what goes on on your threads, and we should help you write "normal sequential code" whenever possible, with the option to easily hop off into async or into nonblocking contexts.
(We're working on getting these API design guidelines into the open so you can see why we make the APIs we do. Stay tuned!)
@jonwis
For what it's worth, the new API design guidance for WinRT types since
Windows.Foundation.UniversalApiContract
version 8.0 has been to introduce non-Async
methods based on demand, and that new APIs should come with bothFoo.Bar()
andFoo.BarAsync()
methods. This guidance has been slowly being absorbed into API-making teams since then.
That is beyond awesome!
Per @BenJKuhn 's comment earlier, we recognized the challenges with this space for "normal" apps and that tooling - especially C++'s coroutines and C#'s
SynchronizationContext
(and this handy await pattern) means it's easy to move code off the UX thread and not block... but you have to know how to do it.
I wasn't aware of that handy await pattern, it's definitely something worth knowing. Having said that, as I've written earlier, there are things a lot worse that just a bit of inconvenience, when it comes to async methods:
there's a function CanvasBitmap.LoadAsync - which you guessed, loads the bitmap from a stream asynchronously. But, if I'm inside the CanvasControl.Draw function, the LoadAsync blocks the thread, and .Draw never completes. This should NEVER EVER EVER happen
(just one of the countless examples I can come up with)
Long story short, I'd love for CanvasBitmap
to have a sync Load()
method. And same for BitmapEncoder
/BitmapDecoder
-they're kinda' in the same boat.
... (We're working on getting these API design guidelines into the open so you can see why we make the APIs we do. Stay tuned!)
Awesome, definitely looking forward to it!
@ptorr-msft
Can you please file an issue for this (if there isn't one already?)
Thanks.
Speaking of async, I wonder which is faster.
A:
public async Task DoLotsOfStuffAsync()
{
await Task.Run(()=>{
DoA();
DoB();
DoC();
...
});
}
B:
public async Task DoLotsOfStuffAsync()
{
await DoAAsync();
await DoBAsync();
await DoCAsync();
...
}
@driver1998 Very likely A.
On another note, I'm almost certain a lot of people don't realize that an "async Task" method executes synchronously until it needs to wait for something.
So in your case, A. executes completely on a different thread, while B. can have parts executing in the current thread, and parts executing on other threads.
FWIW, if A
, B
, and C
are entirely independent (e.g. don't rely on shared state or contend for the same resources) then it might be fastest to do:
var tasks = new List<Task>();
tasks.Add(Task.Run(()=>DoA()));
tasks.Add(Task.Run(()=>DoB()));
tasks.Add(Task.Run(()=>DoC()));
await Task.WhenAll(tasks);
That's "github comment code", so take with a grain of salt :).
Yep 🙂 Or, if you already have async
versions of the functions:
var tasks = new List<Task>();
tasks.Add(DoAAsync());
tasks.Add(DoBAsync());
tasks.Add(DoCAsync());
await Task.WhenAll(tasks);
Anyway, getting back on topic... 🙂
@Bosch-Eli-Black no ! 🙂
DoAAsync() can start with synchronous instructions before asynchronous one. Maybe you should do instead:
tasks.Add(Task.Run(DoAAsync));
@Bosch-Eli-Black to quote myself:
On another note, I'm almost certain a lot of people don't realize that an "async Task" method executes synchronously until it needs to wait for something.
Anyway, just try to prove a point: If we have synchronous versions of WinRT IO APIs, then we can transfer these bulk operation (which is mostly written like B right now) to A. And maybe get some performance improvement.
Especially when we don't necessarily need to update the UI after every single operation, we just want a final result.
Getting back to the topic at hand, @pag3 @ptorr-msft do we have a definitive answer on what is holding us back from using .NET 5 with UWP?
In addition to the way you show, there are other approaches that can work, eg. starting with the packaged desktop app templates we’ve been shipping with the WinUI 3 previews and modifying them to have the apps execute/run as UWP apps instead of desktop apps.
We’d like to figure out the right path to enable this end-to-end, including not just the core platform and runtime working but also the tooling, project templates, deployment, store, etc. We’d like to support this in a way that’s forward-looking, durable, and makes it reasonably easy for developers to build apps with the benefits of UWP and the benefits of the latest .NET.
Is it the tooling and project setup path holding it back, is it more about AOT, (which could be delayed until .NET 6), a combination of both, or something else?
(I realize fully that this is not the time or the place for this comment, but it does relate to some things that have been said in this issue thread that I want to echo and elaborate on. I apologize for the interruption; please do not let my impulsiveness in posting this derail the thread further. I'm not trying to start this conversation up again, I only want to be heard, if only for a moment.)
Quoting a few of you, I want to point out a theme I have sensed, here:
an "async Task" method executes synchronously until it needs to wait for something.
[an
async
method inside aList<Task>
] can start with synchronous instructions before asynchronous one.
etc.
How are people ever supposed to discover these things until they are bitten by them? Why does this particular language feature lay these landmines everywhere like it does? There are so many examples of C#'s async
/ await
"gotchas" that, to me, it's not a language feature worth using anymore. I don't even write C# for myself anymore because of this API and how far this async stuff has spread within the framework libraries. All of my C# development difficulties for the past 3-4 years have always come down to some async/await sneak attack that I had not encountered before. Async & await were consistently the sole source of my C# headaches before I stopped writing code for fun in this language. It's no longer worth it for me to even use the .net framework AT ALL. Up until the pandemic, I had been writing C# for my own utilities and projects since about 2002.
This could have been such a beautiful language feature that made easy things easier, and hard things easier. Instead it made easy things harder and hard things the same, because people facing difficult problems fall back on what they know - threads. The lack of new synchronous APIs alongside the new async APIs was such an absolutely glaring oversight that persisted for so long that it felt like a middle finger from Microsoft. It really stung.
I feel this thread in my bones. I now do nearly all of my own software development in a non-.NET, language that makes async stuff absolutely trivial, and I'm so much happier for it. I mean imagine it: a single method that can be asynchronous or synchronous, depending on how it is called! There is no friction when moving between asynchronous and synchronous program design! I can switch any part at will, without a cascade of other changes that need to happen! I know! It doesn't offer the scheduling control that async and await in C# offer, and I have never once needed that control, and I don't know anyone that has needed that level of control that doesn't also just use plain threads... This API, this feature, whatever it is... it could have been good. It could have been really good. But instead it is worse than normal threads in every single way I care about.
Sorry for the interruption. I just wanted to be heard on that. To protect my sanity, and yours, I won't reply in this issue again.
Thank you @naikrovek for stating so passionately yet so clearly what so many of us feel. I know you do not wish to reply again in this thread, but please say where you went from DotNet so we can all see where the sky is blue.
do we have a definitive answer on what is holding us back from using .NET 5 with UWP?
@pag3 should have the latest info, but for one it is unlikely to pass Store certification. If you don't care about the Store, it can "work" but I do not believe it is officially supported.
@naikrovek thanks for sharing; indeed async programming has introduced new problems even as it attempted to solve old ones. I would suggest you provide your feedback to the C# team directly though.
@naikrovek
I feel your pain. For security critical code which doesn't really need to run in parallel but it is forced to do so by poor API interfaces only providing async, I have implemented a "Commands" dispatcher, which essentially runs these async methods sequentially and waits for each one of them to finish. This seems to have fixed many of the stringent bugs introduced by async.
I do not believe that async/await in C# is necessarily flawed. It is a very powerful tool. However, API interfaces that only allow async are problematic, mainly because they still introduce thread racing conflicts, even though it looks like they don't, which is why I hope project reunion will bring synchronous API equivalents for the myriad of async APIs in winRT.
There are so many examples of C#'s
async
/await
"gotchas" that, to me, it's not a language feature worth using anymore
@mcosmin222 @naikrovek @ptorr-msft
async/await is a smart feature. The only problem is UWP. Or more to the point, WinRT. I've said it quite a few times - nobody at Microsoft is willing to work on fixing anything related to WinRT/UWP. They just postpone this until it'll die. Frankly, I do hope UWP dies, because it (WinRT) was a stupid idea to start with.
async/await do come with a few gotchas, but you can get the hang of them, and live another day. But what will kill you, is support for anything else - which came to the Desktop, but not to UWP. I have a feeling, it will NEVER arrive to UWP:
switch
(because it's a property changed handler). It's pretty much impossible to know what happened.Not to add the countless Access Violation in PrivateCore.lib or something.
So yeah, can't wait for win2d to be ported to Desktop, so I can once and for all forget UWP ever existed.
I do hope UWP dies, because it (WinRT) was a stupid idea to start with. Do you want to kill technology since you can't cook them right? Of course, for .NET projects there are some limitations, like NO STACK TRACE whatsoever or File:Line information in the stack trace (once again, this exists for Desktop, if you have .pdb files). since there used AOT compilation. ProjectN isn't so young for childish bugs, so if you want to debug your application, use the debug config and that's it.
since there used AOT compilation. ProjectN isn't so young for childish bugs, so if you want to debug your application, use the debug config and that's it.
Lol, have you ever actually developed an application that is used by ACTUAL USERS? Where something crashes and you simply have no way to reproduce? And you don't even know where to start?
Do you want to kill technology since you can't cook them right? Of course, for .NET projects there are some limitations, like NO STACK TRACE whatsoever
Yeah, please actually read before you comment. I did not say ".NET", I sad UWP. My whole point here was ".Net Desktop" works as it should, while UWP doesn't.
LATER EDIT: And in Debug, the crash clearly doesn't happen. Duh. DjArt, have you actually ever developed non-trivial UWP apps for the REAL WORLD, or do you just want to hear yourself talk?
@jtorjo, Let's keep it civil 🙂
@jtorjo Release uses .NET Native to compile managed to unmanaged code. You can also activate it for debug mode (which is done in ARM64 config for both debug and release) to see what causes your crashes.
@MagicAndre1981 Thanks for the suggestion. However, I'm not using .Net Native (I have it unchecked in Release as well)
@jtorjo if you publish your app to Microsoft Store as a regular UWP app (not a desktop bridge app), .NET Native is forced during "preprocessing" publish step.
@pfresnay I am very aware of that, I don't publish to MS Store. I am publishing it on my website. Fyi, you can check it out here - [link removed]
In the spirit of getting this discussion back on track (again), I reiterate my previous comment:
@pag3 @ptorr-msft, do we have a definitive answer on what is holding us back from using .NET 5 with UWP?
In addition to the way you show, there are other approaches that can work, eg. starting with the packaged desktop app templates we’ve been shipping with the WinUI 3 previews and modifying them to have the apps execute/run as UWP apps instead of desktop apps.
We’d like to figure out the right path to enable this end-to-end, including not just the core platform and runtime working but also the tooling, project templates, deployment, store, etc. We’d like to support this in a way that’s forward-looking, durable, and makes it reasonably easy for developers to build apps with the benefits of UWP and the benefits of the latest .NET.
Is it the tooling and project setup path holding it back, is it more about AOT, (which could be delayed until .NET 6), a combination of both, or something else?
do we have a definitive answer on what is holding us back from using .NET 5 with UWP?
If you don't care about the Store, it can "work" but I do not believe it is officially supported.
@ptorr-msft Is there a reason why it's not officially supported? If I'm not mistaken, WinUI 3 Desktop apps can be published to the Store without any issue. If WinUI 3 Desktop and WinUI 3 UWP apps are basically the same, does that mean it's the app model that's holding one back and not the other?
Now that .NET 5 is out, I wondered if I could upgrade my UWP app to use it. I found this issue from google... still not sure what the answer is. Is the OP up to date and supported? (I'm not specifically asking about WinUI 3 which is what the discussion here at the bottom of the thread seems to be about)
The official .NET 5 announcement post only has 1 mention of UWP and says to check here. (yes I already checked the faq page... ctrl+f ".net" -> zero hits 😢)
@yoshiask UWP apps have different rules than Desktop apps. For example, the Store will try to run UWP binaries through .NET Native (which will fail) and it performs a Supported API Check to see what APIs you are using. Running the Windows App Certification Kit (WACK) locally on your PC should tell you what (if anything) is wrong, but it might not do the forced-.NET-Native step.
So I guess the real question is why doesn't the Store have a special case or a different set of rules for UWP apps that use .NET 5? Why is it hard-coded to force UWP apps to use .NET Native?
This seems quite weird considering that C++ UWP apps are supported. Wouldn’t that mechanism also work for .NET 5 on UWP? Then just share the .NET 5 runtime via Framework Packaging.
@yoshiask :
why doesn't the Store have a special case or a different set of rules for UWP apps that use .NET 5
Because it's not supported.
@lmcdougald :
Then just share the .NET 5 runtime via Framework Packaging.
But no such package exists, because it's not supported.
Would it be nice if these things worked? Yes.
It seems like we're facing a bit of a chicken-and-egg problem here.
Not really. First the feature has to be supported, and then the other things can fall into place. There aren't any circular dependencies here.
C++ apps are already native, so .NET Native has nothing to do @lmcdougald
The point of the C++ comment is that it's clearly possible for code to run on UWP without .NET Native. .NET 5 should have nothing to do with .NET Native either.
@lmcdougald Windows doesn't care, but the Store assumes all managed binaries in a UWP project need to be .NET-native compiled. So they will see the DLLs and send them through the .NET Native compiler.
If you compiled the .NET 5 assemblies to native code (I can't recall whether there is such a tool or not yet) and built a "stand-alone" app (with no dependency on the shared framework) then you would probably fail the Supported APIs test. You can give it a shot though if you want to try (run WACK locally).
Ok this is the type of detail I was hoping for. So it sounds to me like there's probably hacky ways to make this work (hide that they're DLLs and run them through something on first run) and it's a Store issue just about as much as it's a tooling issue?
Question: .NET 5 UWP apps are already possible, so when will official support arrive?
When it comes to .NET 5 support for UWP apps, we don't really have a clear answer yet to how that will look like and when it will come. UWP developers shouldn't have to be stuck on an old .NET version while Win32 developers are seemingly way ahead and can also use the new C#/WinRT language projection.
How to create a .NET 5 UWP app
What I found is that despite Microsoft telling us developers that creating UWP apps running on .NET 5 is not supported yet, it is actually quite easy to do today with minimal setup and it even works with WinUI 3. You can start off with the regular .NET 5 console app template and modify it from there. This process involves three steps: Modifying the project file, adding a package manifest file and generating a PRI file. Be sure to have the latest .NET 5 preview SDK and Visual Studio Preview installed. I have provided samples in this repository.
Project file
You need to add a few properties, NuGet packages and targets. I tried to make it as independent of Visual Studio and the Windows 10 SDK as possible.
Package manifest
The package manifest named
AppxManifest.xml
is needed to register your app with the OS, but notice that it's not the regularPackage.appxmanifest
file you find in old UWP projects, which would generate the finalAppxManifest.xml
for you. If you use an existing one, be sure to remove the package dependency for UWP .NET Core and use the release version of VCLibs.For WinUI 3 you also need to add any types you use from it to your manifest. This also needs to be done for WinUI Desktop.
Resources
It is necessary to have a file called
resources.pri
in your app for any assets, including XAML files, to be accessible by your app. This can be generated usingMakePri.exe
. It takes a configuration file calledpriconfig.xml
as an input. You can create a new configuration file with the commandmakepri createconfig /cf priconfig.xml /dq en-US
. Be sure to remove the following two tags if you want to only create a singleresources.pri
file.Entry point for WinUI 3
A custom entry point needs to be defined for WinUI 3 apps because the automatically generated one applies the
STAThreadAttribute
to theMain
method, which causes a wrong thread exception.Building and debugging
The project can be built either on the command line using
dotnet build
or in Visual Studio, though for WinUI 3 it currently needs to be done in Visual Studio. Do not start the app from Visual Studio, this would execute the.exe
file directly and essentially be a Win32 launch. The app needs to be launched by clicking on the app list entry in the Start menu or the icon on the taskbar. A debugger can be attached from Visual Studio after the app has been started.Issues
The biggest issues with this approach are:
MakePri.exe
is not included in the .NET SDK or a NuGet package.Conclusions
I have been using .NET 5 and WinUI 3 in my own UWP projects for a few weeks now and it has been working quite well and I was able to take advantage of new .NET APIs that I didn't have access to before. The main issues come from WinUI 3 still being in preview, so there are still many missing pieces, which is why I wouldn't recommend it for production use just yet.
Through this process I also came to understand what the main difference between a UWP and a Win32 app is and it all has to do with how the app is launched. It is the
EntryPoint
on theApplication
element in the package manifest that determines if it will be a UWP or a Win32 launch. For UWP it will beYourProject.App
and for Win32 it will always beWindows.FullTrustApplication
.It is also unclear if this type of app will be accepted in the Microsoft Store, so I would like to know more information about that. The other question remaining is the one I stated at the beginning: Since it is possible to build UWP apps running on .NET 5 today, what is the holdup on supporting it officially? It would be great if Microsoft provided additional tooling to make the process easier for developers. I would like to see a rough timetable on when we can see the issues I mentioned resolved. Hopefully we can see it officially supported whenever WinUI 3 is ready for production, so that UWP developers that make the switch can also take advantage of .NET 5 immediately.