Pobieranie informacji o napędach systemu

Adam Boduch

Aby zidentyfikować napędy zainstalowane w systemie, konieczne jest użycie funkcji WinAPI. W gruncie rzeczy jest to proste, należy jednak poznać kilka fundamentalnych zasad i poznać sposób użycia funkcji WinAPI.

Podstawową funkcją jest GetDriveType. Funkcja ta zawiera jeden parametr, a mianowicie literę dysku dla którego chcesz uzyskać informacje.

Funkcja ta zwraca takie oto wartości:

0 - Typ napędu niemożliwy do określenia.
1 - Nie istnieje napęd o podanej literze.
DRIVE_REMOVABLE - Dyskietka lub napęd wymienny
DRIVE_FIXED - Napęd niewymienny
DRIVE_REMOTE - Napęd sieciowy
DRIVE_CDROM - CD - ROM
DRIVE_RMADISK - Ram-dysk - wirtualny dysk.

W tym artykule napiszemy program, który będzie właśnie podawał informacje dotyczące dysku. Na formularzu umieść komponent ListView - w nim będą zaznaczone dyski. Umieść na formie także komponent ImageList. Dodaj do niego z dwie ikony symbolizujące odpowiednio: ikonę CD oraz ikonę dysku twardego.

Dobrze przejdźmy do rzeczy najważniejszej, czyli uzyskanie informacji o dyskach. Oto procedura OnCreate naszego programu:

procedure TMainForm.FormCreate(Sender: TObject);
var
  i : Integer; // zmienna potrzebna do wykonania petli
  DriveType : Integer;  // informacja o typie dysku
  ListItem: TListItem;
  Bufor:array[0..MAX_PATH] of Char; // zawiera etykiete dysku
  MaxCompLength, FileSystemFlags : DWORD;
begin
{  wykonaj petle analizujac kazda litere dysku }
  for I := Ord('A') to Ord('Z') do
  begin
    DriveType := GetDriveType(PChar(Chr(i) + ':\')); // pobierz typ dysku


  { jezeli typ  dysku to 0 ( nie mozna okreslic ) lub 1 ( nie istnieje taki dysk ) to pomin w opisie. }

    if not (DriveType = 0) and not (DriveType = 1) then
    begin
  {  uzyskaj informacje dotyczace etykiety dysku }
      GetVolumeInformation(PChar(Chr(i) + ':\'), Bufor, SizeOf(Bufor),
      nil, MaxCompLength, FileSystemFlags, nil, 0);

      ListItem := ListView.Items.Add; // dodaj pozycje
      ListItem.Caption := Chr(i) + ':\' + ' '  + Bufor; // ustaw tekst

   { Tutaj w zaleznosci od rodzaju dysku do komponentu ListView do okreslnej
      pozycji zostaje przypisana okreslona ikonka symoblizujaca dysk.  }

      if (DriveType = DRIVE_CDROM) then ListItem.ImageIndex := 0;
      if (DriveType = DRIVE_FIXED) then ListItem.ImageIndex := 1;
      if (DriveType = DRIVE_REMOVABLE) then ListItem.ImageIndex := -1;
    end;                                               
  end;
end;

Wiadomo, że dyski mogą być ponumerowane od A do Z. Na początek do zmiennej DriveType zostaje przypisany rezultat wykonania funkcji GetDriveType. Później następuje sprawdzenie, czy zmienna DriveType nie ma przypadkiem wartości 0 lub 1 co oznaczałoby, że niemożliwe jest określenie dysku - wtedy operacje zostaną pominięte. Jeżeli dysk jest następuje pobranie jego etykiety, a później tworzona jest nowa pozycja w komponencie TListView. To nie wszystko. Trzeba jeszcze wybrać ikonę. Właściwość ImageIndex określa numer ikony. Po prostu dobierana jest odpowiednia ikona w zależności od rodzaju dysku. Bardzo ważna rzecz: trzeba we właściwości LargeImages komponentu ListView wybrać komponent ImageList1.

Dobrze, wiesz już jak uzyskać listę dysków znajdujących się w systemie. Teraz coś trudniejszego mianowicie uzyskanie dokładniejszych informacji o samych dyskach, czyli liczba klasterów, sektory przypadający na klaster itp. To wszystko umożliwia nam funkcja GetDiskFreeSpace. Trzeba w niej podać wszystkie zmienne, które przechowywać będą informacje o właściwościach dysku.

Zadeklarujmy te zmienne:

var
  DirName: String; // litera dysku
  Sectors: DWORD; // sektory w klasterze  
  Bytes: DWORD; // bajty w sektorze
  FreeClust: DWORD; // wolne klastery
  TotalClust: DWORD; // wszystkie klastery

Dobrze. Teraz trzeba jakoś zdobyć literę zaznaczonej pozycji w komponencie. Zrób to w ten sposób:

DirName := ListView.Selected.Caption[1]; // pobierz pierwszy znak napisu - litere dysku

Po prostu uzyskujemy pierwszy znak zaznaczonej pozycji... Na formularzu umieść 4 etykiety tekstowe, które wyświetlały będą te informacje. Teraz samo wywłanie funkcji GetDiskFreeSpace:

 {  Funkcja GetDiskFreeSpace podaje rozne informacje dotyczace  danego dysku }
  if GetDiskFreeSpace(PChar(DirName + ':\'), Sectors, Bytes, FreeClust, TotalClust) then
  begin
  {  przypisz dane do etykiet tekstowych }
    lblSectors.Caption := 'Sektory w klastrze: ' + IntToStr(Sectors);
    lblBytes.Caption := 'Bajty w sektorze: ' + IntToStr(Bytes);
    lblFreeClust.Caption := 'Wolne klastry: ' + IntToStr(FreeClust);
    lblTotalClust.Caption := 'Wszystkie klastry: ' + IntToStr(TotalClust);
  { jezeli niemozliwe jest odczytanie wlasciwosci przypisz etykieta symbolom znak ???? }
  end else
  begin
    lblSectors.Caption := '???';
    lblBytes.Caption := '???';
    lblFreeClust.Caption := '???';
    lblTotalClust.Caption := '???';
  end;

Jeżeli nie jest możliwe określenie danych z dysku to na etykietach przypisany zostaje znak ???.

Oto cały kod programu:

//////////////////////////////////////////////////////////////////
//                                                              //
//               Unit MainFrm for DrivesInfo                    //
//             Copyright ? 2001 by Adam Boduch                  //
//      Service for programmers: http://programowanie.of.pl     //
//                E-mail:  boduch@poland.com                    //
//         29.06.2001 r.                                        //
//                                                              //
//////////////////////////////////////////////////////////////////

unit MainFrm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, ImgList, StdCtrls;

type
  TMainForm = class(TForm)
    ListView: TListView;
    ImageList1: TImageList;
    lblSectors: TLabel;
    lblBytes: TLabel;
    lblFreeClust: TLabel;
    lblTotalClust: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure ListViewClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

procedure TMainForm.FormCreate(Sender: TObject);
var
  i : Integer; // zmienna potrzebna do wykonania petli
  DriveType : Integer;  // informacja o typie dysku
  ListItem: TListItem;
  Bufor:array[0..MAX_PATH] of Char; // zawiera etykiete dysku
  MaxCompLength, FileSystemFlags : DWORD;
begin
{  wykonaj petle analizujac kazda litere dysku }
  for I := Ord('A') to Ord('Z') do
  begin
    DriveType := GetDriveType(PChar(Chr(i) + ':\')); // pobierz typ dysku

  { jezeli typ  dysku to 0 ( nie mozna okreslic ) lub 1 ( nie istnieje taki dysk ) to pomin w opisie.  }

    if not (DriveType = 0) and not (DriveType = 1) then
    begin
    {  uzyskaj informacje dotyczace etykiety dysku }
      GetVolumeInformation(PChar(Chr(i) + ':\'), Bufor, SizeOf(Bufor),
      nil, MaxCompLength, FileSystemFlags, nil, 0);
      
      ListItem := ListView.Items.Add; // dodaj pozycje
      ListItem.Caption := Chr(i) + ':\' + ' '  + Bufor; // ustaw tekst
   {
      Tutaj w zaleznosci od rodzaju dysku do komponentu ListView do okreslnej
      pozycji zostaje przypisana okreslona ikonka symoblizujaca dysk.
   }
      if (DriveType = DRIVE_CDROM) then ListItem.ImageIndex := 0;
      if (DriveType = DRIVE_FIXED) then ListItem.ImageIndex := 1;
      if (DriveType = DRIVE_REMOVABLE) then ListItem.ImageIndex := -1;
    end;                                               
  end;
end;

procedure TMainForm.ListViewClick(Sender: TObject);
var
  DirName: String; // litera dysku
  Sectors: DWORD; // sektory w klastru
  Bytes: DWORD; // bajty w sektorze
  FreeClust: DWORD; // wolne klastery
  TotalClust: DWORD; // wszystkie klastery
begin
  DirName := ListView.Selected.Caption[1]; // pobierz pierwszy znak napisu - litere dysku

  {  Funkcja GetDiskFreeSpace podaje rozne informacje dotyczace  danego dysku }
  if GetDiskFreeSpace(PChar(DirName + ':\'), Sectors, Bytes, FreeClust, TotalClust) then
  begin
  {  przypisz dane do etykiet tekstowych }
    lblSectors.Caption := 'Sektory w klastrze: ' + IntToStr(Sectors);
    lblBytes.Caption := 'Bajty w sektorze: ' + IntToStr(Bytes);
    lblFreeClust.Caption := 'Wolne klastry: ' + IntToStr(FreeClust);
    lblTotalClust.Caption := 'Wszystkie klastry: ' + IntToStr(TotalClust);
  { jezeli niemozliwe jest odczytanie wlasciwosci przypisz etykieta symbolom znak ???? }
  end else
  begin
    lblSectors.Caption := '???';
    lblBytes.Caption := '???';
    lblFreeClust.Caption := '???';
    lblTotalClust.Caption := '???';
  end;
end;

end.

Przydatną może także być funkcja DiskSize, która podaje pojemność dysku oraz DiskFree, która podaje ilość wolnego miejsca na dysku. Funkcje te zwracają rezultat w postaci zmiennej typu Int64. Jako parametr tych funkcji trzeba podać numer dysku. Dysk opatrzony literą A ma numer 1; dysk B - numer 2 itd. Czyli np:

WolneMiejsce.Caption := IntToStr(DiskFree(3)); // wolne miejsce na dysku C: 

5 komentarzy

hahaha, nagrywarka CD Read_Only Memory ;]

Ale po czym można odróżnić napęd CD-ROM od nagrywarki CD-ROM

poczym poznać nagrywarke CD-ROM

Bardzo dobry artykuł. Ale czy można odróżnić napęd CD-ROM od nagrywarki CD-ROM lub DVD

tego potrzebowałem, dzięki!