Восстановить свернутое окно другого приостановленного приложения - PullRequest
0 голосов
/ 24 мая 2019

Я пытаюсь восстановить свернутое приостановленное приложение UWP из другого приложения , но мне не удается найти работоспособное решение.

Использование.NET Core 2.2 и Win32 API через PInvoke

Я попытался установить расположение окна, положение окна, но ничего не работает.Единственная причина, по которой я нахожу, заключается в том, что процесс, который я хочу восстановить, приостановлен.Я провел некоторое исследование, и приложение представляет собой UWP, которым управляет стек WinRT.к сожалению Я не могу найти способ возобновить процесс и отобразить его

Любая помощь или предложение приветствуется.

enter image description here

        Process proc = Process.GetProcessesByName("HxOutlook").FirstOrDefault();

        if (proc != null)
        {
            ShowWindow(proc.MainWindowHandle, SW_SHOWNORMAL);   // Make the window visible if it was hidden
            ShowWindow(proc.MainWindowHandle, SW_RESTORE);      // Next, restore it if it was minimized
            SetForegroundWindow(proc.MainWindowHandle);         // Finally, activate the window 
        }

Ответы [ 2 ]

1 голос
/ 26 мая 2019

Проблема заключалась не в том, что процесс был приостановлен, а в том, что я не смог получить правильный дескриптор окна через C # API (System.Diagnostics.Process). Вся заслуга в jwezorek, это реализация C #. (Есть проблемы, но работает)

    static UInt32 GetProccessByName(string targetProcessName)
    {
        UInt32[] processes = new UInt32[1024];
        UInt32 bytesCopied;

        if (!Psapi.EnumProcesses(processes, (UInt32)processes.Length, out bytesCopied))
        {
            return 0;
        }

        foreach (var pid in processes)
        {
            IntPtr handle = Kernel32.OpenProcess(
              (Kernel32.ProcessAccessFlags.QueryInformation |
                Kernel32.ProcessAccessFlags.VirtualMemoryRead),
                false,
                (int)pid);

            UInt32[] modules = new UInt32[1024];
            UInt32 bytesNeeeded;

            if (handle != null)
            {
                if (Psapi.EnumProcessModules(handle, modules, (UInt32)modules.Length, out bytesNeeeded))
                {
                    StringBuilder text = new StringBuilder(1024);
                    Psapi.GetModuleBaseName(handle, IntPtr.Zero, text, (UInt32)text.Capacity);

                    if (text.Equals(targetProcessName))
                    {
                        return pid;
                    }
                }
            }
        }

        return 0;
    }

    public static bool EnumProc(IntPtr hWnd, ref SearchData data)
    {
        UInt32 pid;

        User32.GetWindowThreadProcessId(hWnd, out pid);

        if(pid == data.PID)
        {
            data.Windows.Add(hWnd);
        }

        return true;
    }

    static List<IntPtr> GetWindowFromProcessID(UInt32 pid)
    {
        var searchData = new SearchData(pid);

        User32.EnumWindows(new User32.EnumWindowsProc(EnumProc), ref searchData);

        return searchData.Windows;
    }

    static void Main(string[] args)
    {
        var pid = GetProccessByName("HxOutlook.exe");

        var windows = GetWindowFromProcessID(pid);

        foreach (var window in windows)
        {
            var owner = User32.GetWindow(window, User32.GetWindowType.GW_OWNER);
            if(owner != null)
            {
                User32.ShowWindow(owner, SW_RESTORE);
            }
        }
    }
1 голос
/ 25 мая 2019

На самом деле я не думаю, что имеет значение, что окно является частью приложения UWP.

Вы можете восстановить главное окно Mail с помощью вызова Win32 ShowWindow (hwnd, SW_RESTORE). Однако хитрость в том, что вы должны найти правильное окно. В Spy ++ вы можете видеть, что это некое окно, которое имеет класс окна «ApplicationFrameWindow», связанный с процессом с именем модуля «APPLICATIONFRAMEHOST» - это должны быть артефакты реализации UWP.

Чтобы найти конкретное «ApplicationFrameWindow», которое является главным окном Mail, не полагаясь на что-то изменчивое или эфемерное, как текст окна, я обнаружил, что правильное окно является владельцем одного из окон, связанных с процессом HxOutlook.exe , Там могут быть менее запутанные, чтобы сделать это, но следующие работы. Это родное приложение командной строки, очевидно:

#include <Windows.h>
#include <psapi.h>
#include <tchar.h>
#include <vector>

DWORD GetProcessByName(const TCHAR* target_process_name)
{
    DWORD processes[1024], bytes_returned;

    if (!EnumProcesses(processes, sizeof(processes), &bytes_returned))
        return 0;
    int n = bytes_returned / sizeof(DWORD);
    for (int i = 0; i < n; i++) {
        auto pid = processes[i];
        TCHAR process_name[MAX_PATH] = TEXT("");
        HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
        if (process) {
            HMODULE module;
            DWORD bytes_needed;
            if (EnumProcessModules(process, &module, sizeof(module), &bytes_needed)) {
                GetModuleBaseName(process, module, process_name, sizeof(process_name) / sizeof(TCHAR));
                if (_tcscmp(process_name, target_process_name) == 0)
                    return pid;
            }
        }
    }
    return 0;
}

struct HwndFinder {
    std::vector<HWND> windows;
    DWORD pid;

    HwndFinder(DWORD pid) : pid(pid)
    {}
};

BOOL CALLBACK EnumWindowsFindProcessWindow(HWND hwnd, LPARAM lParam)
{
    DWORD pid;
    HwndFinder* param = reinterpret_cast<HwndFinder*>(lParam);
    GetWindowThreadProcessId(hwnd, &pid);
    if (pid == param->pid) {
        param->windows.push_back(hwnd);
    }
    return TRUE;
}

std::vector<HWND> GetWindowsFromProcessID(DWORD pid)
{
    HwndFinder param(pid);
    EnumWindows(EnumWindowsFindProcessWindow, reinterpret_cast<LPARAM>(&param));
    return param.windows;
}

int main()
{
    auto mail_process = GetProcessByName(TEXT("HxOutlook.exe"));
    auto windows = GetWindowsFromProcessID(mail_process);
    for (auto window : windows) {
        auto owner = GetWindow(window, GW_OWNER);
        if (owner)
            ShowWindow(owner, SW_RESTORE);
    }
    return 0;
}

Он находит идентификатор процесса для "HxOutlook.exe", перечисляет все окна, в которых WNDPROC для окна выполняется в потоке, принадлежащем этому процессу, и затем показывает окна всех окон, которые владеют этими окнами, одно из которых главное почтовое окно.

Вы можете сделать что-то подобное выше с помощью вызова платформы, или найти более простой способ, или поместить приведенный выше код в DLL и вызывать его в C # через DLLImport.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...