我正在尝试从另一个应用程序还原一个最小化的,暂停的UWP 应用程序, 但我无法找到可行的解决方案。
通过PInvoke使用.NET Core 2.2和Win32 API
我尝试设置窗口位置,设置窗口位置,但没有任何效果。我发现的唯一原因是我要还原的进程已暂停。 我做了一些研究,该应用程序是一个由WinRT堆栈管理的UWP。可悲的是我找不到恢复该过程并显示它的方法
每一个帮助或建议,我们都很感激。
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
}
答案 0 :(得分:1)
实际上,我认为窗口确实是UWP应用程序的一部分并不重要。
您可以通过Win32调用ShowWindow(hwnd,SW_RESTORE)恢复Mail的主窗口。但是,诀窍是您必须找到正确的窗口。在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>(¶m));
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”的进程ID,枚举该窗口的WNDPROC在该进程所拥有的线程中运行的所有窗口,然后ShowWindow-拥有这些窗口的所有窗口,其中之一是“邮件”主窗口。
您可以通过平台调用完成上述操作,或者找到一种更简单的方法,或者将上面的代码放入DLL中,然后通过DLLImport在C#中调用它。
答案 1 :(得分:1)
问题不是因为该进程已被挂起,而是我无法通过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);
}
}
}