C++ Festplatteninfo auslesen

MarkP

Lieutenant
Registriert
Jan. 2016
Beiträge
639
Ich versuche in C++ unter Windows eine Liste der im PC vorhandenen Laufwerke und jeweils ein paar Basisinfos dazu auszugeben.
Das Meiste bekomme ich schon auf die Reihe, aber ein paar Dinge finde ich nicht raus.

Mit getListOfDrives() bekomme ich einen Vector mit den Laufwerksbuchstaben.
Mit FindFirstFile() und einer do .. while Schleife bekomme ich den Inhalt des Laufwerks, also Ordner und Dateien, die kann ich zählen, bei Bedarf noch eine weitere, verschachtelte Schleife die Unterordner öffnet und liest, alles so weit kein Problem, auch die Liste von Ordnern und Dateien ausgeben habe ich fast auf Anhieb hinbekommen.
Was ich nicht weiss ist, ob ich die reine Anzahl von Ordnern und Dateien ohne deren Namen dazu wirklich in einer Schleife selber zählen muss, oder ob es bei Microsoft eine Abfrage als fertige Funktion dafür gibt?

Wo ich mich dann richtig schwer tue sind die Basisinfos des Laufwerks, also Gesamtgrösse der Platte und der einzelnen Partitionen, belegter Platz, verbleibender freier Platz, denn da sehe ich den Wald vor lauter Bäumen nicht.
Bei Microsoft finde ich derartige Unmengen von verschiedenen Funktionen, dass ich nicht mal entscheiden kann welche davon ich nun nehmen soll und wenn ich dann mal eine ausprobiere, dann bringe ich die Syntax nicht auf die Reihe.
GetDiskFreeSpace(), oder DeviceIoControl() mit IOCTL_DISK_GET_LENGTH_INFO, oder GetVolumeInformation() und was sonst sich Microsoft an Namen für die Funktionen hat einfallen lassen.

Hat Jemand Erbarmen und vielleicht auch ein kleines Stückchen Code mit dem ich die Basisinfos eines Laufwerks auslesen kann?
 
Hallo MarkP,

ich kenn mich mit C++ nicht gut aus und es ist nur ein Vorschlag: Aber du könntest dir “CrystalDiskInfo“ anschauen. Das ist Open Source und der Quellcode liegt offen. Ich weiß zwar nicht mal ob das C++ oder eine andere Sprache ist aber einen Versuch ist es wert. Es ist von den Möglichkeiten her vielleicht etwas überdimensioniert aber ein Blick kann ja nicht schaden. Zu finden unter folgenden URLs:

https://www.computerbase.de/downloads/systemtools/festplatten/crystaldiskinfo/

oder direkt:

https://crystalmark.info/en/download/

Gruß
Sesimbra
 
Wer mal versucht hat Code von Anderen abzukupfern, der weiss in aller Regel, dass das noch viel schwerer ist als das Ganze von Grund auf selber zu lernen.
 
Das sind halt immer alles in 100 Layern verschachtelte Stückchen von Code, bis man da mal zurückverfolgt hat, von wo z.B. die Funktion GetDrives() aufgerufen wird, bzw. wohin sie ihre mit GetLogicalDrives() gelesenen Daten zurück gibt, hat man vermutlich schneller via Google rausgefunden wie GetLogicalDrives() funktioniert.
Ausserdem besteht Code in C# gefühlt zu 99% aus Libraries und 1% eigenem Code und bis man das dann so weit aus den Libraries geklaubt hat, dass es in C++ nutzbar wird .... das dauert.
 
Hmm? Du wolltest freien Speicher usw haben, das ist ein Aufruf zu GetDiskFreeSpaceEx. Die API wird auch auf der MS Seite so empfohlen, weil sie direkte werte liefert und keine Sektoren usw.

Bzgl Driveinfo, liegt primär daran, dass es halt Plattform übergreifend ist, aber die Drives hast du ja schon aufgelistet.
 
  • Gefällt mir
Reaktionen: aronlad
Ja, GetDiskFreeSpaceEx habe ich auch gerade eben gefunden.
Der Haken an dem Ding ist die Verwendung von ULARGE_INTEGER statt der heute üblichen simplen Unterstützung für u64 die fast alle Compiler können.
Ich suche gerade danach wie man ULARGE_INTEGER zu UINT64 konvertieren kann, oder überlege ob ich den Wert ohne Konvertierung verwenden kann.

In jedem Fall schon mal Danke für die schnellen Antworten, da habe ich heute noch Lesestoff.
@BAGZZlash HotExamples war auch ein guter Tipp, danke dafür.
 
Zuletzt bearbeitet:
MarkP schrieb:
Kannst einfach auf unsigned __int64 casten. Ist identisches Speicherlayout wenn ichs richtig im Kopf habe. Müsste aber auch in der MS Doku beschrieben sein wenn's nicht so ist
 
  • Gefällt mir
Reaktionen: MarkP
MarkP schrieb:
Mit FindFirstFile() und einer do .. while Schleife bekomme ich den Inhalt des Laufwerks, also Ordner und Dateien, die kann ich zählen,
Viel Spaß dabei :-) Lieber nicht auf des Systemplatte versuchen. Einerseits musst Du natürlich fehlende Zugriffsrechte abfangen, andererseits ist das auch mit einer SSD extrem langsam, wenn das Laufwerk mal etwas mehr Dateien enthält. Wenn man natürlich nur SSDs hat, kann man das ganze in ein paar Threads verteilen. Aber wehe, dann kommt mal eine HDD oder ein Netzwerklaufwerk auf einem langsamen NAS (mit HDDs) dazu.

MarkP schrieb:
oder ob es bei Microsoft eine Abfrage als fertige Funktion dafür gibt?
Nein, dazu gibt es nichts. Mit ein Grund, warum jedes Backup-Tool entsprechend lahm ist, wenn es die Quell- und/oder Zielverzeichnisse vergleichen soll.

Einzige Möglichkeit, sowas extrem zu beschleunigen ist quasi die selbe, die man früher beim C64/C1541 schon anwenden musste. Nämlich der direkte Zuriff auf die FAT, also die Directory-Einträge des Dateisystems. Das klappt aber nur, wenn man (a) das Dateisystem kennt und (b) nur lokale Datenträger hat. Naja, Adminrechte braucht man vermutlich heutzutage dafür auch noch.

Ich habe die Daten damals über
GetDriveType
GetVolumeInformation
GetDiskFreeSpaceEx
aus "kernel32" ausgelesen, da mich die Anzahl an Dateien und deren Namen nicht interessiert hat. Das ganze aber unter .NET, das mir u.A. mit Directory.GetLogicalDrives() schon die Liste der Laufwerke liefert.

MarkP schrieb:
Hat Jemand Erbarmen und vielleicht auch ein kleines Stückchen Code mit dem ich die Basisinfos eines Laufwerks auslesen kann?
Ich nehme mal an, dass für Dich ein "Laufwerk" eine logische Partition ist und nicht das physikalische Laufwerk?
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: MarkP
@gymfan
Vielen Dank für die ausführliche Antwort, hat mir sehr geholfen.
Bei mir haben sämtliche physikalischen Festplatten immer nur genau eine Partition über die gesamte Grösse.
Die Zeiten als ich noch mehrere Partitionen pro Platte hatte sind lange vorbei, von daher würfele ich hier vermutlich Begriffe durcheinander, weil es für mich halt dasselbe ist.
Faktisch will ich natürlich die Daten der Partition haben, aber ob die nun ein paar Byte weniger hat als die physikalische Platte fällt eh in der Rundung weg, wenn ich den Wert in Byte 3 oder 4x durch 1024 teile.

Nebenbei @alle: Erfolgsmeldung, GetDiskFreeSpaceEx() klappt mit Hilfe vom Beispiel von HotExamples prima.
Nu muss ich nur noch einen Haufen Casts und Konvertierungen einbauen, damit ich das Ganze als sinnvollen Text im TextOut unter WM_PAINT angezeigt bekomme, aber das schaffe ich locker selber.

Nochmal vielen Dank an alle, ihr seid die Besten.
 
Für solche Dinge gibts eigentlich das Common Interface Model (CIM), bzw. Microsofts Implementierung davon (Windows Management Instrumentation, WMI).
Das ist ein standardisiertes Interface für Systeminformationen.

Ansonsten "habe ich das Gefühl" daß du vielleicht nochmal einen Blick auf das Zugriffsmodell von Windows werfen solltest, bzw an der Stelle von Storagesystemen (nicht nur Windows).
Daten liegen in einem Dateisystem.
Dateisysteme liegen in einem Volume.
Volumes liegen in Partitionen (kann, aber muß nicht eine einzelne sein).
Partitionen liegen auf virtuellen disk devices.
Und die virtuellen disk devices haben dann irgendwelche Storage im Backend, die dich an der Stelle nicht weiter interessieren wird (hardware device, iscsi device, virtual disk, etc pp.)

Das womit man in Windows interagiert sind Dateisysteme. Der ganze Rest darunter ist abstrahiert.
Wenn Du auf Dateisysteminformationen zugreifen willst, dann brauchst du die Dateisystem-API. Sollte auf der Hand liegen. :daumen:

Protip, verschachtelte Schleifen sind ganz schlecht und eignen sich auch nicht für Baumstrukturen.
Was du suchst sind Traversal Funktionen, entweder breadth first oder depth first, mit denen du den Verzeichnisbaum eben als Baum durchläufst. Im Zweifel selber was implementieren.
Wenn Du Abfragen auf den MFT beschränken kannst, umso besser.

C++ ist auch nicht unbedingt der beste Ansatz für sowas (da man arg viel selber implementieren muß), aber wenn man was lernen will, eignet sich natürlich mehr oder weniger alles gleich gut.
 
Iqra schrieb:
C++ ist auch nicht unbedingt der beste Ansatz für sowas (da man arg viel selber implementieren muß), aber wenn man was lernen will, eignet sich natürlich mehr oder weniger alles gleich gut.

Es ist genau andersrum.
Ich habe noch nie irgendwas für irgendwen Anders gecoded als für mich selber und ich verwende mit voller Absicht C++, genau WEIL ich damit alles selber machen ..... nicht muss sondern ...... kann.
Dass das länger dauert ist völlig klar, aber darum geht es gar nicht, es macht mir ganz schlicht Spass kleine und für mich selber nützliche Tools zu coden und dabei so wenig wie möglich auf Implementierungen von Anderen zurück zu greifen.
Deswegen verwende ich auch nicht VisualC++ oder sowas, sondern Code::Blocks/MinGW/GCC++.
 
Zurück
Oben