windowsdelphiwinapifiremonkeydelphi-12-athens

Getting list of devices plugged in in a pc (windows platform)


I am working on a project and I need to get the list of plugged in devices in the PC, just like the Windows Device Manager does.

enter image description here

But I don't know how to communicate with Windows to retrive the list of available devices in Delphi Firemonkey framework. I am using Delphi 12.


Solution

  • I made a unit for you to do this:

    unit DeviceLister;
    
    interface
    
    uses
      System.Classes
      ,System.SysUtils
      {$IFDEF MSWINDOWS}
        ,Winapi.Windows
      {$ENDIF};
    
    function GetPluggedInDevices: TStringList;
    
    implementation
    
    {$IFDEF MSWINDOWS}
      const
        DIGCF_PRESENT = $00000002;
        DIGCF_ALLCLASSES = $00000004;
        SPDRP_DEVICEDESC = $00000000;
    
      type
        HDEVINFO = Pointer;
        ULONG_PTR = NativeUInt;
    
        TSPDevInfoData = packed record
          cbSize: DWORD;
          ClassGuid: TGUID;
          DevInst: DWORD;
          Reserved: ULONG_PTR;
        end;
    
      function SetupDiGetClassDevsW(ClassGuid: PGUID; Enumerator: PWideChar; hwndParent: HWND;
        Flags: DWORD): HDEVINFO; stdcall; external 'setupapi.dll' name 'SetupDiGetClassDevsW';
    
      function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD;
        var DeviceInfoData: TSPDevInfoData): BOOL; stdcall; external 'setupapi.dll';
    
      function SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet: HDEVINFO;
        const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD;
        PropertyBuffer: PBYTE; PropertyBufferSize: DWORD; RequiredSize: PDWORD): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiGetDeviceRegistryPropertyW';
    
      function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): BOOL; stdcall; external 'setupapi.dll';
    {$ENDIF}
    
    function GetPluggedInDevices: TStringList;
    {$IFDEF MSWINDOWS}
      var
        DeviceName: array[0..1023] of Byte;
        RegType: DWORD;
    {$ENDIF}
    begin
      Result := TStringList.Create;
    
      {$IFDEF MSWINDOWS}
        var DeviceInfoSet: HDEVINFO := SetupDiGetClassDevsW(nil, nil, 0, DIGCF_ALLCLASSES or DIGCF_PRESENT);
        if NativeUInt(DeviceInfoSet) = NativeUInt(INVALID_HANDLE_VALUE) then
        begin
          Result.Add('Failed to get device list.');
          Exit;
        end;
    
        var i := 0;
        var DeviceInfoData: TSPDevInfoData;
        DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
    
        while SetupDiEnumDeviceInfo(DeviceInfoSet, i, DeviceInfoData) do
        begin
          if SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, SPDRP_DEVICEDESC,
            RegType, @DeviceName, SizeOf(DeviceName), nil) then
          begin
            Result.Add(Format('%d: %s', [i + 1, PWideChar(@DeviceName)]));
          end;
          Inc(i);
        end;
    
        SetupDiDestroyDeviceInfoList(DeviceInfoSet);
      {$ELSE}
        Result.Add('Device listing is only supported on Windows.');
      {$ENDIF}
    end;
    
    end.
    

    And then in your app, you can simply add DeviceLister to your uses list, and then call the GetPluggedInDevices function. Here's an example where I'm calling and using it on a button to display the devices onto a memo:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      var Devices := GetPluggedInDevices;
      Memo1.Lines.Assign(Devices);
      Devices.Free;
    end;
    

    And the result:

    Getting Plugged in Devices using Delphi Programming Language


    Is this kind of what you wanted?