Перечисление переносных устройств Windows в C # - PullRequest
12 голосов
/ 28 мая 2011

Я пытаюсь перечислить подключенные переносные устройства в Windows с помощью API переносных устройств Windows и PortableDeviceManager, предоставляемых этим API.

Я реализовал перечисление идентификаторов устройств в соответствии с документацией MSDN ссылка и различными блогами ссылка , но все они приводят к одной и той же проблеме - я могу только заставить его дать Идентификатор устройства one , когда подключено несколько устройств.

Вот фрагмент кода 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-накопитель и одна цифровая камера. Когда оба активны, будет возвращен только идентификатор устройства моей камеры. Когда я деактивирую камеру, возвращается идентификатор устройства съемного USB-накопителя.

Есть ли кто-нибудь с опытом работы с этим API, который может указать мне, что я делаю неправильно?

Ответы [ 6 ]

15 голосов
/ 29 мая 2011

Джаран,

Посмотрите на следующий пост команды 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, чтобы получить количество устройств, а затем снова вызвать его с массивом, чтобы получить идентификаторы устройств.

Надеюсь, это поможет.

1 голос
/ 26 августа 2014

В одной строке приведенного ниже сценария Power-shell отключается подключенный USB-кабель Переносное устройство Windows (WPD) из операционной системы Windows (XP - W8 / 2012)

Ина тот случай, если вы еще не начали играть с 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'"

Неправильно документ Google, не найдено больше 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/

0 голосов
/ 02 октября 2016

Я опаздываю на вечеринку, но вот что у меня сработало:

  1. Загрузите этот пакет NuGet: PortableDevices

  2. Добавить ссылки на эти 4 библиотеки COM:

    • PortableDeviceClassExtension
    • PortableDeviceConnectApi
    • PortableDeviceTypes
    • PortableDeviceApi
  3. Возьмите dll под obj\Debug и поместите их в bin\Debug:

    • Interop.PortableDeviceClassExtension.dll
    • Interop.PortableDeviceConnectApiLib.dll
    • Interop.PortableDeviceTypesLib.dll
    • Interop.PortableDeviceApiLib.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();
0 голосов
/ 12 ноября 2015

Просто обновление принятого ответа.

Правильная замена выглядит следующим образом.

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

на

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

Согласно Эндрю Треварроу .

0 голосов
/ 03 июля 2015

WPD-.NET-Wrapper на github - может успешно перечислять устройства и копировать файлы.так что вам не придется тратить время на кодирование.Вы можете просто открыть, подключить и скопировать ...

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

0 голосов
/ 28 мая 2011

Может быть, я ошибаюсь, но строка 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

И я обнаружил, что Импорт PortableDeviceApiLib генерирует некорректное взаимодействие в VB.NET - похоже, что сборка взаимодействия по умолчанию не правильная.Возможно, удачный способ - получить правильную сборку взаимодействия от кого-то и использовать ее.Или используйте какой-то другой мост между управляемым кодом (C # / VB.NET / ...) и собственным кодом.C ++ \ CLI может быть хорошим способом, если вы достаточно хороши в C ++.

Я нашел Portable Device Lib проект на CodePlex - возможно, это правильный мост.

...