Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enumerating Windows Portable Devices in C#

Tags:

c#

.net

wpd

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 implemented enumeration of device IDs following the MSDN documentation link and various blogs link, but they all result in the same issue - I can only get it to give me the ID of one device when there are several connected.

Here's the snippet of C# code I am using:

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;

I have two devices connected to my computer, one Removable USB memory stick and one digital camera. When both are active, only the device ID of my camera will be returned. When I deactivate the camera, the device ID of the removable USB stick is returned.

Is there anyone with experience with this API which can point me in the direction of what I am doing wrong?

like image 351
Jaran Avatar asked May 28 '11 13:05

Jaran


3 Answers

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.

like image 124
Christophe Geers Avatar answered Nov 10 '22 13:11

Christophe Geers


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.

like image 3
Bruno Klein Avatar answered Nov 10 '22 13:11

Bruno Klein


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/

like image 1
Kiquenet Avatar answered Nov 10 '22 14:11

Kiquenet