以编程方式获取已安装应用程序可执行文件的列表(Windows10、C#)

Asy*_*Asy 3 .net c# windows winapi known-folders

我想要获取在 Windows 10 上安装并可执行的应用程序列表 - 即用户可以启动的应用程序的可执行文件(UWP 和非 UWP)。对于 UWP 应用程序,我想获取其 AppUserModelId。对于非 UWP 应用程序,我想获取可执行文件的文件位置。

到目前为止,我已经尝试过:1)遍历注册表并迭代已安装的应用程序。但是,此方法会遍历所有已安装的应用程序,返回的列表将包括类似的内容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;
         }
     }
}

Run Code Online (Sandbox Code Playgroud)

执行为:

string[] names = AppsFolder.GetItemNames(AppsFolder.ESHGDN.SHGDN_INFOLDER).ToArray();
for (int i=0; i<names.Length; i++)
{
    Console.WriteLine(names[i]);
}
Run Code Online (Sandbox Code Playgroud)

ILaunchSourceAppUserModelID接口提供了一种获取 AppUserModelID 的方法,但我不确定如何通过我的 IShellFolder 接口访问该接口。另外,如何获取 AppsFolder 虚拟文件夹中的实际文件位置到实际 exe 文件路径?

use*_*903 7

看看这个答案。

简而言之,将Microsoft.WindowsAPICodePack-Shell nuget 包添加到您的项目中,然后使用以下代码:

// GUID taken from https://learn.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)
{
    // The friendly app name
    string name = app.Name;
    // The ParsingName property is the AppUserModelID
    string appUserModelID = app.ParsingName; // or app.Properties.System.AppUserModel.ID
    // You can even get the Jumbo icon in one shot
    ImageSource icon =  app.Thumbnail.ExtraLargeBitmapSource;
}
Run Code Online (Sandbox Code Playgroud)

启动应用程序:

System.Diagnostics.Process.Start("explorer.exe", @" shell:appsFolder\" + appUserModelID);
Run Code Online (Sandbox Code Playgroud)

适用于常规应用程序和商店应用程序。