枚举C#中的Windows便携式设备

本文关键字:便携式 Windows 中的 枚举 | 更新日期: 2023-09-27 17:57:49

我正在尝试使用Windows portable devices API和此API提供的PortableDeviceManager枚举Windows上连接的便携式设备。

我已经在MSDN文档链接和各种博客链接之后实现了设备ID的枚举,但它们都会导致相同的问题——当有几个连接时,我只能让它给我一个设备的ID。

以下是我正在使用的C#代码片段:

PortableDeviceManagerClass deviceManager = new PortableDeviceManagerClass();
deviceManager.RefreshDeviceList();  
uint numberOfDevices = 1;            
deviceManager.GetDevices(null, ref numberOfDevices);
if (numberOfDevices == 0)
{
    return new string[0];
}
string [] deviceIds = new string[numberOfDevices];
deviceManager.GetDevices(ref deviceIds[0], ref numberOfDevices);
return deviceIds;

我有两个设备连接到我的电脑,一个可移动USB记忆棒和一个数码相机。当两者都处于活动状态时,将只返回我的相机的设备ID。当我停用相机时,会返回可移动U盘的设备ID。

有没有人有这个API的经验,可以为我指出我做错了什么?

枚举C#中的Windows便携式设备

Jaran,

看看WPD团队的以下文章,它提到了如何修复互操作程序集。

http://blogs.msdn.com/b/dimeby8/archive/2006/12/05/enumerating-wpd-devices-in-c.aspx

为了完整起见,我也会在这里提到答案:

这是由于编组限制。此示例代码将只检测一个设备。您需要手动修复互操作程序集。

  • 使用以下命令拆解PortableDeviceApi互操作程序集:

    ildasm Interop.PortableDeviceApiLib.dll /out:pdapi.il

  • 在记事本中打开IL并搜索以下字符串:

    instance void GetDevices([in][out] string& marshal( lpwstr) pPnPDeviceIDs,

  • 用以下字符串替换上面字符串的所有实例:

    instance void GetDevices([in][out] string[] marshal([]) pPnPDeviceIDs,

  • 保存IL并使用以下命令重新组装互操作:

    ilasm pdapi.il /dll /output=Interop.PortableDeviceApiLib.dll

重建您的项目。现在,您可以首先使用NULL参数调用GetDevices以获取设备计数,然后使用数组再次调用它以获取设备ID。

希望这能有所帮助。

只是接受答案的更新。

正确的更换如下。

GetDevices([in][out] string& marshal( lpwstr) pPnPDeviceIDs,

GetDevices([in][out] string[] marshal( lpwstr[]) pPnPDeviceIDs,

根据Andrew Trevarow的说法。

下面的一行Power shell脚本从Windows操作系统(XP到W8/2012)卸载USB电缆连接的Windows便携式设备(WPD)

如果你还没有开始玩Powershell,这里有等效的VBScript(可能是可以移植到C#的):

Set objWMIService = GetObject ("winmgmts:''.'root'cimv2")
Set colItems = objWMIService.ExecQuery ("Select * from Win32ext_WPD Where strFriendlyName = 'SAMSUNG-SGH-I747'")
For Each objItem in colItems
Set objWMIWPDStatic = objWMIService.Get("Win32ext_WPD")
Set objInParam = objWMIWPDStatic.Methods_("EjectDevice").inParameters.SpawnInstance_()
objInParam.Properties_.Item("strObjectDeviceId") =  objItem.strId
Set objOutParams = objWMIService.ExecMethod("Win32ext_WPD", "EjectDevice", objInParam)
Exit For
Next

注意将"SAMSUNG-SGH-I747"更改为您在Windows资源管理器中看到的手机/平板电脑名称

关于Win32ext_WPD

"从Win32ext_WPD中选择*其中strFriendlyName=三星SGH-I747

文档谷歌搜索不好,找不到更多的2个参考文献。

也许端口到C#使用:

var oScope = new ManagementScope(@"''" + MachineName + @"'root'cimv2");

参考:

http://squadratechnologies.wordpress.com/2013/07/24/windows-powershellvbscript-to-un-mount-a-smart-phone-or-tablet/

WPD-github上的.NET包装器-可以成功枚举设备和复制文件。这样您就不必浪费时间进行编码。你可以打开、连接和复制。。。

https://github.com/kumushoq/WPD-.NET-Wrapper/blob/2d502d883b981b8bc57d32389e8280877632f6de/WindowsPortableDeviceNet/Utility.cs

我参加聚会迟到了,但这对我来说很有效:

  1. 下载此NuGet包:PortableDevices

  2. 添加对这4个COM库的引用:

    • PortableDeviceClassExtension
    • PortableDeviceConnectApi
    • 便携式设备类型
    • PortableDeviceApi
  3. obj'Debug下的dll放入bin'Debug:

    • Interop.PortalDeviceClassExtension.dll
    • Interop.PortalDeviceConnectApiLib.dll
    • Interop.PortalDeviceTypesLib.dll
    • Interop.PortalDeviceApiLib.dll

现在您可以使用以下函数列出所有设备,尽管FriendlyName似乎不起作用(它返回一个空字符串):

    private IDictionary<string, string> GetDeviceIds()
    {
        var deviceIds = new Dictionary<string, string>();
        var devices = new PortableDeviceCollection();
        devices.Refresh();
        foreach (var device in devices)
        {
            device.Connect();
            deviceIds.Add(device.FriendlyName, device.DeviceId);
            Console.WriteLine(@"DeviceId: {0}, FriendlyName: {1}", device.DeviceId, device.FriendlyName);
            device.Disconnect();
        }
        return deviceIds;
    }

下一步是从设备中获取内容,这样做:

var contents = device.GetContents();

也许我错了,但deviceManager.GetDevices(ref deviceIds[0], ref numberOfDevices);行对我来说没有意义。如果你想填充字符串的数组,你应该传递整个数组,而不仅仅是一个字符串。

我在blgs.msdn.com上发现了一篇帖子,其中传递了整个数组。

string[] deviceIDs = new string[cDevices];
devMgr.GetDevices(deviceIDs, ref cDevices);

不过这只是猜测。我希望它能帮助你。

编辑:我发现了几个代码示例,其中传递的是整个数组,而不是第一项:例如:http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/22288487-caf3-4da5-855f-6447ad9fa48d

我发现Importing PortableDeviceApiLib在VB.NET中生成了不正确的互操作问题——看起来默认的互操作程序集不正确。也许最成功的方法是从某人那里获得正确的互操作程序集并使用它。或者在托管代码(C#/VB.NET/…)和本机代码之间使用其他桥梁。如果您在C++方面足够优秀,那么C++''CLI可能是一个不错的方法。

我在CodePlex上找到了PortableDeviceLib项目——也许它是正确的桥接器。