question

RM94 avatar image
0 Votes"
RM94 asked RoyLi-MSFT commented

UWP Restricted Capability "inputObservation"

Hi Devs,

i was looking to inputObservation restricted capability, MSDN doens't have any reference to its implementation.
Has anyone succeeded in getting keyboard input without having focus on the app?
I managed to bypass the suspended mode of the app minimized but i don't see any solution for keyboard/mouse input problem.

With Win32 apis it was easy to set up Hotkeys or use GetAsyncKeyState, but with UWP these apis are not supported and i would like to know if there's a new method.
There is only a reference in the whole UWP documentation about this "inputObservation" but i don't have any clue how to implement it.

Kind Regards,

Ros





windows-uwp
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RoyLi-MSFT avatar image
0 Votes"
RoyLi-MSFT answered

Hello,

Welcome to Microsoft Q&A!

Thank you for reporting this here. There are no more documents about the inputObservation Capability. I'll confirm it with the team later.

>>Has anyone succeeded in getting keyboard input without having focus on the app?

Generally, UWP apps won't be able to get the input if the app is not focused. UWP apps could not get user's actions like click or keyboard input outside the app. That's why the app needs to be focused.

>>I managed to bypass the suspended mode of the app minimized
May I know how you do that? Are you using ExtendedExecutionForegroundSession in your app? If it is, running in the background does not mean the app is focused.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RM94 avatar image
0 Votes"
RM94 answered RoyLi-MSFT commented

Hi there!

(I didn't get any notification for the answer)

>>Generally, UWP apps won't be able to get the input if the app is not focused. UWP apps could not get user's actions like click or keyboard input outside the app. That's why the app needs to be focused.

I understand that concept but the fact is that they added a way to do it, that restricted capability clearly refers to that. So it's wierd not having a clue about the implementation.

May I know how you do that? Are you using ExtendedExecutionForegroundSession in your app? If it is, running in the background does not mean the app is focused.

Nope! I had to scan through all MSDN pages to find out a solution that didn't need to use a Rescricted Capability. I found it in the last notes of a page.

I'll write here all my static class (FROM MSDN) to unlock this functionality the quickest way.

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Windows.ApplicationModel.ExtendedExecution;
 using Windows.Foundation;
    
 namespace UWPLimitations
 {
   /*Info added by Rossano Montori
  *
  * With this class you can run your application in background without any limit.
  * 
  * https://docs.microsoft.com/en-us/windows/uwp/launch-resume/run-minimized-with-extended-execution
  * 
  * MSDN: "On desktop devices running Windows 10 for desktop editions (Home, Pro, Enterprise, and Education), 
  * this is the approach to use if an app needs to avoid being suspended while it is minimized"
  * 
  * MSDN: "If the device is connected to wall power, 
  * there is no limit to the length of the extended execution time period. 
  * If the device is on battery power, the extended execution time period 
  * can run up to 10 minutes in the background."
  * 
  * NOTE: In debug time there isn't any limitation therefore you might notice it, to verify the real time extension please "Run without debug" (CTRL + F5)
  * 
  * MSDN: "These application lifecycle time constraints are disabled while the app is running under a debugger."
  * 
  */
    
     static class UWPBackgroundTimeLimit // ExtendedExecutionHelper from MSDN page
     {
         private static ExtendedExecutionSession session = null;
         private static int taskCount = 0;
    
         public static bool IsRunning
         {
             get
             {
                 if (session != null)
                 {
                     return true;
                 }
                 else
                 {
                     return false;
                 }
             }
         }
    
         public static async Task RequestSessionAsync(ExtendedExecutionReason reason, TypedEventHandler revoked, String description)
         {
             // The previous Extended Execution must be closed before a new one can be requested.       
             ClearSession();
    
             var newSession = new ExtendedExecutionSession();
             newSession.Reason = reason;
             newSession.Description = description;
             newSession.Revoked += SessionRevoked;
    
             if (revoked != null)
             {
                 newSession.Revoked += revoked;
             }
    
             ExtendedExecutionResult result = await newSession.RequestExtensionAsync();
    
             switch (result)
             {
                 case ExtendedExecutionResult.Allowed:
                     session = newSession;
                     break;
                 default:
                 case ExtendedExecutionResult.Denied:
                     newSession.Dispose();
                     break;
             }
             return result;
         }
    
         public static void ClearSession()
         {
             if (session != null)
             {
                 session.Dispose();
                 session = null;
             }
    
             taskCount = 0;
         }
    
         public static Deferral GetExecutionDeferral()
         {
             if (session == null)
             {
                 throw new InvalidOperationException("No extended execution session is active");
             }
    
             taskCount++;
             return new Deferral(OnTaskCompleted);
         }
    
         private static void OnTaskCompleted()
         {
             if (taskCount > 0)
             {
                 taskCount--;
             }
    
             //If there are no more running tasks than end the extended lifetime by clearing the session
             if (taskCount == 0 && session != null)
             {
                 ClearSession();
             }
         }
    
         private static void SessionRevoked(object sender, ExtendedExecutionRevokedEventArgs args)
         {
             //The session has been prematurely revoked due to system constraints, ensure the session is disposed
             if (session != null)
             {
                 session.Dispose();
                 session = null;
             }
    
             taskCount = 0;
         }
     }
 }

NOTICE: In debug mode your application never goes suspended even if it is not focused! Only the release version has this limitation.

And here is the quickest way to implement it:

 //enable on release
    
 await UWPBackgroundTimeLimit.RequestSessionAsync(ExtendedExecutionReason.Unspecified, 
                     null, "nothing");

After testing this class, i can tell that the application still runs calculations after losing focus, not just when minimized. Try it out.

I forgot, i'm targeting Windows Desktop, so "connected to power wall" it's enough to unlock the unlimited execution time.

You don't have to create a "background task" in order to access the execution extended time. Instead use "Task.Run" or "ThreadPool.RunAsync" to initiate a task that will run despite losing focus or being minimized.




· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I know how you made the app running without getting suspended now. But as I mentioned, UWP apps must get focused so that UWP apps could receive keyboard events. It's different from desktop apps that don't have such limitations.

0 Votes 0 ·

I was fine with that concept until i found the “inputObservation” capability. That describes exatly getting inputs without focus which means it is possibile via code.

What is the point of not giving the implementation but giving the capability?!
There is also the capability to interact with drivers which can lead in input observation as well.
They can decide not to allow my app in the store but i can still use sideload and use it for myself.

Since the capability is there it means that there is a documentation.

0 Votes 0 ·

Currently, there are no documents about inputObservation capability like which API will use it. This is also mentioned in my previous reply. So that we can't confirm if it works in the scenario you want. That's why I say at this moment UWP apps could not get keyboard input without getting focused.

0 Votes 0 ·