如何从hWnd for Windows 10 Store应用程序(例如Edge)获取“应用程序名称”

我正在尝试为Windows 10应用程序获取可理解的“进程名称”。 目前,他们都使用ApplicationFrameHost ,所以我认为我可以使用ModelIdPackageName ,但似乎Windows 10商店应用程序(我尝试使用MailStoreEdge )将无法使用包查询API

使用kernel32.dllGetApplicationUserModelId返回APPMODEL_ERROR_NO_APPLICATIONGetPackageId返回APPMODEL_ERROR_NO_PACKAGE

我如何获得Windows 10商店应用程序的标识符,以便我可以唯一标识Edge ,还有其他任何Windows 10商店应用程序?


更新

我从hWnd (窗口句柄)获取进程ID,所以我认为我的问题实际上是如何从窗口句柄中获取“真实”进程ID。 从那里,使用这些方法可能会奏效。

GetPackageFullName / FamilyName / Id(hprocess,…)等返回APPMODEL_ERROR_NO_PACKAGE,如果进程没有包标识。 同上GetApplicationUserModelId(hprocess …)返回APPMODEL_ERROR_NO_APPLICATION,因为同样的过程没有应用程序标识。

听起来就像你有一个代表应用程序工作的HWND,但不是应用程序。 这是相当普遍的 – RuntimeBroker和其他进程作为“桌面应用程序”(即无W / O包或应用程序标识的进程)运行,作为中间商为他们自己无法完成的应用程序处理事务。

到你原来的问题,“我从hWnd(窗口句柄)获取进程ID,所以我认为我的问题实际上是如何从窗口句柄”获得真实“的进程ID”这是一个根本上有缺陷的方法。 你有一个HWND的PID,但是如果这个过程是一个经纪人,它可以代表多个应用程序工作 – 代理程序没有身份; 它知道每个请求/ WinRT API调用/等谁是调用者,并将其工作的范围,以该身份。 在流程层面你无法发现。

您可以使用GetPackageId() ,然后使用PackageFullNameFromId() 。

例如:

 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); 

下面是在Windows 8/10中获取实际进程名称, 活动窗口进程名称的类似

使用Spy ++实用程序,确认Windows.Core.UI.CoreWindow是天气的子窗口,并且是我们感兴趣的窗口。(Win10 10563验证)

所以首先有一个叫做AppUserModelID的东西,它是任务栏用来分组窗口的窗口的ID。 因为所有的WinRT窗口都来自同一个进程,但是没有分组,这意味着每个应用都有自己的UserModelID。

要从HWND获得UserModelID,您可以使用此答案中的方法。

 #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); 

并且prop将包含值LPWSTR = 0x00838f68 L"Microsoft.BingWeather_8wekyb3d8bbwe!App" 。 这是完整的入口点名称格式<FullPackageFamilyName>!<EntryPoint> 。 启动应用程序的入口点通常称为App 。 入口点在应用程序清单中定义。

另外有趣的事情 – 应用程序拥有的子窗口不被破坏,而是从应用程序框架主机移到桌面窗口。 我不知道为什么会发生,但是你必须小心,因为FindWindow(nullptr, L"Weather")返回了子应用程序窗口而不是appframehost窗口。

PS AppUserModelID只是一个字符串,它的格式没有记录,所以这个方法并不是最可靠的。

PPS另外我注意到你想要有图标和名字,你可以使用PackageManager来做这件事,它需要你引用winmd程序集,怎么做到这里看这里