2017-12-29 7 views
0

In diesem Snippet habe ich eine Funktion (FDiskScan), die einen Computernamen als Eingabe erhält und ein Array von Objekten zurückgeben sollte.PowerShell-Array erhält neue Einträge

function FDiskScan ([String] $name) 
{ 
    $outarray = [System.Collections.ArrayList]@() 
    $diskscan = Get-WmiObject Win32_logicaldisk -ComputerName $name 

    foreach ($diskobj in $diskscan) 
    { 
     if($diskobj.VolumeName -ne $null) 
     { 
      $max = $diskobj.Size/1024/1024/1024 
      $free = $diskobj.FreeSpace/1024/1024/1024 
      $full = $max - $free 

      $obj = @{ 
       'ID' = $diskobj.deviceid 
       'Name' = $diskobj.VolumeName 
       'TotalSpace' = $max 
       'FreeSpace' = $free 
       'OccupiedSpace' = $full } 
      $TMP = New-Object psobject -Property $obj 
      $outarray.Add($TMP) 
     } 
    } 
    return $outarray 
} 

$pc = "INSERT PC NAME HERE" 
$diskdata = [System.Collections.ArrayList]@() 
$diskdata = FDiskScan($pc) 

foreach ($disk in $diskdata) 
{ 
    Write-Host "Disco: " $disk.ID 
    Write-Host "Espaço Total: " ([math]::Round($disk.TotalSpace, 2)) "GB" 
    Write-Host "Espaço Ocupado: " ([math]::Round($disk.OccupiedSpace, 2)) "GB" 
    Write-Host "Espaço Livre" ([math]::Round($disk.FreeSpace, 2)) "GB" "`n" 
} 

Innerhalb der Funktion mit Debugging und die Variablen geht in ich, dass alles in Ordnung ist sehen, und wenn das Array aus der Funktion und in den Skriptbereich wird ergänzt es 2 weitere Einträge.

Im Debug-Modus sagt es mir, dass $outarry innerhalb FDiskScan hat die zwei Festplatten, die ich auf meinem System organisiert habe, wie sie sein sollten.

jedoch auf:

$diskdata = FDiskScan($pc) 

Er sagt, dass es einen Eintrag des Wertes 0 auf Index 0 und der Wert 1 auf den Index 1, hat dann die Scheiben Anzug, erste Scheibe C folgen: in Index 3 und Scheibe D in Index 4.

Das erwartete Verhalten war für Index 0 und 1 mit Festplatten C und D bzw. keine Phantom 0 und 1 Einträge.

+0

@ Eines ist PhaniAnne bewusst zu sein: '$ diskdata = FDiskScan ($ pc)' ist nicht der richtige Weg, um eine Funktion mit Powershell zu rufen. Der richtige Weg ist '$ diskdata = FDiskScan $ pc'. Der falsche Weg funktioniert mit einer einzigen Argumentfunktion, aber sobald Sie zu zwei Argumenten kommen, wie '$ diskdata = FDiskScan2 ($ pc, $ DriveType)' wird es nicht wie erwartet funktionieren. –

+0

Sie denken, Sie rufen eine Funktion mit Argument 1 = '$ pc' und Argument 2 =' $ DriveType' auf, aber was Sie wirklich tun, ist den Aufruf der Funktion mit Argument 1 = ein Array von '($ pc, $ DriveType) 'und Argument 2 ist null. Der korrekte Aufruf der Funktion wäre '$ diskdata = FDiskScan2 $ pc $ DriveType'. –

+0

@BaconBits Die Funktion ist, nur ein Argument zu haben, zumindest für jetzt. Aber ich danke Ihnen, dass Sie mich auf die bessere Art, Argumente zu schreiben, hingewiesen haben. Ich habe eine bessere Vorstellung von C wie Syntax, also manchmal werde ich gemischt, aber mit einigen der Details von Sprachen wie Powershell. –

Antwort

1

Beim Hinzufügen eines Objekts zu einer Array-Liste in PowerShell (d. H. $outarray.Add($TMP)) wird der Index, bei dem das Objekt hinzugefügt wurde, zurückgegeben. Da Sie den Rückgabewert keiner Variablen zuweisen, gibt die Funktion eine System.Array zurück, die die Indizes und die Einträge der Array-Liste enthält, die von return $outarray zurückgegeben wird. Das ist der Grund, warum Ihr Funktionsrückgabewert 4 Elemente enthält. Desweiteren sind Ihre Funktionen in diesem Fall nicht vom Typ System.Collections.ArrayList sondern vom Typ System.Array. Um dieses Verhalten zu vermeiden, machen Sie folgendes.

$null = $outarray.Add($TMP); 
+0

Sie haben angegeben, dass der Rückgabetyp der Funktion "System.Array" anstelle von "System.Collections.ArrayList" ist. Da der unbeabsichtigte Effekt auf den Output der Add-Methode zurückzuführen war, konnten Sie mir sagen, was und wie der Typ der Funktion anspricht und wie der Ausgabetyp einer Funktion –

+0

PowerShell dynamisch, implizit deklariert wird typisierte Skriptsprache. Das bedeutet, dass eine Variable ihren Typ zur Laufzeit ändern kann. Außerdem gibt es keine Möglichkeit den Ausgabetyp einer Funktion zu definieren. Der Typ des Rückgabewerts hängt vom Wert ab, der von der return-Anweisung zurückgegeben wird. Wenn andere nicht zugewiesene Werte von einem Cmdlet (d. H. Wie in der Frage) zurückgegeben werden, werden diese Werte zum Rückgabewert hinzugefügt, der dann ein Array ist, das alle Elemente enthält. – rufer7

2

Sie sehen 0, 1 wegen dieser Linie - $outarray.Add($TMP). Ändern Sie es in $outarray.Add($TMP) | Out-Null. Ich denke PowerShell druckt den Index beim Hinzufügen zum Array.

+0

Nach der Suche scheint die Methode Add des ArrayList-Objekts neben dem Hinzufügen den Index auszugeben, zu dem sie hinzugefügt wurde. Was dies tut ignoriert diese Ausgabe, und ich fand auch die Varianten: '$ null = $ outarray.Add ($ TMP) $ outarray.Add ($ TMP)> $ null' HINWEIS: Die $ Null = $ outarray.Add ($ TMP) 'wurde in der anderen Antwort von @ rufer7 dargestellt. –

+0

Sorry für den doppelten Kommentar, aber ich stolperte über diesen [thread] (https://stackoverflow.com/questions/5260125/whats-the- Besser-Reiniger-Weg-zu-Ignorieren-Ausgabe-in-Powershell). Das scheint darauf hinzuweisen, dass andere Optionen im Allgemeinen besser wären, als nach Out-Null zu pumpen. Meinungen? Und ja, mir ist klar, dass es in diesem Fall Nadeln sind und sinnlos, ich möchte gerne die Best Practices auf lange Sicht aufgreifen. –

+0

@AlexanderCorreia Es ist gut, sich über Best Practices zu informieren, aber ich würde mir keine Gedanken über die Leistung machen, wenn die App nicht wirklich langsam läuft. Sie können das Measure-Command-Cmdlet wie in Ihrem Link gezeigt ausführen und herausfinden, welches schneller ist, wenn Sie Zeit haben! Es gibt * immer * einen besseren Weg; Sie könnten Zeit verlieren, um den "besten" Weg zu finden, für wenig Gewinn. –

Verwandte Themen