22

An UWP app which runs on desktop can be closed from the top X button but it doesn't have any event for it. It is known that on phones and tablets an app should rely on Suspending event, no matter how it's triggered and then the app should rely on ApplicationExecutionState.

However, here is a (maybe) common scenario: on phones the Suspending event suffice and in case a Voip call is going on it will be operated by OS after the app is suspended. On desktop the close button is expected, by user, to completely close the app. So if a call is on going it should be hanged up and certain resources should be released.

How can I know when the user clicked the "close" button if (and only if) the UWP app is running on desktop?

tomab
  • 2,061
  • 5
  • 27
  • 38

5 Answers5

26

A restricted capability confirmAppClose was added in Windows 10 version 1703 (build 10.0.15063) in order to provide apps the ability to intercept window closing.

Manifest namespace:

xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"

Manifest:

<Capabilities> 
  <Capability Name="internetClient" /> 
  <rescap:Capability Name="confirmAppClose"/> 
</Capabilities> 

It needs extra approval when submitting to the store. But then will fire the CloseRequested event on a SystemNavigationManagerPreview instance.

Code:

    public MainPage()
    {
        this.InitializeComponent();
        SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += this.OnCloseRequest;
    }

    private void OnCloseRequest(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
    {
        if (!saved) { e.Handled = true; SomePromptFunction(); }
    }

You can get a deferral to do a bit of work here (save or prompt), or you can set Handled to true in order to stop the window from closing (user cancelled prompt).

Michael Hawker - MSFT
  • 1,572
  • 12
  • 18
  • I saw the documentation pages you shared the link to, but i still dont know how to do it. Can you guide me how to register a handler for that event, in my window? – kkica Sep 13 '18 at 10:14
  • 1
    There's a blog someone posted about it here: http://codeworks.it/blog/?tag=systemnavigationmanagerpreview – Michael Hawker - MSFT Sep 13 '18 at 19:49
  • 1
    Interesting - Intellisense shows the rescap:Capabilty node in appxmanifest with a squiggly underline indicating the capability doesn't exist, however the code compiles and the capability becomes active with this addition. – zax Oct 30 '18 at 19:40
  • 1
    @zax I'm not sure why VS can't figure out the pieces, but that's also why they have the `IgnorableNamespaces` tag on the Package. You can add rescap there to remove the squiggles. – Michael Hawker - MSFT Nov 01 '18 at 18:37
  • 1
    @MichaelHawker-MSFT The squiggles and associated pop-up error text are present *with* rescap added to IgnorableNamespaces. VS 2017, 15.8.4. – zax Nov 01 '18 at 20:03
  • Hmm, I'd log an issue with the VS feedback tools then. – Michael Hawker - MSFT Nov 02 '18 at 04:21
4

From official page about app lifecycle:

There's no special event to indicate that the user closed the app.

Closed-by-user behavior: If your app needs to do something different when it is closed by the user than when it is closed by Windows, you can use the activation event handler to determine whether the app was terminated by the user or by Windows.

So according to this there is no (clear) way to know if the user closed the app before the app is closed but only after it's restarted. Too bad.

Community
  • 1
  • 1
tomab
  • 2,061
  • 5
  • 27
  • 38
  • I guess it sorta make sense not to fire a close event. What if someone re-open another window at Closed? Is it achievable? Probably. – Hiro Apr 01 '18 at 14:51
  • @Hiro I'm not sure I understand what you mean by "re-open another window at Closed". Anyway, needs vary from case to case and therefore it might makes sense to have a Closed event or to ignore it. For the record WinForms and WPF have it. – tomab Apr 03 '18 at 14:42
  • 1
    This is outdated now, I posted an updated answer below. – Michael Hawker - MSFT Jul 24 '18 at 18:40
2

This code helps you -

In App.xaml.cs

...
using Windows.ApplicationModel;
...

public App()
{
    InitializeComponent();            
    this.Suspending += OnSuspending;
}
...
private void OnSuspending(object sender, SuspendingEventArgs e)
{
    var deferral = e.SuspendingOperation.GetDeferral();
    //Add your logic here, if any
    deferral.Complete();
}

Thanks!!!

Nitika Chopra
  • 1,281
  • 17
  • 22
1

I deleted my original answer with Window.Current.Closed event, because it doesn't seem to work if you have only one Window instance. There is also CoreApplication.Exiting, but judging by this topic it doesn't work either. Seems to be known issue which might be fixed in future. At the end, it appears there is no clear way to determine when the app is getting closed, only when it's suspended.

However, Window.Current does fire VisibilityChanged event when app is closed. Problem is, it's also fired when app is minimized and maybe in some other cases. But I think in combination with Suspending you can (more or less) safely determine that desktop app is closing. Good thing is, VisibilityChanged fired before Suspending and you can save it's value and check it in OnSuspending handler, after which decide if you need to do any cleaning up or other work.

Andrei Ashikhmin
  • 2,401
  • 2
  • 20
  • 34
  • But `VisibilityChanged` event will be fired when the OS closes the app as well. So there is no difference between OS-closing and user-closing. – tomab Jan 28 '16 at 09:09
  • Yes, OS can close the app as well, but it does so when it needs to free resources, which could be a quite rare case in desktop. Anyway, as I pointed before - it appears there is no clear way to determine when the app is getting closed by user. – Andrei Ashikhmin Jan 28 '16 at 09:20
  • So we can *guess* the app has been closed if we get the `VisibilityChanged` followed by the `Suspending` event. Can this not occur naturally if the user minimizes the app and later Windows decides to suspend our app? Then we would have incorrectly *guessed* the app is closing, as the user can later maximize it and resume? – Felix Sep 05 '17 at 21:55
  • Yes, in this case our guess will probably be incorrect. As I mentioned before, there seems to be no clear way to determine if app is closed by user unless you're checking it on the next launch. – Andrei Ashikhmin Sep 06 '17 at 04:42
1

For those who find this question looking for how to confirm closing of a Window in WinUI3:

The Window.Closed event args has a Handled property which can be set to true to cancel the close.

I was really confused that Closed, in contrast to WPF can still be cancelled.

Eric Pitz
  • 364
  • 2
  • 6