我正在尝试使用Windows Portable Devices API和此API提供的PortableDeviceManager在Windows上枚举连接的便携式设备。
我已按照MSDN文档link和各种博客link实施了设备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。当我关闭相机时,将返回可移动USB记忆棒的设备ID。
是否有任何有此API经验的人可以指出我做错的方向?
答案 0 :(得分:15)
Jaran,
请看WPD团队的以下帖子,它提到了如何修复互操作程序集。
http://blogs.msdn.com/b/dimeby8/archive/2006/12/05/enumerating-wpd-devices-in-c.aspx
为了完成,我也会在这里提到答案:
这是由于编组限制。此示例代码仅检测一个设备。您需要手动修复互操作程序集。
使用以下命令反汇编PortableDeviceApi Interop程序集:
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
重建您的项目。您现在可以先使用GetDevices
参数调用NULL
来获取设备数量,然后使用数组再次调用它以获取设备ID。
希望这有帮助。
答案 1 :(得分:1)
下面的一行Power-shell脚本从Windows操作系统(XP到W8 / 2012)卸下连接Windows Portable Device (WPD)的USB电缆
如果你还没有开始玩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 = 'SAMSUNG-SGH-I747'“
不好的文档googleing,找不到更多2个引用。
可能使用以下方式移植到C#:
var oScope = new ManagementScope(@"\\" + MachineName + @"\root\cimv2");
参考:
答案 2 :(得分:0)
也许我错了,但deviceManager.GetDevices(ref deviceIds[0], ref numberOfDevices);
行对我来说没有意义。如果你想填充字符串数组,你应该传递整个数组,而不仅仅是一个字符串。
我发现post on 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 generates incorrect Interop in VB.NET问题 - 看起来默认的互操作程序集不正确。也许成功的方法是从某人那里获得正确的互操作程序集并使用它。或者在托管代码(C#/ VB.NET / ...)和本机代码之间使用另一个桥梁。如果你在C ++中足够好,那么C ++ \ CLI可能是个好方法。
我在CodePlex上找到了Portable Device Lib项目 - 也许它是正确的桥梁。
答案 3 :(得分:0)
WPD-.NET-Wrapper - 可以成功枚举设备和复制文件。这样你就不必浪费时间编码。你可以打开,连接和复制......
答案 4 :(得分:0)
只是对已接受答案的更新。
正确的替换如下。
GetDevices([in][out] string& marshal( lpwstr) pPnPDeviceIDs,
到
GetDevices([in][out] string[] marshal( lpwstr[]) pPnPDeviceIDs,
答案 5 :(得分:0)
我迟到了,但这对我有用:
下载此NuGet包:PortableDevices
添加对这4个COM库的引用:
将{d}放在obj\Debug
下并将其放入bin\Debug
:
现在您可以使用以下函数列出所有设备,虽然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();