C# 如何获得;“应用程序名称”;来自适用于Windows 10应用商店应用的hWnd(例如Edge)
我正在尝试为Windows 10应用程序获取一个可理解的“进程名称”。目前,它们都使用C# 如何获得;“应用程序名称”;来自适用于Windows 10应用商店应用的hWnd(例如Edge),c#,windows,windows-10,kernel32,C#,Windows,Windows 10,Kernel32,我正在尝试为Windows 10应用程序获取一个可理解的“进程名称”。目前,它们都使用ApplicationFrameHost,所以我想我可以使用ModelId或PackageName,但似乎Windows 10应用商店应用程序(我尝试了Mail、Store和Edge)无法与 使用kernel32.dll,GetApplicationUserModelId返回APPMODEL\u ERROR\u NO\u APPLICATION和GetPackageId返回APPMODEL\u ERROR\u
ApplicationFrameHost
,所以我想我可以使用ModelId
或PackageName
,但似乎Windows 10应用商店应用程序(我尝试了Mail
、Store
和Edge
)无法与
使用kernel32.dll
,GetApplicationUserModelId
返回APPMODEL\u ERROR\u NO\u APPLICATION
和GetPackageId
返回APPMODEL\u ERROR\u NO\u PACKAGE
如何获取Windows 10应用商店应用程序的标识符,以便我可以唯一地标识(例如)任何其他Windows 10应用商店应用程序
更新 我从
hWnd
(窗口句柄)获取进程ID,因此我认为我的问题实际上是如何从窗口句柄获取“真实”进程ID。从那时起,使用这些方法可能会起作用。您可以使用和
例如:
HANDLE hProcess=OpenProcess(
处理查询有限的信息,
假,,
pe32.th32ProcessID);
UINT32缓冲长度=0;
LONG result=GetPackageId(hProcess,&bufferLength,nullptr);
字节*buffer=(PBYTE)malloc(bufferLength);
结果=GetPackageId(hProcess和bufferLength,buffer);
PACKAGE_ID*packageId=重新解释转换(缓冲区);
wprintf(L“名称:%s\n”,packageId->Name);
GetPackageFullName/FamilyName/Id(HPProcess,…)等如果进程没有包标识,则返回APPMODEL\u ERROR\u NO\u包。同上,GetApplicationUserModelId(HPProcess…)返回APPMODEL\u ERROR\u NO\u APPLICATION,因为该进程同样没有应用程序标识
听起来您有一个HWND,它代表应用程序工作,但不是应用程序。这是很常见的-RuntimeBroker和其他进程作为“桌面应用程序”(即进程w/o包或应用程序标识)运行,作为代理为应用程序进程执行它们自己无法执行的操作
对于您最初的问题,“我从hWnd(窗口句柄)获取进程ID,所以我认为我的问题实际上是如何从窗口句柄获取“真实”的进程ID”这是一种根本上有缺陷的方法。您有一个来自HWND的pid,但是如果进程是一个代理,它可以代表多个应用程序工作-代理进程没有标识;它知道*per-request/WinRT-API-call/etc调用方是谁,并将其工作范围限定为该标识。您无法在进程级别发现这一点。因此,首先有一个东西叫做,它是任务栏用来对窗口进行分组的窗口ID。因为所有WinRT窗口都来自同一进程,但它们没有分组,这意味着每个应用程序都有自己的UserModelID 要从HWND获取UserModelID,可以使用中的方法
#包括“Propsys.h”
#包括
#pragma注释(lib,“Shell32.lib”)
//.........
IPropertyStore*propStore;
自动weatherWnd=FindWindow(L“应用程序框架窗口”,L“天气”);
SHGetPropertyStoreForWindow(weatherWnd、IID_IPropertyStore、(void**)和propStore);
道具变体道具;
propStore->GetValue(PKEY\u AppUserModel\u ID和prop);
和prop
将包含值LPWSTR=0x00838f68 L“Microsoft.BingWeather\u 8wekyb3d8bbwe!App”
。这是格式为的完整入口点名称代码>。启动的应用程序的入口点通常称为App
。入口点在应用程序清单中定义
还有一件有趣的事——应用程序拥有的子窗口并没有被破坏,而是从应用程序框架主机移到了桌面窗口。我不知道为什么会发生这种情况,但您必须小心,因为FindWindow(nullptr,L“Weather”)
返回的是子应用程序窗口,而不是appframehost窗口
p.S.AppUserModelID只是一个字符串,其格式没有文档记录,因此此方法并非最可靠的方法
p.p.S.我还注意到,你想要有图标和名称,你可以使用它,它要求你引用winmd程序集,如何做这个看起来是一个类似的获得实际进程名称的方法,
使用Spy++实用程序,确认Windows.Core.UI.CoreWindow是天气的子窗口,它是我们感兴趣的窗口。(在Win10 10563上验证)应用程序被包装到其他应用程序/进程中。如果有焦点,那么尝试找到子UWP进程
您将需要一些p/Invoke方法。看看这个类,它提供了完成这项工作所需的所有代码:
使用系统;
使用System.IO;
使用System.Runtime.InteropServices;
使用系统文本;
命名空间堆栈溢出
{
内部结构WINDOWINFO
{
公共单位所有者ID;
公共部门;
}
公共类计算机
{
#区域用户32
[DllImport(“user32.dll”)]
公共静态外部IntPtr GetForegroundWindow();
[DllImport(“user32.dll”,SetLastError=true)]
公共静态外部单元GetWindowThreadProcessId(IntPtr hWnd,out单元lpdwProcessId);
//当您不需要ProcessId时,请使用此重载并将IntPtr.Zero传递给第二个参数
[DllImport(“user32.dll”,SetLastError=true)]
公共静态外部IntPtr GetWindowThreadProcessId(IntPtr hWnd,IntPtr ProcessId);
///
///EnumChildWindows方法的委托
///
///窗把手
///调用方定义的变量;我们使用它作为指向列表的指针
///如果为True,则继续枚举,如果为false,则为bail。
公共委托bool EnumWindowProc(IntPtr hWnd,IntPtr参数);
[DllImport(“user32”,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部bool EnumChildWindows(IntPtr hwndpresent、EnumWindowProc lpEnumFunc、IntPtr lParam);
#端区
#区域核32
公安部门32过程查询信息
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION,
false,
pe32.th32ProcessID);
UINT32 bufferLength = 0;
LONG result = GetPackageId(hProcess, &bufferLength, nullptr);
BYTE* buffer = (PBYTE) malloc(bufferLength);
result = GetPackageId(hProcess, &bufferLength, buffer);
PACKAGE_ID* packageId = reinterpret_cast<PACKAGE_ID*>(buffer);
wprintf(L"Name: %s\n", packageId->name);
#include "Propsys.h"
#include <propkey.h>
#pragma comment (lib, "Shell32.lib")
//.........
IPropertyStore* propStore;
auto weatherWnd = FindWindow(L"ApplicationFrameWindow", L"Weather");
SHGetPropertyStoreForWindow(weatherWnd, IID_IPropertyStore, (void**)&propStore);
PROPVARIANT prop;
propStore->GetValue(PKEY_AppUserModel_ID, &prop);