AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

SSD erkennen?

Ein Thema von Mattze · begonnen am 6. Jan 2012 · letzter Beitrag vom 28. Dez 2016
Antwort Antwort
Seite 1 von 2  1 2      
Mattze

Registriert seit: 6. Jan 2005
664 Beiträge
 
#1

SSD erkennen?

  Alt 6. Jan 2012, 09:12
Hallo,

sicher schon mal gefragt, aber ich finde nix.

Wie erkennt man im Programm eigentlich sicher, dass man es mit einer SSD zu tun hat?

(D7pro, Win7 64)

Danke!
Mattze
  Mit Zitat antworten Zitat
bernerbaer
(Gast)

n/a Beiträge
 
#2

AW: SSD erkennen?

  Alt 6. Jan 2012, 13:18
_Ich_ denke, dass es dazu keine allgemein gültige Lösung gibt, da SSDs sich als Festplatten ausgeben. Vermutlich musst du über Umwege rausfinden zu versuchen, ob es sich um eine SSD-HD handelt. Anbieten würde sich da z.B.
  • Ermitteln der Zugriffszeit
  • ermitteln der Geschwindigkeit
oder du führst intern eine Liste mit allen Gerätekennungen von SSD-Festplatten und liest SMART aus und vergleichst mit deiner Liste.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.293 Beiträge
 
Delphi 12 Athens
 
#3

AW: SSD erkennen?

  Alt 6. Jan 2012, 13:29
Jupp, es gibt zwar einige standardisierte IDE-Befehle für SSDs, wie z.B. TRIM, aber nicht in allen SSDs sind diese implementiert.

PS: Es gibt auch Möglichkeiten um Speicherkarten via IDE anzuschließen. (quasi der Vorfahre von SSD)
z.B. die Compact-Flash-Karten oder SD-Karten
Die sind ja auch nicht sooo langsam, so daß es da mit dem Erkennen, über die Zugriffszeiten nicht so einfach aussieht.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
DanielProgramming
(Gast)

n/a Beiträge
 
#4

AW: SSD erkennen?

  Alt 6. Jan 2012, 13:47
Hallo,

Kollege von mir meinte vor kurzem SSDs geben bei der Rotationsgeschwindigkeit 0 an wenn man diese abfragt, vielleicht wäre das ja ein Ansatzpunkt für Dich. Bin da nicht weiter drauf eingegangen, empfand es aber als logisch, da drin rotiert ja nix
  Mit Zitat antworten Zitat
bernerbaer
(Gast)

n/a Beiträge
 
#5

AW: SSD erkennen?

  Alt 6. Jan 2012, 14:06
Hallo,

Kollege von mir meinte vor kurzem SSDs geben bei der Rotationsgeschwindigkeit 0 an wenn man diese abfragt, vielleicht wäre das ja ein Ansatzpunkt für Dich. Bin da nicht weiter drauf eingegangen, empfand es aber als logisch, da drin rotiert ja nix
ja, das stimmt vermutlich, ist aber vermutlich kein ausschliessliches Erkennungsmerkmal, auch andere Medien haben Rotationsgeschwindigkeit 0. (Hast du z.b. schon mal die Rotationsgeschwindigkeit eines Raid 0 Systems mit normalen Festplatten ermittelt?)
  Mit Zitat antworten Zitat
devidespe

Registriert seit: 7. Sep 2006
Ort: Berlin
434 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: SSD erkennen?

  Alt 6. Jan 2012, 15:24
Ja, die Rotationsgeschwindigkeit ist das Stichwort. Windows 7 deaktiviert die automatische Datenträgerdefragmentierung für ein Laufwerk, sobald die Rotationsgeschwindigkeit 0 beträgt. Das hat auch den Huintergrund, dass eine Defragmentierung bei SSD's und USB-Sticks eher kontraproduktiv ist.
Devid
57 65 72 20 6C 65 73 65 6E 20 6B 61 6E 6E 2C 20 69 73 74 20 6B 6C 61 72 20 69 6D 20 56 6F 72 74 65 69 6C 21
  Mit Zitat antworten Zitat
DanielProgramming
(Gast)

n/a Beiträge
 
#7

AW: SSD erkennen?

  Alt 6. Jan 2012, 15:39
(Hast du z.b. schon mal die Rotationsgeschwindigkeit eines Raid 0 Systems mit normalen Festplatten ermittelt?)
Nein und da du so fragst nehme ich an man bekommt keinen Mittelwert von den beteiligten Platten sondern auch 0
  Mit Zitat antworten Zitat
Mattze

Registriert seit: 6. Jan 2005
664 Beiträge
 
#8

AW: SSD erkennen?

  Alt 28. Mär 2012, 17:32
Hallo,

ich komme leider erst jetzt wieder dazu, mich damit weiter zu beschäftigen und...
ich finde es nicht!
Ich kriege die Rotationsgeschwindigkeit einfach nicht raus.
Irgendwann, als ich mich mit DeviceIoControl näher beschäftigt habe, habe ich mal etwas davon gelesen - bin ich mir sicher.
Nun finde ich es nicht mehr. In der Struktur für IOCTL_ATA_PASS_THROUGH finde ich auch nix.
Für einen kleiner Tipp wäre ich dankbar.

Gruß
Mattze
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
552 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: SSD erkennen?

  Alt 23. Apr 2016, 15:19
Ja, jetzt sind ja schlappe 4 Jährchen vergangen, ob Mattze immer noch über der Antwort brütet?
Jedenfalls brauchte ich auch eine funktionierende SSD-Erkennung und habe mich mal ungeniert hier bedient.
Das funktioniert auch, hat aber einen großen Pferdefuß: Man braucht Administratorrechte für das CreateFile.
Kennt jemand eine Lösung, wo es auch ohne geht? Oder ist das prinzipiell unmöglich?
Delphi-Quellcode:
uses Winapi.Windows,System.SysUtils,System.Types,System.UITypes,Vcl.Dialogs;

type
  { ATA_PASS_THROUGH_EX }
  _ATA_PASS_THROUGH_EX = packed record
    Length: Word;
    AtaFlags: Word;
    PathId: UCHAR;
    TargetId: UCHAR;
    Lun: UCHAR;
    ReservedAsUchar: UCHAR;
    DataTransferLength: ULONG;
    TimeOutValue: ULONG;
    ReservedAsUlong: ULONG;
    DataBufferOffset: ULONG_PTR;
    PreviousTaskFile: array [0..7] of UCHAR;
    CurrentTaskFile: array [0..7] of UCHAR;
  end;
  {$EXTERNALSYM _ATA_PASS_THROUGH_EX}
  ATA_PASS_THROUGH_EX = _ATA_PASS_THROUGH_EX;
  {$EXTERNALSYM  ATA_PASS_THROUGH_EX}
  TAtaPassThroughEx = _ATA_PASS_THROUGH_EX;
  PAtaPassThroughEx = ^TAtaPassThroughEx;

  { ATAIdentifyDeviceQuery }
  TATAIdentifyDeviceQuery = packed record
    header: ATA_PASS_THROUGH_EX;
    data: array [0..255] of Word;
  end;

const
{$IF RTLVersion < 22.0}
  FILE_DEVICE_CONTROLLER = $00000004;
  {$EXTERNALSYM FILE_DEVICE_CONTROLLER}

  FILE_READ_ACCESS = $0001;
  {$EXTERNALSYM FILE_READ_ACCESS}

  FILE_WRITE_ACCESS = $0002;
  {$EXTERNALSYM FILE_WRITE_ACCESS}
{$IFEND}

  ATA_FLAGS_DRDY_REQUIRED = $01;
  ATA_FLAGS_DATA_IN = $02;
  ATA_FLAGS_DATA_OUT = $04;
  ATA_FLAGS_48BIT_COMMAND = $08;
  ATA_FLAGS_USE_DMA = $10;
  ATA_FLAGS_NO_MULTIPLE = $20;

  IOCTL_SCSI_BASE = FILE_DEVICE_CONTROLLER;
  IOCTL_ATA_PASS_THROUGH = (IOCTL_SCSI_BASE shl 16) or
                            ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or
                            ($040B shl 2) or
                            (METHOD_BUFFERED);
{$IF RTLversion < 22.0}
const
  FILE_READ_DATA = $0001;
  {$EXTERNALSYM FILE_READ_DATA}

  FILE_READ_ATTRIBUTES = $0080;
  {$EXTERNALSYM FILE_READ_ATTRIBUTES}

  FILE_DEVICE_MASS_STORAGE = $0000002d;
  {$EXTERNALSYM FILE_DEVICE_MASS_STORAGE}

  IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE;
  {$EXTERNALSYM IOCTL_STORAGE_BASE}

  FILE_ANY_ACCESS = 0;
  {$EXTERNALSYM FILE_ANY_ACCESS}

  METHOD_BUFFERED = 0;
  {$EXTERNALSYM METHOD_BUFFERED}

  IOCTL_STORAGE_QUERY_PROPERTY = (IOCTL_STORAGE_BASE shl 16) or
                                 (FILE_ANY_ACCESS shl 14) or
                                 ($0500 shl 2) or
                                 (METHOD_BUFFERED);
  {$EXTERNALSYM IOCTL_STORAGE_QUERY_PROPERTY}
{$IFEND}

type
  { STORAGE_PROPERTY_ID }
  _STORAGE_PROPERTY_ID = (
    StorageDeviceProperty = 0,
    StorageAdapterProperty = 1,
    StorageDeviceIdProperty = 2,
    StorageDeviceUniqueIdProperty = 3,
    StorageDeviceWriteCacheProperty = 4,
    StorageMiniportProperty = 5,
    StorageAccessAlignmentProperty = 6,
    StorageDeviceSeekPenaltyProperty = 7,
    StorageDeviceTrimProperty = 8,
    StorageDeviceWriteAggregationProperty = 9,
    StorageDeviceDeviceTelemetryProperty = 10
  );
  {$EXTERNALSYM _STORAGE_PROPERTY_ID}
  STORAGE_PROPERTY_ID = _STORAGE_PROPERTY_ID;
  {$EXTERNALSYM  STORAGE_PROPERTY_ID}
  TStoragePropertyId = _STORAGE_PROPERTY_ID;
  PStoragePropertyId = ^TStoragePropertyId;

  { STORAGE_QUERY_TYPE }
  _STORAGE_QUERY_TYPE = (
    PropertyStandardQuery = 0,
    PropertyExistsQuery = 1,
    PropertyMaskQuery = 2,
    PropertyQueryMaxDefined = 3
  );
  {$EXTERNALSYM _STORAGE_QUERY_TYPE}
  STORAGE_QUERY_TYPE = _STORAGE_QUERY_TYPE;
  {$EXTERNALSYM  STORAGE_QUERY_TYPE}
  TStorageQueryType = _STORAGE_QUERY_TYPE;
  PStorageQueryType = ^TStorageQueryType;

  { STORAGE_PROPERTY_QUERY }
  _STORAGE_PROPERTY_QUERY = packed record
    PropertyId: DWORD;
    QueryType: DWORD;
    AdditionalParameters: array[0..9] of Byte;
  end;
  {$EXTERNALSYM _STORAGE_PROPERTY_QUERY}
  STORAGE_PROPERTY_QUERY = _STORAGE_PROPERTY_QUERY;
  {$EXTERNALSYM  STORAGE_PROPERTY_QUERY}
  TStoragePropertyQuery = _STORAGE_PROPERTY_QUERY;
  PStoragePropertyQuery = ^TStoragePropertyQuery;

  { DEVICE_SEEK_PENALTY_DESCRIPTOR }
  _DEVICE_SEEK_PENALTY_DESCRIPTOR = packed record
    Version: DWORD;
    Size: DWORD;
    IncursSeekPenalty: ByteBool;
    Reserved: array[0..2] of Byte;
  end;
  {$EXTERNALSYM _DEVICE_SEEK_PENALTY_DESCRIPTOR}
  DEVICE_SEEK_PENALTY_DESCRIPTOR = _DEVICE_SEEK_PENALTY_DESCRIPTOR;
  {$EXTERNALSYM  DEVICE_SEEK_PENALTY_DESCRIPTOR}
  TDeviceSeekPenaltyDescriptor = _DEVICE_SEEK_PENALTY_DESCRIPTOR;
  PDeviceSeekPenaltyDescriptor = ^TDeviceSeekPenaltyDescriptor;
    type
      { DISK_EXTENT }
      _DISK_EXTENT = packed record
        DiskNumber: DWORD;
        StartingOffset: LARGE_INTEGER;
        ExtentLength: LARGE_INTEGER;
        Reserved: array [0..3] of Byte;
      end;
      {$EXTERNALSYM _DISK_EXTENT}
      DISK_EXTENT = _DISK_EXTENT;
      {$EXTERNALSYM  DISK_EXTENT}
      TDiskExtent = _DISK_EXTENT;
      PDiskExtent = ^TDiskExtent;

      { VOLUME_DISK_EXTENTS }
      _VOLUME_DISK_EXTENTS = packed record
        NumberOfDiskExtents: DWORD;
        Reserved: array [0..3] of Byte;
        Extents: array [0..0] of DISK_EXTENT;
      end;
      {$EXTERNALSYM _VOLUME_DISK_EXTENTS}
      VOLUME_DISK_EXTENTS = _VOLUME_DISK_EXTENTS;
      {$EXTERNALSYM  VOLUME_DISK_EXTENTS}
      TVolumeDiskExtents = VOLUME_DISK_EXTENTS;
      PVolumeDiskExtents = ^TVolumeDiskExtents;

    {$IF RTLVersion < 22.0}
    const
      IOCTL_VOLUME_BASE = $00000056;
      {$EXTERNALSYM IOCTL_VOLUME_BASE}

      IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = (IOCTL_VOLUME_BASE shl 16) or
                                             (FILE_ANY_ACCESS shl 14) or
                                             (0 shl 2) or
                                             (METHOD_BUFFERED);
  {$EXTERNALSYM IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS}
{$IFEND}

function HasNominalMediaRotationRate(const PhysicalDrivePath: String): Boolean;
function HasNoSeekPenalty(const PhysicalDrivePath: String): Boolean;
procedure PathnameToPhysicalDriveNumber(const Path: String; var PhysicalDrives: TIntegerDynArray);
function IstSSD(LW:Char):Boolean;

implementation

function HasNominalMediaRotationRate(const PhysicalDrivePath: String): Boolean;
var
  h: THandle;
  ATAIdentifyDeviceQuery: TATAIdentifyDeviceQuery;
  RSize: DWORD;
begin

  h := CreateFile(PChar(PhysicalDrivePath),GENERIC_READ or GENERIC_WRITE,
                  FILE_SHARE_READ or FILE_SHARE_WRITE,nil,
                  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  if h = INVALID_HANDLE_VALUE then
  begin
    RaiseLastOSError;
  end;

  try
    FillChar(ATAIdentifyDeviceQuery,SizeOf(ATAIdentifyDeviceQuery),0);
    with ATAIdentifyDeviceQuery do
    begin
      header.Length := SizeOf(header);
      header.AtaFlags := ATA_FLAGS_DATA_IN;
      header.DataTransferLength := SizeOf(data);
      header.TimeOutValue := 3; // sec
      header.DataBufferOffset := SizeOf(header);
      header.CurrentTaskFile[6] := $EC; // ATA IDENTIFY DEVICE command
    end;

    RSize := 0;
    if DeviceIoControl(h,IOCTL_ATA_PASS_THROUGH,
                       @ATAIdentifyDeviceQuery,SizeOf(ATAIdentifyDeviceQuery),
                       @ATAIdentifyDeviceQuery,SizeOf(ATAIdentifyDeviceQuery),
                       RSize,nil) = False then
    begin
      RaiseLastOSError;
    end;

    Result := (ATAIdentifyDeviceQuery.data[217] = 1);

  finally
    CloseHandle(h);
  end;

end;

function HasNoSeekPenalty(const PhysicalDrivePath: String): Boolean;
var
  h :THandle;
  StoragePropertyQuery: TStoragePropertyQuery;
  DeviceSeekPenaltyDescriptor: TDeviceSeekPenaltyDescriptor;
  RSize: DWORD;
begin

  h := CreateFile(PChar(PhysicalDrivePath),FILE_READ_ATTRIBUTES,
                  FILE_SHARE_READ or FILE_SHARE_WRITE,nil,
                  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  if h = INVALID_HANDLE_VALUE then
  begin
    RaiseLastOSError;
  end;

  try
    with StoragePropertyQuery do
    begin
      PropertyId := Ord(StorageDeviceSeekPenaltyProperty);
      QueryType := Ord(PropertyStandardQuery);
    end;

    FillChar(DeviceSeekPenaltyDescriptor,SizeOf(DeviceSeekPenaltyDescriptor),0);
    RSize := 0;
    if DeviceIoControl(h,IOCTL_STORAGE_QUERY_PROPERTY,
                       @StoragePropertyQuery,SizeOf(StoragePropertyQuery),
                       @DeviceSeekPenaltyDescriptor,SizeOf(DeviceSeekPenaltyDescriptor),
                       RSize,nil) = False then
    begin
      RaiseLastOSError;
    end;

    Result := not DeviceSeekPenaltyDescriptor.IncursSeekPenalty;

  finally
    CloseHandle(h);
  end;
end;

procedure PathnameToPhysicalDriveNumber(const Path: String; var PhysicalDrives: TIntegerDynArray);
var
  h: THandle;
  I: Integer;
  MountPoint: String;
  VolumeName: String;
  Size: DWORD;
  RSize: DWORD;
  P: PVolumeDiskExtents;
  lpFilePart : PWideChar;
  lpBuffer : PWideChar;
begin

  SetLength(PhysicalDrives,0);
  lpBuffer := nil;
  { Pathname to mount point }
  Size := GetFullPathName(PWideChar(Path),0,lpBuffer,lpFilePart);
  SetLength(MountPoint,Size);
  if GetVolumePathName(PAnsiChar(Path),PAnsiChar(MountPoint),Size) = False then
  begin
    RaiseLastOSError;
  end;
  SetLength(MountPoint,StrLen(PWideChar(MountPoint)));

  { Mount point to logical volume name }
  Size := 50; // Recomended size from http://msdn.microsoft.com/en-us/library/windows/desktop/aa364994.aspx
  SetLength(VolumeName,Size);
  if GetVolumeNameForVolumeMountPoint(PAnsiChar(MountPoint),PAnsiChar(VolumeName),Size) = False then
  begin
    RaiseLastOSError;
  end;
  SetLength(VolumeName,StrLen(PChar(VolumeName)));
  VolumeName := ExcludeTrailingPathDelimiter(VolumeName);

  { Open volume }
  h := CreateFile(PChar(VolumeName),FILE_READ_ATTRIBUTES,
                  FILE_SHARE_READ or FILE_SHARE_WRITE,nil,
                  OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  if h = INVALID_HANDLE_VALUE then
  begin
    RaiseLastOSError;
  end;

  try
    Size := SizeOf(TVolumeDiskExtents);
    P := AllocMem(Size);
    try
      FillChar(P^,Size,0);
      RSize := 0;
      if DeviceIoControl(h,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
                         nil,0,
                         P,Size,
                         RSize,nil) = False then
      begin
        if GetLastError <> ERROR_MORE_DATA then
        begin
          RaiseLastOSError;
        end;

        Size := SizeOf(TVolumeDiskExtents) +
                SizeOf(DISK_EXTENT) * (P^.NumberOfDiskExtents - 1);
        ReallocMem(P,Size);
        FillChar(P^,Size,0);
        if DeviceIoControl(h,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
                           nil,0,
                           P,Size,
                           RSize,nil) = False then
        begin
          RaiseLastOSError;
        end;
      end;

      SetLength(PhysicalDrives,P^.NumberOfDiskExtents);
      for I := 0 to P^.NumberOfDiskExtents - 1 do
      begin
        PhysicalDrives[I] := P^.Extents[I].DiskNumber;
      end;

    finally
      FreeMem(P);
    end;

  finally
    CloseHandle(h);
  end;

end;

function IstSSD(LW:Char):Boolean;
var
  Index: Integer;
  Filename: String;
  PhysicalDrives: TIntegerDynArray;
  PhysicalDrivePath: String;
  IsSSD: Boolean;
begin
  Result := False;
  Filename := LW + ':\';
  SetLength(PhysicalDrives,0);
  PathnameToPhysicalDriveNumber(Filename,PhysicalDrives);
  try
    IsSSD := False;
    for Index := Low(PhysicalDrives) to High(PhysicalDrives) do
    begin
      PhysicalDrivePath := Format('\\.\PhysicalDrive%d',[PhysicalDrives[Index]]);
      try
        IsSSD := IsSSD or HasNominalMediaRotationRate(PhysicalDrivePath);
      except
        { Ignore }
      end;
      if IsSSD = True then
      begin
        exit(True);
      end;
    end;
  finally
    SetLength(PhysicalDrives,0);
  end;
end;

end.
  Mit Zitat antworten Zitat
t.roller
(Gast)

n/a Beiträge
 
#10

AW: SSD erkennen?

  Alt 23. Apr 2016, 18:52
Es gibt S.M.A.R.T.-Werte, die nur bei SSD vorhanden sind, z.B.
230, E6, Drive Life Protection Status:
100 (protection is not active) oder 90 (protection is active)
231, E7, SSD Life Left 1-100 %
Info:
MKP_306_SMART_attribute.pdf
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz