5

我一直在尝试从桌面应用程序获取系统上安装的所有 UWP 应用程序的显示名称(应用程序的用户友好名称)。我正在尝试使用SHLoadIndirectString()从与这些应用程序对应的注册表项获得的资源字符串。让我们以 windows 计算器为例。

SHLoadIndirectString() 用法

它的资源字符串可以从HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\‌​Repository\Packages\‌​Microsoft.WindowsCal‌​culator_10.1705.1301‌​.0_x64__8wekyb3d8bbw‌​e\DisplayName注册表项中获取。我系统上的资源字符串是@{Microsoft.WindowsCalculator_10.1705.1301.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.WindowsCalculator/Resources/AppStoreName}

要获得显示名称,我会这样做SHLoadIndirectString(@{Microsoft.WindowsCalculator_10.1705.1301.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.WindowsCalculator/Resources/AppStoreName})

实验观察

  1. (实验 1)我用于SHLoadIndirectString()两个不同的用户(U1 和 U2)。U1 的语言设置为英语,U2 的语言设置为法语(FR-fr)。当 SHLoadIndirectString() 从 U1 运行时,它返回Windows Calculator,而对于 U2,我得到了Calculatrice Windows. 因此,相同资源字符串的返回值取决于当前用户的语言设置。
  2. (实验2)我在U2中安装了一个UWP应用,对DiplayName中的资源字符串做了SHLoadIndirectString()。我在 U1 中遇到错误,但在 U2 中,它正确地给了我所需的字符串。
  3. (实验 3)当我将资源文件的路径添加(resources.pri)到资源字符串时,我在 U1 中没有错误。之前的资源字符串是@{DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar_5.1.12.0_x64__3nf5xjt6s13jt?ms-resource://DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar/Resources/AppName},我后来@{C:\\Program Files\\WindowsApps\\DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar_5.1.12.0_x64__3nf5xjt6s13jt\\resources.pri?ms-resource://DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar/Resources/AppName}在传递给 之前对其进行了SHLoadIndirectString()

寻找解决方案

  1. SHLoadIndirectString() 的文档说它的返回值取决于Shell environment or ResourceContext,但没有给出每个细节的详细信息。
  2. 尝试重新创建 windows NT API 以运行 windows 应用程序的两个项目是ReactOSwine。我查看了他们的源代码以找到 的实现SHLoadIndirectString(),但代码似乎所做的只是在删除开头LoadLibrary()的符号后对资源字符串执行 a 操作。@这没有任何意义,为什么系统中会有这样的dll,因为每个应用程序的资源字符串都不一样?

4

1 回答 1

5

从 Windows XP 到 Windows 7SHLoadIndirectString仅使用MSDN 上记录LoadLibrary@filename.dll,resource语法。文件类型注册的MUIVerb条目可能是最常见的用法。

在 Windows 8 中,它被扩展为支持其他来源,特别是 WinRT/Modern/Store 应用程序使用的.PRI 文件(包资源索引)。

要确切了解它是如何工作的,您可以在调试器中单步执行它,但这些实现细节不是您应该依赖的,您应该只使用文档化的 API。

在 Windows 8 上,它使用 MrmCoreR.dll ( ) 中的各种函数来提取包名,然后使用++mrmcorer!Microsoft::Resources::Runtime::CResource*构建路径,然后调用以获取首选语言列表。然后它从路径构建一个字符串(它转换为),因此它可以检查资源字符串是否缓存在. 如果不是,它会使用资源管理器读取字符串。ResourceContext如何工作(语言、DPI 比例等)以及它如何从 .pri 文件中找到真正来源的确切细节可能超出了这个问题的范围,并且本身就是一个更大的主题。KERNEL32!PackageIdFromFullNameKERNEL32!GetPackagePath"\resources.pri"Bcp47Langs!Windows::Internal::CLanguagesListFactory::GetUserLanguages\%5HKCU\Software\Classes\Local Settings\MrtCache

于 2017-09-01T19:02:02.680 回答