Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connecting UWP apps hosted by ApplicationFrameHost to their real processes

I am working on an WPF application to monitor my activities on my computer. I use Process.GetProcesses() and some filtering to get the processes I am interested in (example:Calculator) then I record their StartTime. I am also using WIN32/USER32 API method GetForegroundWindow() to get the window the user is using.

The problem is that when the windows are Windows/UWP applications they are always hosted by the process ApplicationFrameHost. So the GetForegroundWindow() method returns that window with a title (example:Calculator), but not the real process being hosted.

What I need is either another way to get the foreground window that includes the real process being hosted, or some way to connect the window to process.

Anyone that knows how to accomplish this? All help would be really appreciated.

like image 905
Chris Johnsson Avatar asked Sep 26 '16 12:09

Chris Johnsson


People also ask

How do I know if my application is UWP?

If the file location is the WindowsApps folder in Program Files, or Windows 10 refuses to open the folder, then it is a UWP App, because Win32 apps are stored in their own folder in Program Files (x86) and 64bit applications are stored in their own folder in Program Files . . .

Can I disable application frame host?

Can I Disable It? You can't actually disable this process. If you right-click it in the Task Manager and select “End Task”, the process will be closed. All your open UWP or Store apps—the new type of app included with Windows 10—will also be closed.

What is UWP in .NET core?

A common API surface across all devices Windows 10 introduced the Universal Windows Platform (UWP), which provides a common app platform on every device that runs Windows. The UWP core APIs are the same on all Windows devices.


1 Answers

I eventually found a way to do this, so I am going answer my own question so maybe someone in the future with the same problem could find it useful.

This is the class with the WinApiFunctions:

public class WinAPIFunctions
{
    //Used to get Handle for Foreground Window
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern IntPtr GetForegroundWindow();

    //Used to get ID of any Window
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
    public delegate bool WindowEnumProc(IntPtr hwnd, IntPtr lparam);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc callback, IntPtr lParam);

    public static int GetWindowProcessId(IntPtr hwnd)
    {
        int pid;
        GetWindowThreadProcessId(hwnd, out pid);
        return pid;
    }

    public static IntPtr GetforegroundWindow()
    {
        return GetForegroundWindow();
    }
}

And this is the class I used to test if it would work. I used it in a simple console program that just writes out the name of the process that has current focus:

class FindHostedProcess
{
    public Timer MyTimer { get; set; }
    private Process _realProcess;
    public FindHostedProcess()
    {
        MyTimer = new Timer(TimerCallback, null, 0, 1000);
        Console.ReadKey();
    }

    private void TimerCallback(object state)
    {
        var foregroundProcess = Process.GetProcessById(WinAPIFunctions.GetWindowProcessId(WinAPIFunctions.GetforegroundWindow()));
        if (foregroundProcess.ProcessName == "ApplicationFrameHost")
        {
            foregroundProcess = GetRealProcess(foregroundProcess);
        }
        Console.WriteLine(foregroundProcess.ProcessName);
    }

    private Process GetRealProcess(Process foregroundProcess)
    {
        WinAPIFunctions.EnumChildWindows(foregroundProcess.MainWindowHandle, ChildWindowCallback, IntPtr.Zero);
        return _realProcess;
    }

    private bool ChildWindowCallback(IntPtr hwnd, IntPtr lparam)
    {
        var process = Process.GetProcessById(WinAPIFunctions.GetWindowProcessId(hwnd));
        if (process.ProcessName != "ApplicationFrameHost")
        {
            _realProcess = process;
        }
        return true;
    }
}
like image 194
Chris Johnsson Avatar answered Sep 28 '22 09:09

Chris Johnsson