2013-04-19 2 views
5

У меня есть программа, которая обращается к нескольким последовательным портам с использованием cport.Имя или идентификатор последовательных портов (COM)

Чтобы настроить, до сих пор я просто перечислял все доступные компоненты в combobox, чтобы сделать выбор, но все большее число драйверов с (виртуальными) последовательными интерфейсами делает настройку для конечных пользователей неудобной.

Текущее обнаружение работает с createfile(), но у этой проблемы есть только то, что вы получаете только/nonexists и, возможно, «заняты» в качестве информации.

Однако, чтобы улучшить, мне нужно, чтобы на COM-порт была указана строка идентификации, например, аппаратное устройство/драйвер (диспетчер устройств). Это упростит пользователю сужение компоновки (поскольку мы доставим конечное число последовательных карт)

Возможно, это доступно от WMI, но это довольно джунгли, у sb есть более конкретная информация или лучше , код?

(Delphi XE3, Win7 +, не решения, которое требует дополнительной установки или развертывания пожалуйста)

+0

Возможный дубликат [Как определить, физически ли компьютер имеет последовательный порт?] (Http://stackoverflow.com/questions/5575372/how-to-determine-if-a-machine-physically-has-a -сериальный порт) –

+0

также: http://stackoverflow.com/q/613166/327083 ... есть jedi и т. д., компоненты, которые обеспечивают эту функциональность на высоком уровне, но если вы хотите сворачивать свои собственные, я думаю, что либо WMI, либо реестр - ваш единственный ресурс. –

+0

Что вы ищете, это, пожалуй, способ перечислить COM-порты, включая их «Friendly Names»? –

ответ

9

Если вы хотите перечислить COM-порты получать понятное имя вы можете использовать и класс интерфейс SetupAPIGUID_DEVINTERFACE_COMPORT устройства.

Попробуйте этот образец

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    Windows, 
    SysUtils, 
    JvSetupApi; 

const 
    GUID_DEVINTERFACE_COMPORT:TGUID='{86E0D1E0-8089-11D0-9CE4-08003E301F73}'; 

procedure EnumerateCOMPorts; 
var 
    cbRequired : DWORD; 
    hdev  : HDEVINFO; 
    idev  : Integer; 
    did  : TSPDeviceInterfaceData; 
    pdidd : PSPDeviceInterfaceDetailData; 
    PropertyBuffer : array[0..255] of Char; 
    DeviceInfoData: TSPDevInfoData; 
    PropertyRegDataType: DWORD; 
    RequiredSize: DWORD; 
begin 
    // enumerate the com ports 
    hdev := SetupDiGetClassDevs(@GUID_DEVINTERFACE_COMPORT, nil, 0, DIGCF_PRESENT OR DIGCF_DEVICEINTERFACE); 
    if (INVALID_HANDLE_VALUE <> THandle(hdev)) then 
    begin 
    try 
     idev:=0; 
     ZeroMemory(@did, SizeOf(did)); 
     did.cbSize := SizeOf(did); 
     repeat 
     if (SetupDiEnumDeviceInterfaces(hdev, nil, GUID_DEVINTERFACE_COMPORT, idev, did)) then 
     begin 
      cbRequired := 0; 
      SetupDiGetDeviceInterfaceDetail(hdev, @did, nil, 0, cbRequired, nil); 
      if (ERROR_INSUFFICIENT_BUFFER= GetLastError()) then 
      begin 
       pdidd:=AllocMem(cbRequired); 
       try 
       pdidd.cbSize := SizeOf(TSPDeviceInterfaceDetailData); 
       DeviceInfoData.cbSize:= SizeOf(DeviceInfoData); 
       RequiredSize:=0; 
       if (SetupDiGetDeviceInterfaceDetail(hdev, @did, pdidd, cbRequired, RequiredSize, @DeviceInfoData)) then 
       begin 

       PropertyRegDataType:=0; 
       RequiredSize:=0; 
       if SetupDiGetDeviceRegistryProperty(hdev, DeviceInfoData, SPDRP_FRIENDLYNAME, PropertyRegDataType, PBYTE(@PropertyBuffer[0]), SizeOf(PropertyBuffer), RequiredSize) then 
        Writeln(Format('Friendly Name - %s',[PropertyBuffer])); 

       if SetupDiGetDeviceRegistryProperty(hdev, DeviceInfoData, SPDRP_DEVICEDESC, PropertyRegDataType, PBYTE(@PropertyBuffer[0]), SizeOf(PropertyBuffer), RequiredSize) then 
        Writeln(Format('Description - %s',[PropertyBuffer])); 

       if SetupDiGetDeviceRegistryProperty(hdev, DeviceInfoData, SPDRP_LOCATION_INFORMATION, PropertyRegDataType, PBYTE(@PropertyBuffer[0]), SizeOf(PropertyBuffer), RequiredSize) then 
        Writeln(Format('Location  - %s',[PropertyBuffer])); 
       end 
       else 
       RaiseLastOSError; 
       finally 
       FreeMem(pdidd); 
       end; 
      end; 
     end 
     else 
     Break; 
     inc(idev); 
     until false; 
    finally 
     SetupDiDestroyDeviceInfoList(hdev); 
    end; 
    end; 
end; 

begin 
    try 
    if not LoadsetupAPI then exit; 
    EnumerateCOMPorts; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    readln; 
end. 

Это будет возвращать что-то вроде так

enter image description here

Примечания: JvSetupApi блока является частью библиотеки JVCL.

+0

Да, получил то же время от других ссылок. Однако не отображает все порты.Я играл с различными примерами WMI, но они либо показывают то же самое, что и это, либо требуют повышения (и даже тогда я не могу заставить их видеть все устройства COM ) –

+1

Кажется, у вашего кода есть ошибка, потому что он показывает только одно устройство. Вам понадобится раздел 'try..finally' за пределами цикла повтора, потому что после первого показанного устройства' SetupDiDestroyDeviceInfoList (hdev) 'уничтожит' hdev', а следующий вызов 'SetupDiEnumDeviceInterfaces (hdev, nil, GUID_DEVINTERFACE_COMPORT, idev, did)' будет return error (6 - Недопустимый дескриптор). – AntonBazhal

+0

@AntonBazhal, спасибо. Я только что отредактировал код, переместив блок try наконец. – RRUZ

0

Вы можете использовать HKEY_LOCAL_MACHINE \ HARDWARE \ DEVICEMAP \ SERIALCOMM для коротких имен стиля COMxx. Не забывайте указывать доступ только для чтения, чтобы избежать необходимости администрирования/UAC. Вы можете видеть как адаптеры usb232, так и реальные коммуникационные порты.

Вы также можете использовать HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Enum \ Root \ PORTS, но это кажется немного сложным.

Смежные вопросы