Enumerating Windows Portable Devices in C#

后端 未结 6 1009
半阙折子戏
半阙折子戏 2020-12-14 04:09

I am attempting to enumerate connected portable devices on Windows using the Windows Portable Devices API and the PortableDeviceManager provided by this API.

I have

相关标签:
6条回答
  • 2020-12-14 04:51

    I am late to the party, but this is what worked for me:

    1. Download this NuGet package: PortableDevices

    2. Add references to these 4 COM libraries:

      • PortableDeviceClassExtension
      • PortableDeviceConnectApi
      • PortableDeviceTypes
      • PortableDeviceApi
    3. Take the dll's under obj\Debug and put them into bin\Debug:

      • Interop.PortableDeviceClassExtension.dll
      • Interop.PortableDeviceConnectApiLib.dll
      • Interop.PortableDeviceTypesLib.dll
      • Interop.PortableDeviceApiLib.dll

    Now you can use the following function to list all devices, although FriendlyName does not seem to be working (it returns an empty string):

        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;
        }
    

    The next step is getting the contents from the device, which is done like so:

    var contents = device.GetContents();
    
    0 讨论(0)
  • 2020-12-14 04:53

    Jaran,

    Take a look at the following post by the WPD team, it mentions how you can fix the interop assembly.

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

    Just to be complete, I'll mention the answer here as well:

    This is due to a marshalling restriction. This sample code will only detect one device. You need to manually fix the interop assembly.

    • Disassemble the PortableDeviceApi Interop assembly using the command:

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

    • Open the IL in Notepad and search for the following string:

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

    • Replace all instances of the string above with the following string:

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

    • Save the IL and reassemble the interop using the command:

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

    Rebuild your project. You can now first call GetDevices with a NULL parameter to get the count of devices and then call it again with an array to get the device IDs.

    Hope this helps.

    0 讨论(0)
  • 2020-12-14 04:53

    The one line of Power-shell script below un-mounts a USB cable attached Windows Portable Device (WPD) from the Windows Operating System (XP thru W8/2012)

    And just in case you have not yet started playing with Powershell, here is the equivalent VBScript (maybe be can port to 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
    

    Note change ‘SAMSUNG-SGH-I747′ to the phone/tablet name you see in Windows Explorer

    About Win32ext_WPD

    "Select * from Win32ext_WPD Where strFriendlyName = 'SAMSUNG-SGH-I747'"

    Not well document googleing, not found more 2 references.

    Maybe port to C# using:

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

    Reference:

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

    0 讨论(0)
  • 2020-12-14 05:00

    WPD-.NET-Wrapper on github - Can enumerate devices and copy files successfully. so that you don't have to waste time coding. you can just open, connect and copy...

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

    0 讨论(0)
  • 2020-12-14 05:00

    Maybe I'm wrong, but the line deviceManager.GetDevices(ref deviceIds[0], ref numberOfDevices); does not makes sense to me. If you want fill the array of string, you should pass whole array, not only one string.

    I found a post on blgs.msdn.com where is passed the whole array.

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

    However it's only guess. I hope, it will help you.

    EDIT: I found several code samples, where is passed whole array instead of first item: For example: http://social.msdn.microsoft.com/forums/en-US/vbgeneral/thread/22288487-caf3-4da5-855f-6447ad9fa48d

    And I found the Importing PortableDeviceApiLib generates incorrect Interop in VB.NET issue - it looks like the default interop assembly is not correct. Maybe the successfull way is getting correct interop assembly from someone and use it. Or use some another bridge between managed code (C#/VB.NET/...) and native code. The C++\CLI could be good way if you are good enough in C++.

    I found Portable Device Lib project on CodePlex - maybe it is the correct bridge.

    0 讨论(0)
  • 2020-12-14 05:07

    Just an update on the accepted answer.

    The correct replacement is as follows.

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

    to

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

    As per Andrew Trevarrow.

    0 讨论(0)
提交回复
热议问题