【发布时间】:2019-10-09 10:17:04
【问题描述】:
我想获取在 Windows 10 上安装和可执行的应用程序列表——即用户可以启动的应用程序的可执行文件(UWP 和非 UWP)。对于 UWP 应用,我想获取它的 AppUserModelId。对于非 UWP 应用,我想获取可执行文件的文件位置。
到目前为止,我已经尝试过:
1) 遍历注册表并遍历installed applications。但是,此方法会遍历所有已安装的应用程序,返回的列表将包括 microsoft asp.net core 2.1.8 shared framework (x64) 之类的内容,我想将其删除。
2) 我发现我可以通过特殊的Appsfolder 访问我想要的内容,方法是在资源管理器窗口或运行中键入shell:Appsfolder。到目前为止,我能够访问此文件夹,并遍历项目并列出文件的名称。但我不确定如何收集有关 AppUserModelId(对于 UWP 应用)和文件路径(对于 WPF 应用)的信息。
我用来枚举Appsfolder文件的相关代码:
namespace AppsFolder
{
...
public static class AppsFolder
{
...
// GUID for shell:Appsfolder
public static readonly Guid KnownFolderID = new Guid("1e87508d-89c2-42f0-8a7e-645a0f50ca58");
public static IEnumerable<string> GetItemNames(ESHGDN gdn)
{
IShellFolder appsFolder = GetAppsFolder();
try
{
IntPtr enumIDListInterfacePointer;
appsFolder.EnumObjects(IntPtr.Zero,
ESHCONTF.SHCONTF_NONFOLDERS | ESHCONTF.SHCONTF_FOLDERS,
out enumIDListInterfacePointer);
using (var enumIDList = new
EnumIDListWrapper(enumIDListInterfacePointer))
{
var names = new List<string>();
foreach (var pidl in enumIDList)
{
STRRET name;
recycleBin.GetDisplayNameOf(
pidl.DangerousGetHandle(),
gdn,
out name);
names.Add(STRRETToString(ref name, pidl));
if (name.uType != (int)STRRETType.Offset)
Marshal.FreeCoTaskMem(name.data.pOleStr);
}
return names;
}
}
finally
{
Marshal.FinalReleaseComObject(recycleBin);
}
}
private static IShellFolder GetAppsFolder()
{
IShellFolder desktop;
NativeMethod.SHGetDesktopFolder(out desktop);
try
{
Guid shellFolderInterfaceId = typeof(IShellFolder).GUID;
IntPtr recycleBinShellFolderInterfacePointer;
desktop.BindToObject(
GetItemIDList().DangerousGetHandle(),
IntPtr.Zero,
ref shellFolderInterfaceId,
out recycleBinShellFolderInterfacePointer);
return (IShellFolder)Marshal.GetObjectForIUnknown(
recycleBinShellFolderInterfacePointer);
}
finally
{
Marshal.FinalReleaseComObject(desktop);
}
}
public static SafeCoTaskMemHandleZeroIsInvalid GetItemIDList()
{
SafeCoTaskMemHandleZeroIsInvalid pidl;
Guid guid = KnownFolderID;
NativeMethod.SHGetKnownFolderIDList(
ref guid, 0, IntPtr.Zero, out pidl);
return pidl;
}
}
}
执行为:
string[] names = AppsFolder.GetItemNames(AppsFolder.ESHGDN.SHGDN_INFOLDER).ToArray();
for (int i=0; i<names.Length; i++)
{
Console.WriteLine(names[i]);
}
ILaunchSourceAppUserModelID 接口提供了获取 AppUserModelID 的方法,但我不确定如何通过我的 IShellFolder 接口访问该接口。另外,如何将 AppsFolder 虚拟文件夹中的实际文件位置获取到实际 exe 的文件路径?
【问题讨论】:
-
您所描述的仅适用于向操作系统注册的应用程序,但这不是必需的。无需向操作系统注册即可安装和执行应用程序。如果您真的想找到所有内容,您最终可能不得不枚举整个文件系统。
-
好吧,我明白了。在这一点上,我只想找到那些在操作系统中注册的。你能推荐一个更好的方法吗?
标签: c# .net windows winapi known-folders