Do you need to identify Storage Devices available or connected to the machine and perform some programmatically actions to the Storage Devices? How do enumerate among the Storage Devices quickly? Don’t know how to do it? Don’t worry. MiTec’s System Information Management Suite component helps to enumerate the available Internal or External Storage devices, and we will learn how to use the TMiTec_Storage, TMiTeC_Disk component in this blog post.
Platforms: Windows.
Installation Steps:
You can easily install this Component Suite from GetIt Package Manager. The steps are as follows.
- Navigate In RAD Studio IDE->Tools->GetIt Package Manager->select Components in Categories->Components->Trail -MiTec system Information Component Suite 14.3 and click Install Button.
- Read the license and Click Agree All. An Information dialog saying ‘Requires a restart of RAD studio at the end of the process. Do you want to proceed? click yes and continue.
- It will download the plugin and installs it. Once installed Click Restart now.
How to run the Demo app:
- Navigate to the System Information Management Suite trails setup, Demos folder which is installed during Get It installation e.g) C:UsersDocumentsEmbarcaderoStudio21.0CatalogRepositoryMiTeC-14.3DemosDelphi5
- Open the DiskView project in RAD studio 10.4.1 Compile and Run the application.
- This Demo App shows how to list down the internal and external storage devices, enumerate among them and access its properties.
Components used in MSIC DiskView Demo App:
- TMiTeC_Disk: Detects properties of given logical disk.
- TMiTeC_Storage: Enumerates logical drives and physical storage devices as disks, tapes, CD/DVD etc.
- TMiTeC_DeviceMonitor : Catches USB, Bluetooth devices or TV/monitor connection/disconnection, volumes mount/unmount, CD/DVD insert/eject and other events from other devices
- TTreeView to list the Storage Device nodes and TListView to show the Selected Storage Device properties.
- TButton’s to save and refresh.
Implementation Details:
- An instance is created Storage of TMiTeC_Storage, Disk of TMiTeC_Disk and DeviceMonitor of TMiTeC_DeviceMonitor were created. Call cmRefresh where list of Storage devices were added to the tree node by loop through Storage.PhysicalCount. Further the list of Logical partitions were added to the physical tree node by loop through storage.LogicalCount. For each logical partitions, some of the logical storage device properties were listed in the list view.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
procedure Twnd_dv_Main.cmRefresh(Sender: TObject); var rd,c,i,j,ii: Integer; n,r: TTreeNode; pi: PInteger; s,d: string; g: TGUID; begin d:=''; Tree.OnChange:=nil; with Storage do try Screen.Cursor:=crHourGlass; RefreshData; Tree.Items.BeginUpdate; try Tree.Items.Clear; c:=PhysicalCount; for i:=0 to PhysicalCount-1 do with Physical[i] do begin New(pi); pi^:=i; if Size>0 then r:=Tree.Items.AddChildObject(nil,Trim(Format('%s (%d MB)',[Model,Size shr 20])),pi) else r:=Tree.Items.AddChildObject(nil,Trim(Format('%s',[Model])),pi); g:=GUID_DEVCLASS_DISKDRIVE; case DeviceType of FILE_DEVICE_CD_ROM, FILE_DEVICE_DVD: g:=GUID_DEVCLASS_CDROM; FILE_DEVICE_TAPE: g:=GUID_DEVCLASS_TAPEDRIVE; FILE_DEVICE_DISK: if Removable then g:=GUID_DEVCLASS_FDC; end; SetupDiGetClassImageIndex(spid,g,ii); r.ImageIndex:=ii; r.SelectedIndex:=r.ImageIndex; for j:=0 to LogicalCount-1 do with Logical[j] do if PhysicalIndex=i then begin d:=d+Copy(Drive,1,1); New(pi); pi^:=j; Disk.Drive:=Drive+':'; if Disk.Capacity=0 then n:=Tree.Items.AddChildObject(r,Format('%s:',[Drive]),pi) else begin if not(DeviceType in [FILE_DEVICE_CD_ROM,FILE_DEVICE_DVD, FILE_DEVICE_TAPE,FILE_DEVICE_UNKNOWN]) and (Length(Layout)>0) and (LayoutIndex>-1) then n:=Tree.Items.AddChildObject(r,Format('%s: (%s %s - %d MB)',[ Drive, GetPartitionType(Layout[LayoutIndex].Number,Layout[LayoutIndex].Typ), FileSystem,//GetPartitionSystem(Layout[LayoutIndex].Typ), Layout[LayoutIndex].Length.QuadPart shr 20]),pi) else n:=Tree.Items.AddChildObject(r,Format('%s: (%s - %d MB)',[Drive,Disk.FileSystem,Disk.Capacity shr 20]),pi); end; g:=GUID_DEVCLASS_VOLUME; SetupDiGetClassImageIndex(spid,g,ii); n.ImageIndex:=ii; n.SelectedIndex:=n.ImageIndex; end; end; new(pi); pi^:=-1; r:=Tree.Items.AddChildObject(nil,'Network drives',pi); g:=GUID_DEVCLASS_DISKDRIVE; SetupDiGetClassImageIndex(spid,g,ii); r.ImageIndex:=ii; r.SelectedIndex:=r.ImageIndex; Disk.RefreshData; s:=Disk.AvailableDisks; with Disk do for i:=1 to Length(s) do begin Drive:=Format('%s:',[Copy(s,i,1)]); if MediaType=dtRemote then begin d:=d+Copy(Drive,1,1); new(pi); pi^:=i; n:=Tree.Items.AddChildObject(r,Format('%s (%s)',[Drive,UNCPath]),pi); g:=GUID_DEVCLASS_VOLUME; SetupDiGetClassImageIndex(spid,g,ii); n.ImageIndex:=ii; n.SelectedIndex:=n.ImageIndex; end; end; if r.Count=0 then Tree.Items.Delete(r); new(pi); pi^:=-2; r:=Tree.Items.AddChildObject(nil,'Removable drives',pi); g:=GUID_DEVCLASS_DISKDRIVE; SetupDiGetClassImageIndex(spid,g,ii); r.ImageIndex:=ii; r.SelectedIndex:=r.ImageIndex; with Disk do for i:=1 to Length(s) do begin Drive:=Format('%s:',[Copy(s,i,1)]); if (Pos(Copy(s,i,1),d)=0) and (MediaType=dtRemovable) then begin d:=d+Copy(Drive,1,1); new(pi); pi^:=i; n:=Tree.Items.AddChildObject(r,Format('%s',[Drive]),pi); g:=GUID_DEVCLASS_VOLUME; SetupDiGetClassImageIndex(spid,g,ii); n.ImageIndex:=ii; n.SelectedIndex:=n.ImageIndex; Inc(rd); end; end; if r.Count=0 then Tree.Items.Delete(r); new(pi); pi^:=-2; r:=Tree.Items.AddChildObject(nil,'Other drives',pi); g:=GUID_DEVCLASS_DISKDRIVE; SetupDiGetClassImageIndex(spid,g,ii); r.ImageIndex:=ii; r.SelectedIndex:=r.ImageIndex; with Disk do for i:=1 to Length(s) do begin if Pos(Copy(s,i,1),d)=0 then begin Drive:=Format('%s:',[Copy(s,i,1)]); new(pi); pi^:=i; n:=Tree.Items.AddChildObject(r,Format('%s',[Drive]),pi); g:=GUID_DEVCLASS_VOLUME; SetupDiGetClassImageIndex(spid,g,ii); n.ImageIndex:=ii; n.SelectedIndex:=n.ImageIndex; end; end; if r.Count=0 then Tree.Items.Delete(r); Tree.FullExpand; finally Tree.Items.EndUpdate; end; finally Screen.Cursor:=crDefault; Caption:=Format('Storage Devices (%d physical, %d logical)',[PhysicalCount+rd, Length(s)]); end; Tree.Items[0].MakeVisible; Tree.OnChange:=TreeChange; end; |
- Display the selected Disk View properties on TreeChange event as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
procedure Twnd_dv_Main.TreeChange(Sender: TObject; Node: TTreeNode); var s: string; begin List.Items.BeginUpdate; List.Columns.BeginUpdate; try List.Items.Clear; if Assigned(Node) and Assigned(Node.Data) then begin if PInteger(Node.Data)^<0 then Exit; if Node.Level=0 then with Storage.Physical[PInteger(Node.Data)^] do begin with List.Items.Add do begin Caption:='Serial number'; SubItems.Add(SerialNumber); end; with List.Items.Add do begin Caption:='Revision'; SubItems.Add(Revision); end; with List.Items.Add do begin Caption:='Model'; SubItems.Add(Model); end; with List.Items.Add do begin Caption:='Bus Type'; SubItems.Add(GetStorageBusTypeStr(BusType)); end; s:=''; case DeviceType of FILE_DEVICE_CD_ROM: s:='CD-ROM'; FILE_DEVICE_DVD: s:='DVD'; FILE_DEVICE_MASS_STORAGE: s:='Mass Storage'; FILE_DEVICE_TAPE: s:='Tape'; FILE_DEVICE_DISK: begin s:='Drive'; if SSD then s:='Solid State Drive'; end; end; if s<>'' then with List.Items.Add do begin Caption:='Device Type'; SubItems.Add(s); end; with List.Items.Add do begin Caption:='Media Type'; SubItems.Add(GetDeviceMediaTypeStr(MediaType)); end; if (DeviceType=FILE_DEVICE_CD_ROM) or (DeviceType=FILE_DEVICE_DVD) then begin s:=''; if Read_CDRW then s:=s+'CD-R,'; if Read_CDR then s:=s+'CD-RW,'; if Read_DVDROM then s:=s+'DVD-ROM,'; if Read_DVDR then s:=s+'DVD-R,'; if Read_DVDRAM then s:=s+'DVD-RAM,'; SetLength(s,Length(s)-1); with List.Items.Add do begin Caption:='Read Caps'; SubItems.Add(s); end; s:=''; if Write_CDRW then s:=s+'CD-R,'; if Write_CDR then s:=s+'CD-RW,'; if Write_DVDR then s:=s+'DVD-R,'; if Write_DVDRAM then s:=s+'DVD-RAM,'; SetLength(s,Length(s)-1); with List.Items.Add do begin Caption:='Write Caps'; SubItems.Add(s); end; end; if HaId>=0 then with List.Items.Add do begin Caption:='SCSI adapter'; SubItems.Add(IntToStr(HaId)); end; if PathId>=0 then with List.Items.Add do begin Caption:='Bus'; SubItems.Add(IntToStr(PathId)); end; if Target>=0 then with List.Items.Add do begin Caption:='Target device'; SubItems.Add(IntToStr(Target)); end; if Lun>=0 then with List.Items.Add do begin Caption:='Logical unit number'; SubItems.Add(IntToStr(Lun)); end; //end; if Temperature>0 then with List.Items.Add do begin Caption:='Temperature'; SubItems.Add(Format('%d°C',[Temperature])); end; if PowerOnHours>0 then with List.Items.Add do begin Caption:='Power-on Hours'; SubItems.Add(Format('%d',[PowerOnHours])); end; if Size>0 then begin with List.Items.Add do begin Caption:='Capacity'; SubItems.Add(Format('%d MB',[Size shr 20])); end; with List.Items.Add do begin Caption:='Cyls'; SubItems.Add(Format('%d',[Geometry.Cylinders.QuadPart])); end; with List.Items.Add do begin Caption:='Heads'; SubItems.Add(Format('%d',[Geometry.TracksPerCylinder])); end; with List.Items.Add do begin Caption:='Sectors per track'; SubItems.Add(Format('%d',[Geometry.SectorsPerTrack])); end; with List.Items.Add do begin Caption:='Bytes per sector'; SubItems.Add(Format('%d',[Geometry.BytesPerSector])); end; if (IdentifyDeviceData.Max48BitLBA[0]=0) then with List.Items.Add do begin Caption:='Physical sectors'; if (Geometry.BytesPerSector>0) then SubItems.Add(Format('%d',[LengthInBytes div Geometry.BytesPerSector])) else SubItems.Add(Format('%d',[Geometry.Cylinders.QuadPart*Geometry.TracksPerCylinder*Geometry.SectorsPerTrack])); end else begin with List.Items.Add do begin Caption:='Number of sectors'; SubItems.Add(Format('%d',[IdentifyDeviceData.CurrentSectorCapacity])); end; with List.Items.Add do begin Caption:='Total 32-bit LBA sectors'; SubItems.Add(Format('%d',[IdentifyDeviceData.UserAddressableSectors])); end; with List.Items.Add do begin Caption:='Total 48-bit LBA sectors'; SubItems.Add(Format('%d',[IdentifyDeviceData.Max48BitLBA[0]])); end; end; end; if IdentifyDeviceData.MajorRevision>0 then with List.Items.Add do begin Caption:='ATA Major version'; SubItems.Add(GetATAMajorVersion(IdentifyDeviceData.MajorRevision)); end; if IdentifyDeviceData.MinorRevision>0 then with List.Items.Add do begin Caption:='ATA Minor version'; SubItems.Add(GetATAMinorVersion(IdentifyDeviceData.MinorRevision)); end; if IdentifyDeviceData.ReservedWord220[2]>0 then with List.Items.Add do begin Caption:='ATA Transport version'; SubItems.Add(GetATATransportVersion(IdentifyDeviceData.ReservedWord220[2])); end; if ECCCode<>0 then with List.Items.Add do begin Caption:='ECC'; SubItems.Add(Format('%d',[ECCCode])); end; if CtlBufSize<>0 then with List.Items.Add do begin Caption:='Cache Buffer size'; SubItems.Add(Format('%d KB',[CtlBufSize shr 10])); end; with List.Items.Add do begin Caption:='S.M.A.R.T.'; if SMARTSupport then begin if SMARTActive then SubItems.Add('Supported and active') else SubItems.Add('Supported and NOT active'); end else SubItems.Add('NOT supported'); end; end else begin if PInteger(Node.Parent.Data)^<0 then Disk.Drive:=Copy(Disk.AvailableDisks,PInteger(Node.Data)^,1)+':' else Disk.Drive:=Storage.Logical[PInteger(Node.Data)^].Drive+':'; with List.Items.Add do begin Caption:='Volume label'; SubItems.Add(Disk.VolumeLabel); end; with List.Items.Add do begin Caption:='Serial number'; SubItems.Add(Disk.SerialNumber); end; with List.Items.Add do begin Caption:='Capacity'; SubItems.Add(Format('%d MB',[Disk.Capacity shr 20])); end; with List.Items.Add do begin Caption:='Free'; SubItems.Add(Format('%d MB',[Disk.FreeSpace shr 20])); end; with List.Items.Add do begin Caption:='File system'; SubItems.Add(Disk.FileSystem); end; with Storage.Logical[PInteger(Node.Data)^] do if LayoutIndex>-1 then begin with List.Items.Add do begin Caption:='First sector'; SubItems.Add(IntToStr(Layout[LayoutIndex].StartingOffset.QuadPart div Geometry.BytesPerSector)); end; with List.Items.Add do begin Caption:='Last sector'; SubItems.Add(IntToStr((Layout[LayoutIndex].StartingOffset.QuadPart+Layout[LayoutIndex].Length.QuadPart-1) div Geometry.BytesPerSector)); end; with List.Items.Add do begin Caption:='Cluster size'; SubItems.Add(Format('%d B',[ClusterSize])); end; with List.Items.Add do begin Caption:='Total sectors'; SubItems.Add(IntToStr(Layout[LayoutIndex].Length.QuadPart div Geometry.BytesPerSector)); end; end; end; end; finally List.Items.EndUpdate; List.Columns.EndUpdate; end; end; |
- Use DeviceMonitor events OnVolumeConnect,OnVolumeDisconnect to identify the Storage device arrival/removal and refresh the tree view accordingly.
It’s that simple to enumerate Storage Devices connected and list their properties for your application. Use this MiTeC component suite and get the job done quickly.
Learn how you can take advantage of a powerful and flexible hard disk space manager called TreeSize in this article.
With the use of a Windows IDE, you can easily access storage device information in your Delphi Windows apps with a component suite. Try your Free Trial here.
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition