枚举设备的shell

时间:2017-12-08 00:10:49

标签: c# shell com

有两种实用方法可以从C#访问Shell命名空间,将MS WindowsApiCodePack桥连接到IShellFolder以及相关内容(在NuGet上可用),或者直接引用Shell32(Microsoft Shell控件和自动化)。这两种方法基本相似,尽管第一种方法具有更多功能(我最感兴趣的是支持图像缩略图和更好的文件复制功能)。

枚举此PC 文件夹:

string ThisPC = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
var folder = ShellFolder.FromParsingName(ThisPC) as ShellFolder;
foreach (var child in folder)

var shellAppType = Type.GetTypeFromProgID("Shell.Application");
object shell = Activator.CreateInstance(shellAppType);
var ThisPC = (Folder)shellAppType.InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, shell, new object[] { 0x11 });
foreach (FolderItem child in ThisPC.Items())

但两者之间有一个非常重要的区别:第二个枚举设备,如连接手机,而第一个没有。我使用Api Code Pack是开源的并且修改了ShellFolderItems构造函数(这是ShellFolder迭代的东西)来尝试

HResult hr = nativeShellFolder.NativeShellFolder.EnumObjects(
  IntPtr.Zero,
  //ShellNativeMethods.ShellFolderEnumerationOptions.IncludeHidden | ShellNativeMethods.ShellFolderEnumerationOptions.IncludeSuperHidden |
  //ShellNativeMethods.ShellFolderEnumerationOptions.Shareable |
  ShellNativeMethods.ShellFolderEnumerationOptions.Folders | ShellNativeMethods.ShellFolderEnumerationOptions.NonFolders | ShellNativeMethods.ShellFolderEnumerationOptions.Storage,
  out nativeEnumIdList);

最初为文件夹和NonFolders过滤的代码,但这首先排除了手机。所以我添加了存储,隐藏的东西,我能想到的所有组合,但没有任何区别。某些过滤器组合将删除已枚举的项目,但不会将其增加到设备。

我能做些什么才能使第一种方法与第二种方法一样枚举?

更新:使更容易重现,这是整个程序,真的不比上面描述的更多:

using System;
using System.Reflection;
using Microsoft.WindowsAPICodePack.Shell;
using Shell32;

namespace ConsoleApp1 {
  class Program {

    private static void ShellObjects1() {
      string ThisPC = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}";
      var folder = ShellFolder.FromParsingName(ThisPC) as ShellFolder;
      foreach (var child in folder)
        Console.WriteLine($"{child.Name} = {child.ParsingName}");
    }

    private static void ShellObjects2() {
      var shellAppType = Type.GetTypeFromProgID("Shell.Application");
      object shell = Activator.CreateInstance(shellAppType);
      var ThisPC = (Folder)shellAppType.InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, shell, new object[] { 0x11 });
      foreach (FolderItem child in ThisPC.Items())
        Console.WriteLine($"{child.Name} = {child.Path}");
    }

    static void Main(string[] args) {
      Console.WriteLine("WindowsAPICodePack");
      ShellObjects1();
      Console.WriteLine();

      Console.WriteLine("Shell32");
      ShellObjects2();
      Console.WriteLine();
    }

  }
}

您应该从COM项中添加对Microsoft Shell的引用,并安装Microsoft.WindowsAPICodePack-Shell NuGet包以进行编译。当我运行这个时,两个列表几乎完全相同。就像在Explorer窗口中一样,首先是文件夹,然后是驱动器。但是在第二个列表中,将会有一个额外的条目:一个设备。就像在Explorer中一样。第一个清单中缺少该项目。

1 个答案:

答案 0 :(得分:0)

哦,亲爱的,雷声,这是一个古老的STAThread失踪。有点误导,因为它的大部分都在工作,所以可能是评论结尾附近提到的IDelegateFolder使得单一界面错过了节拍。

[STAThread]
static void Main(string[] args) {