Disk Space Sleuth

Disk Space Sleuth: A Tale of PowerShell Optimization

Hey there, tech enthusiasts and fellow script-wranglers! Today, we're diving into the world of PowerShell optimization. Buckle up, because we're about to turn a simple disk space query into a lean, mean, data-collecting machine.

The Mission

Our mission, should we choose to accept it (and let's face it, we're geeks, of course we will), is to gather disk information from multiple servers efficiently. We're talking system names, device IDs, and disk sizes - all neatly packaged in a CSV file. Sounds simple, right? Well, hold onto your keyboards, because we're about to kick it up a notch.

The Original Script: A Diamond in the Rough

Sometimes, us old-timers have a script that we have used for many years. Many will tell you the wise words of "If it is not broke, don't fix it". But sometimes, you do not know it is broke until you fix it. That is what happened to me here. We started with this little gem:

1Get-WMIObject Win32_LogicalDisk -computer (Get-Content C:\scripts\servers.txt) -Filter "Drivetype=3" | 
2Select SystemName,DeviceID,@{Name='Size(GB)';Exp={$_.Size /1gb -as [int]}} |
3Export-CSV "C:\CSVReports\DiskDrives.csv"

Not bad, right? It gets the job done. But in the world of IT, "done" isn't enough. We want it done faster, smoother, and with more pizzazz. (Okay, maybe not pizzazz, but definitely faster.)

The Optimization Journey

1. Streamlined Reading

First, we swapped out Get-Content for a StreamReader. It's like upgrading from a bicycle to a motorcycle when reading our server list.

2. CIM for the Win

We ditched Get-WMIObject in favor of Get-CimInstance. It's newer, faster, and doesn't require you to yell "WMI" every time you use it. (Though you can if you want to. I won't judge.)

3. Batch Processing

We introduced batch processing, because why query one server at a time when you can query 10? It's like carpooling, but for data.

4. Parallel Power

By using Invoke-Command, we're now running our queries in parallel. It's like sending out a team of mini-mes to gather data simultaneously. Efficiency at its finest!

5. Write As You Go

Instead of hoarding all our data and then writing it out, we're now writing to our CSV file in batches. It's like clearing your plate between courses at a buffet - keeps things manageable and reduces the risk of a memory "food coma".

The Optimized Script: A Thing of Beauty

And now, ladies and gentlemen, I present to you the optimized script in all its glory:

 1# Define the output file path
 2$outputFile = "C:\CSVReports\DiskDrives.csv"
 3
 4# Remove the existing output file if it exists
 5if (Test-Path $outputFile) {
 6    Remove-Item $outputFile
 7}
 8
 9# Use a StreamReader to read the servers file
10$reader = [System.IO.StreamReader]::new("C:\scripts\servers.txt")
11
12# Process servers in batches
13$batchSize = 10
14$batch = @()
15
16while ($true) {
17    $server = $reader.ReadLine()
18    if ($server -eq $null) {
19        # Process remaining servers in the last batch
20        if ($batch.Count -gt 0) {
21            $results = Invoke-Command -ComputerName $batch -ScriptBlock {
22                Get-CimInstance Win32_LogicalDisk -Filter "Drivetype=3" |
23                Select-Object @{Name='SystemName';Expression={$env:COMPUTERNAME}},
24                              DeviceID,
25                              @{Name='Size(GB)';Expression={[int]($_.Size / 1GB)}}
26            }
27            $results | Export-Csv $outputFile -Append -NoTypeInformation
28        }
29        break
30    }
31
32    $batch += $server
33
34    if ($batch.Count -eq $batchSize) {
35        $results = Invoke-Command -ComputerName $batch -ScriptBlock {
36            Get-CimInstance Win32_LogicalDisk -Filter "Drivetype=3" |
37            Select-Object @{Name='SystemName';Expression={$env:COMPUTERNAME}},
38                          DeviceID,
39                          @{Name='Size(GB)';Expression={[int]($_.Size / 1GB)}}
40        }
41        $results | Export-Csv $outputFile -Append -NoTypeInformation
42        $batch = @()
43    }
44}
45
46$reader.Close()
47
48Write-Host "Disk information has been exported to $outputFile"

You can also find the script, just like all the other wonderful scripts you see on this block, from my GitHub repository here.

The Takeaway

Remember, folks, optimization isn't just about making things faster. It's about being smarter with our resources, reducing strain on our systems, and ultimately, making our lives (and our servers' lives) easier.

So, the next time you're faced with a script that works but could work better, channel your inner optimizer. Your servers (and your fellow IT pros) will thank you.

Until next time, keep scripting, keep optimizing, and may your disk spaces always be plentiful!