我正在尝试为Windows 10应用程序获取可理解的“进程名称”。 目前,他们都使用ApplicationFrameHost
,所以我认为我可以使用ModelId
或PackageName
,但似乎Windows 10商店应用程序(我尝试使用Mail
, Store
和Edge
)将无法使用包查询API
使用kernel32.dll
, GetApplicationUserModelId
返回APPMODEL_ERROR_NO_APPLICATION
, GetPackageId
返回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程序集,怎么做到这里看这里