Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HeadedDemo not working when the device locked screen or logged out #55

Open
liudanking opened this issue Apr 5, 2016 · 14 comments
Open
Labels
Milestone

Comments

@liudanking
Copy link

I run HeadedDemo as a small web server on machine A, and visit it from a remote machine B.
All works well when I log in machine A.
When I log out machina A and keep HeadedDemo running on machine A, I can NOT get any response from machine B. If I log in machine A from remote-desptop app again, response is returned as what I want.
Is this what windows universal app designed for? Can I keep HeadedDemo running even I log out machine A?

@liudanking liudanking changed the title HeadedDemo not working when the device locked screen HeadedDemo not working when the device locked screen or logged off Apr 5, 2016
@liudanking liudanking changed the title HeadedDemo not working when the device locked screen or logged off HeadedDemo not working when the device locked screen or logged out Apr 5, 2016
@tomkuijsten
Copy link
Owner

What do yo mean with "when I log out", because if you would really do that, the HeadedDemo will quit (as with all other apps). Do you mean you lock the screen, or close your remote session?

@liudanking
Copy link
Author

@tomkuijsten I mean close my remote session from machine A.

@Jark
Copy link
Collaborator

Jark commented Apr 6, 2016

Hey @liudanking,

I think this is because your app will be suspended when there's no active remote session, I think if you put this code in the OnLaunched event in the App.xaml it should work:

var extendedSession = new ExtendedExecutionSession();
extendedSession.Reason = ExtendedExecutionReason.Unspecified;
extendedSession.Description = "Serving requests";

var result = await extendedSession.RequestExtensionAsync();
if (result == ExtendedExecutionResult.Allowed)
{
    Debug.WriteLine("Background execution approved");
}
else
{
    Debug.WriteLine("Background execution denied");
}

See: http://blog.qmatteoq.com/the-new-background-features-in-windows-10/ for background information.

If this doesn't work you'll have to do use a BackgroundTask with a SocketActivityTrigger and somehow call into (a copy of) the HttpServer: https://msdn.microsoft.com/en-us/windows/uwp/networking/network-communications-in-the-background which might be way too complex for what you're doing...

Cheers,

Jark

@tomkuijsten
Copy link
Owner

Would a headless app work for you, I guess that will work, even under lock. Worth the try.

@Jark
Copy link
Collaborator

Jark commented Apr 6, 2016

I think @liudanking is running on Windows 10, afaik headless apps are not (yet) supported there.

@liudanking
Copy link
Author

@Jark @tomkuijsten Yes, I am running HeadedDemo on Windows 10.
I have tested ExtendedExecutionSession with HeadedDemo, unfortunately, it did not work.
I can compile HeadlessDemo on my Windows 10 PC successfully, but when I try to launch it on my PC, it displays an error: Unable to activate Windows Store app 'xxxxx!App'. The activation request failed with error 'There are no more endpoints available from the endpoint mapper'. So, @Jark you are right, it is not supported on Windows 10 yet.

@liudanking
Copy link
Author

Hi @Jark
It seems that SocketActivityTrigger is interesting, and I would like to do an experiment with restup.
Currently, I can get a trigger in my background task, and get the socket obj, but I have no idea how to copy the socket data to restup httpserver. Can you give me some guide?

@Jark
Copy link
Collaborator

Jark commented Apr 8, 2016

Hey @liudanking,

I did test ExtendedExecutionSession and was getting good results with it, only thing I wasn't sure about is if I should've put the code in OnSuspended or not.

For SocketActivityTriger to work I would instantiate the http server and attach it to a static variable on the application class and use that to pass the socket back to HttpServer. You'd have to make some modifications to the source however to have a point where you can inject the socket.

Question I have is: do you really need support for uwp? If you can use standard .Net then the HttpListener might work better for you and gives you more flexibility.

@liudanking
Copy link
Author

@Jark
I need to call some functions which are only available in winRT/uwp, so standard .Net is not suitable.
On the whole, I am looking for a straightforward and clean solution to achieve this. Restup solves 99% of the problem, and I do not plan to move to other solutions.

I have tested ExtendedExecutionSession in OnLaunched function, but did not get a good result. I run HeadedDemo with Ctrl+F5 in visual studio 2015.

@liudanking
Copy link
Author

@Jark
I find an interesting thing: when in debugging, HeadedDemo will not be suspended.
So, start HeadedDemo in debug mode is the simplest way to keep the app running even I close remote session. But after googling a little, I have not figure out how to launch windows universal app in debug mode without visual studio.

@Jark
Copy link
Collaborator

Jark commented Apr 12, 2016

Hi @liudanking,

Apologies for the late reply, have been quite busy with personal and work life.

I don't know of any way to launch the app in debug mode without visual studio, but it might be worth revisiting the ExtendedExecutionSession, since it is supposed to disallow suspending, see: http://blog.qmatteoq.com/the-new-background-features-in-windows-10/

In my test (to be fair, I tested only once and didn't really tested it extensively) I did the following:

  • I added the code above to the app at the top of the OnLaunched method in App.cs
  • deployed the app on my local machine
  • remoted in, started up the HeadedDemo app, tested it works locally in the app and remotely from my phone
  • closed my rdp session, saw it still worked from my phone

It should be a lot easier to see what is happening after #42 is done, because then we can log any unhandled exceptions, if we're allowed the extended execution session or not, etc. But no one is currently working on that, so it might be a while before we can get to the bottom of it.

Let me know how you get on, would be very interested to hear if / how you get it to work!

Cheers,

Jark

@liudanking
Copy link
Author

Hi, @Jark

Appreciate your tracking.

I have tested ExtendedExecutionSession again with following code:

...
namespace HeadedDemo
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
                Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
                Microsoft.ApplicationInsights.WindowsCollectors.Session);
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }


        ExtendedExecutionSession extendedSession = null;

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected override async void OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();

            ////
            if (extendedSession == null)
            {
                extendedSession = new ExtendedExecutionSession();
            }
            extendedSession.Reason = ExtendedExecutionReason.LocationTracking;
            extendedSession.Description = "Location tracking";

            ExtendedExecutionResult result = await extendedSession.RequestExtensionAsync();
            if (result == ExtendedExecutionResult.Allowed)
            {
                //textBlockSrvStat.Text += "Background execution approved\n";
                Debug.WriteLine("Background execution approved");
            }
            else
            {
                //textBlockSrvStat.Text += "Background execution denied\n";
                Debug.WriteLine("Background execution denied");
            }


        }

        /// <summary>
        /// Invoked when Navigation to a certain page fails
        /// </summary>
        /// <param name="sender">The Frame which failed navigation</param>
        /// <param name="e">Details about the navigation failure</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            ShowToast("onsuspending");
            deferral.Complete();
        }

        public void ShowToast(string text)
        {
            var toastNotifier = ToastNotificationManager.CreateToastNotifier();
            var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            var textNodes = toastXml.GetElementsByTagName("text");
            textNodes.First().AppendChild(toastXml.CreateTextNode(text));
            var toastNotification = new ToastNotification(toastXml);
            toastNotifier.Show(new ToastNotification(toastXml));
        }
    }
}

Some interesting results learned:

  1. If I launch HeadedDemo, do NOT do anything with its GUI, then close rdp session directly, HeadedDemo will not be suspended, and will run like a service.
  2. After step 1, I re-connect to the machine through rdp, do nothing, then close rdp session, HeadedDemo seems be suspended, I can't get any response from it, but I can connect to its listener port.
  3. If I launch HeadedDemo, do something with its GUI(e.g., maximum window), then close rdp session , HeadedDemo will not response my http request.

From the article,http://blog.qmatteoq.com/the-new-background-features-in-windows-10/:

The application needs to continue the execution even when it’s suspended, for example to keep track of the user’s position (a fitness app, a turn by turn navigator, etc.)

The author may mean that: ExtendedExecutionSession does not promise that app will not be suspended, it promises that it can continue execution some code even in background or suspended. I say some code, because StreamSocketListener may be one of exceptions from my experimentals.

@tomkuijsten tomkuijsten added this to the 1.0 RC milestone May 26, 2016
@tomkuijsten
Copy link
Owner

Any new insights on this matter?

@tomkuijsten tomkuijsten modified the milestones: vFuture, 1.0 RC Jul 14, 2016
@tomkuijsten
Copy link
Owner

Looks like this is not really a common problem, as we don't get any other issue about this. I suggest to close it to keep the backlog clean (would still be accessible through the archive). Let me know if you think otherwise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants