首页 > 解决方案 > 如何使用 c# 从 shell:AppsFolder 虚拟文件夹中检索项目及其详细信息?

问题描述

我正在尝试从 FOLDERID_AppsFolder 中获取所有项目,您可以通过运行explorer.exe shell:appsFolder命令访问这些项目,以及它们的详细信息,特别是 AppUserModelID。

我可以使用下面的代码获取项目的名称,但我不确定如何获取 AppUserModelID。我能以某种方式得到这个值吗?

IShellItem appsFolder;
string str;
var res = ShellItemUtilities.SHGetKnownFolderItem(ShellItemUtilities.FOLDERID_AppsFolder,
              0, IntPtr.Zero, typeof(IShellItem).GUID, out appsFolder);
if (res < 0) return;

try
{
    var pidl = default(PIDLIST_ABSOLUTE);
    foreach (var app in appsFolder.Enumerate())
    {                    
        try
        {
            recyleBin.GetDisplayName(2, out ptr);
            // Get the actual name of the item
            str = Marshal.PtrToStringUni(ptr);
        }
        finally
        {   
            if (ptr != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(ptr);
                ptr = IntPtr.Zero;
            }
        }
    }
}
...

也许该IShellItem::GetAttributes方法是我需要的,但它只能检索我通过sfgaoMask参数指定的属性,并且有关此参数值的文档不包括与 AppUserModelID 相关的任何内容。

作为参考,apps 文件夹如下所示: 在此处输入图像描述

标签: c#

解决方案


你能听到蟋蟀的叫声吗?

当我偶然发现Microsoft.WindowsAPICodePack-Shell nuget 包时,我最终能够找到解决此问题的方法,该包包装了我需要的所有 shell 命令,因此我不必 P/Ivoke 它们。代码现在变为:

// GUID taken from https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid
var FODLERID_AppsFolder = new Guid("{1e87508d-89c2-42f0-8a7e-645a0f50ca58}");
ShellObject appsFolder = (ShellObject)KnownFolderHelper.FromKnownFolderId(FODLERID_AppsFolder);

foreach (var app in (IKnownFolder)appsFolder)
{
    string name = app.Name;
    // The ParsingName property is the AppUserModelID
    string appUserModelID = app.ParsingName; // or app.Properties.System.AppUserModel.ID
    ImageSource icon =  app.Thumbnail.MediumBitmapSource;
}

ShellObject 对象实际上包含更多可通过其 Properties.System 属性获得的属性。

如果您想知道为什么我将appsFolder 转换为ShellObjectat 实例化只是为了将其转换回IKnownFolder枚举时,那是因为API 代码包实际上带有a ShellObjectWatcher,它接受aShellObject并监视它的更改。如果安装了一个新应用程序并且它被列在这个虚拟文件夹中,那么观察者可以用来监控这个:

ShellObjectWatcher sow = new ShellObjectWatcher(appFolder, false);
sow.AllEvents += (s, e) => DoWhatever();
sow.Start();

推荐阅读