[PowerShell] Auswertung der WMI-Klasse "LogicalDisk" liefert nicht immer ein Ergebnis

Misdemeanor

Lieutenant Pro
Registriert
Mai 2009
Beiträge
558
Hallo zusammen.

Ich bin gerade dabei, eine (relativ einfache) Auswertung von Festplattenspeicher zu schreiben. Weil ich mit gefundenen Lösungen nicht zufrieden war und sich außerdem der Drang in mir regte, es selbst einmal zu versuchen, habe ich mich mal dran gesetzt und bin auf ein Problem gestoßen.

Leider funktioniert mein Script nämlich nur dann, wenn ich mehr als einen Datenträger auf dem PC auswerte.
Zur Auswertung selber nutze ich übrigens die Klasse Win32_LogicalDisk, um mir die Daten zu den Datenträgern anzeigen zu lassen.


Das ist, was ich bisher versucht habe:
Code:
Clear-Host

# Angabe Schwellenwert in %
$Schwellenwert = 20

# Array aller physikalischen Laufwerke erstellen
$ArrayLaufwerke = Get-WmiObject Win32_LogicalDisk | Where-Object DriveType -eq 3

#$ArrayLaufwerke.count -gt 0

# Durchlauf des Arrays, Index beachten
for ($i = 0; $i -lt $ArrayLaufwerke.length; $i++) {
    
    # Gesamtspeicher, Restspeicher, Berechnung Prozent Restspeicher
    $LaufwerkGesamtSpeicher = [System.Math]::round([int]($ArrayLaufwerke[$i].Size/1024/1024/1024),2)
    $LaufwerkFreierSpeicher = [System.Math]::round([int]($ArrayLaufwerke[$i].FreeSpace/1024/1024/1024),2)
    $LaufwerkFreiInProzent  = [System.Math]::round(100/($LaufwerkGesamtSpeicher/$LaufwerkFreierSpeicher),2)

    
    # Auflisten der Laufwerke im Array
    Write-Host Laufwerk $ArrayLaufwerke[$i].DeviceID -ForegroundColor Green
    Write-Host Gesamt: $LaufwerkGesamtSpeicher GByte
    Write-Host Frei: $LaufwerkFreierSpeicher GByte "($LaufwerkFreiInProzent %)"
    
    if ($LaufwerkFreiInProzent -lt $Schwellenwert) {
        Write-Host "Achtung! " -ForegroundColor Red -NoNewline; Write-Host Der Festplattenplatz liegt unter $Schwellenwert %!
        
    }
    # Leerzeile einfügen
    Write-Host 

}

Das Ergebnis (im PowerShell ISE) - wie zu erwarten - sieht so aus:
2014-01-15_105429.jpg


Seltsam wird es nun, wenn ich Laufwerk E: entferne (es handelt sich um eine USB-Festplatte) und nur noch ein Laufwerk vorhanden bleibt. Das Script liefert dann kein Ergebnis mehr, auch nicht für Laufwerk C:.
Die Prüfung des Arrays ergibt, dass es keine Einträge enthält. Das prüfe ich mit dem Code in Zeile #9, hier wird ein "FALSE" ausgegeben, d.h. das Array ist nicht größer 0 und damit leer!

Wieso also? Wenn ich nur eine Platte C: auswerte, und dafür
Code:
Get-WmiObject Win32_LogicalDisk  | Where-Object DriveType -eq 3
nutze, erhalte ich doch auch ein Ergebnis. Hä? Kann mir das jemand genauer erläutern und mir sagen, wo der Denk- und Code-Fehler ist?

Ich hoffe, ich konnte mein Problem verständlich darstellen und würde mich über konstruktive Rückmeldung freuen.
Danke & MfG
 
Ich denke es liegt an dem "Where-Object DriveType -eq 3", also nur feste Platten, keine USB-Sticks etc. wenn ich richtig verstanden habe.
Ich kenne mich mit PS nicht so aus, aber probiere es mal mit einem Filter:

Get-WMIObject Win32_LogicalDisk -filter "DriveType=3"

LG Tigerass
 
Hallo Tigerass 2.0,

Danke für Deinen Input. Leider ändert es jedoch an der Problematik nichts.

Die Filter-Bedingung hat dieselbe Auswirkung wie der "DriveType" - es werden nur die Elemente gelistet, deren DriveType = 3 ist.
Hintergrund ist der, dass bspw. Netzlaufwerke andere DriveType-IDs haben als USB-Sticks oder CD/DVD-Laufwerke. Alles, was physikalisch dran hängt bzw. vorhanden ist, hat als ID die "3", weshalb der Filter zwar richtig ist, aber nichts an der Ausgabe ändert. Das Problem liegt also wo anders.

Du kannst das ja mal im PowerShell ISE durchjagen, sofern Du mehr als ein LW hast, sollte es klappen, hast Du nur eines, klappt es nicht mehr. Irgendwo gibt's da einen Bruch in der Logik, weil das Array nicht mehr befüllt wird, sofern nur noch ein Datenträger vorhanden ist.

So sieht's aus mit einem LW:
Code:
PS H:\> Get-WmiObject Win32_LogicalDisk | Where-Object DriveType -eq 3

DeviceID     : C:
DriveType    : 3
ProviderName : 
FreeSpace    : 73282539520
Size         : 127666221056
VolumeName   : System


Und so sieht's aus mit zwei LWs:
Code:
PS H:\> Get-WmiObject Win32_LogicalDisk | Where-Object DriveType -eq 3

DeviceID     : C:
DriveType    : 3
ProviderName : 
FreeSpace    : 73282703360
Size         : 127666221056
VolumeName   : System

DeviceID     : E:
DriveType    : 3
ProviderName : 
FreeSpace    : 376264065024
Size         : 500091060224
VolumeName   : PLATINUM

Es macht also irgendwie keinen Sinn.
Ist nur C: vorhanden, wird C: ausgewertet und ausgegeben.
Sind C: und E: vorhanden, werden die ebenfalls ausgewertet und ausgegeben.

Warum wird das Array nicht befüllt?
Danke für weitere konstruktive Hinweise.
 
Bei mir:
Code:
PS C:\Users\Admin> Get-WmiObject Win32_LogicalDisk | Where-Object DriveType -eq 3
Where-Object : Der Parameter "FilterScript" kann nicht gebunden werden. Der Wert "DriveType" vom Typ "System.String" kann nicht in den Typ "S
ystem.Management.Automation.ScriptBlock" konvertiert werden.
Bei Zeile:1 Zeichen:47
+ Get-WmiObject Win32_LogicalDisk | Where-Object <<<<  DriveType -eq 3
    + CategoryInfo          : InvalidArgument: (:) [Where-Object], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WhereObjectCommand

Wohingegen die -filter variante Funktioniert.
 
Oh ich sollte vielleicht sagen, dass ich Windows 8.1 einsetze, die PS-Version ist mittlerweile 4.

Code:
PS H:\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

Angesichts dieser Tatsache sollte ich Deine -filter-Variante besser vorziehen.
Aber mein Problem besteht leider immer noch - das Array wird nicht befüllt. Why on earth?
Ergänzung ()

HEUREKA, ich hab's jetzt *seufz*
Das Problem liegt nicht der WMI-Klasse, sondern ... tadaaa - am vermeintlichen Array mit den Laufwerks-Objekten.

Problem:
Wenn man das Array - wie gezeigt - deklariert, funktioniert das zwar, aber mit einer Einschränkung.
Code:
$ArrayLaufwerke = Get-WMIObject Win32_LogicalDisk -filter "DriveType=3"
Wird nämlich nur ein Objekt zugewiesen (C:), ist die Variable einfach nur eine Variable und kein Array.
Werden zwei oder mehr Objekte zugewiesen (C: und E: bspw.), ist die Variable ein Array.

Solange die Variable kein Array ist, kann ich diese auch nicht durchlaufen und auch nicht mit einer Zählervariable [$i] darauf zugreifen, demzufolge -> kein Ergebnis.

Abhilfe geschaffen habe ich damit, dass man das Array zwingend als solches mit @() deklariert:
Code:
$ArrayLaufwerke = @(Get-WMIObject Win32_LogicalDisk -filter "DriveType=3")

Ob's überhaupt ein Array ist, kann man übrigens damit prüfen:
Code:
$ArrayLaufwerke -is [system.array]


Der Vollständigkeit halber hier der gesamte Code:
Code:
Clear-Host

# Angabe Schwellenwert in %
$Schwellenwert = 20

# Array aller physikalischen Laufwerke erstellen
#$ArrayLaufwerke = @(Get-WmiObject Win32_LogicalDisk | Where-Object DriveType -eq 3)
$ArrayLaufwerke = @(Get-WMIObject Win32_LogicalDisk -filter "DriveType=3")

# Prüfen, ob's ein Array ist:
#$ArrayLaufwerke -is [system.array]

# Zähler-Variable ersetzen
#Write-Host $zaehlerArrayAnzahl = ($ArrayLaufwerke | Measure-Object).Count

# Prüfen, wie viele Objekte (= Laufwerke) im Array vorhanden sind
#$ArrayLaufwerke.count


# Durchlauf des Arrays, Index beachten
for ($i = 0; $i -lt $ArrayLaufwerke.count; $i++) {
    
    # Gesamtspeicher, Restspeicher, Berechnung Prozent Restspeicher
    $LaufwerkGesamtSpeicher = [System.Math]::round([int]($ArrayLaufwerke[$i].Size/1024/1024/1024),2)
    $LaufwerkFreierSpeicher = [System.Math]::round([int]($ArrayLaufwerke[$i].FreeSpace/1024/1024/1024),2)
    $LaufwerkFreiInProzent  = [System.Math]::round(100/($LaufwerkGesamtSpeicher/$LaufwerkFreierSpeicher),2)

    
    # Auflisten der Laufwerke im Array
    Write-Host Laufwerk $ArrayLaufwerke[$i].DeviceID -ForegroundColor Green
    Write-Host Gesamt: $LaufwerkGesamtSpeicher GByte
    Write-Host Frei: $LaufwerkFreierSpeicher GByte "($LaufwerkFreiInProzent %)"
    
    if ($LaufwerkFreiInProzent -lt $Schwellenwert) {
        Write-Host "Achtung! " -ForegroundColor Red -NoNewline; Write-Host Der Festplattenplatz liegt unter $Schwellenwert %!
        
    }
    # Leerzeile einfügen
    Write-Host 

}

Ich werde das Ganze jetzt noch soweit verwursten, dass ich in einem neuen Array alle Laufwerke sammele, bei denen der Schwellenwert überschritten wird. Dann wird eine E-Mail generiert mit diesen Laufwerken und Füllständen als Inhalt.
 
Zuletzt bearbeitet: (Fehler korrigiert!)

Ähnliche Themen

Antworten
7
Aufrufe
4.013
R
Zurück
Oben