【问题标题】:How does SHLoadIndirectString() work internally?SHLoadIndirectString() 如何在内部工作?
【发布时间】:2018-02-10 19:26:00
【问题描述】:

我一直在尝试从桌面应用程序获取系统上安装的所有 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)。当从 U1 运行 SHLoadIndirectString() 时,它返回 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()'s documentation 表示它的返回值取决于 Shell environment or ResourceContext,但没有给出每个细节的详细信息。
  2. 尝试重新创建 Windows NT API 以运行 Windows 应用程序的两个项目是 ReactOSwine。我查看了他们的源代码以找到SHLoadIndirectString() 的实现,但代码似乎所做的只是在删除开头的@ 符号后在资源字符串上执行LoadLibrary()。这没有任何意义,为什么系统中会有这样的dll,因为每个应用程序的资源字符串都不一样?

【问题讨论】:

  • 这是一个非常庞大和复杂的 api。还有什么更具体的问题?

标签: winapi wine react-os


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2019-01-13
    • 2010-10-14
    • 2013-09-28
    • 2012-08-01
    • 2011-12-10
    • 2014-09-29
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多