How To Build a Disk Space Pie Chart in PowerShell
This article ends our series about using PowerShell to visualize disk space usage. Part 3 explains how to generate a pie chart that displays your space.
December 24, 2024
In this series, I have shown you how my script’s folder tree works and how to generate a list of the largest files on a hard disk. Next, I will explain how the script produces a pie chart.
Part 1: Track Disk Space With a PowerShell Folder Tree
Part 2: Identify the 10 Largest Files on Your Disk
Part 3: Building a Disk Space Pie Chart // Complete Script
The Update-PieChart Function
I designed the script so that when you click a node in the tree, it calls a function called Update-PieChart. The folder path you select by clicking the node is passed to this function.
Here is what the function looks like:
Function Update-PieChart {
param (
[String]$FolderPath
)
# Get the size of the selected folder (in bytes)
$FolderSize = Get-FolderSize -FolderPath $FolderPath
# Calculate Used, Free, and Total Space on Drive
$DriveLetter = $SelectedDrive[0]
$Drive = Get-PSDrive -Name $DriveLetter
$FreeSpace = $Drive.Free
$UsedSpace = $Drive.Used
$TotalSpace = $Drive.Used + $Drive.Free
# Update the pie chart with disk space and folder size
$Series.Points.Clear()
$Series.Points.AddXY("Used Space", $UsedSpace)
$Series.Points.AddXY("Free Space", $FreeSpace)
$Series.Points.AddXY("Folder Size", $FolderSize)
$DisplayTotalSpace= $([math]::Round($TotalSpace / 1GB, 2))
$DisplayUsedSpace= $([math]::Round($UsedSpace / 1GB, 2))
$DisplayFreeSpace = $([math]::Round($FreeSpace / 1GB, 2))
$DisplayFolderSpace= $([math]::Round($FolderSize / 1GB, 2))
$TotalSpaceLabel.Text = "Total Disk Space: - $DisplayTotalSpace GB"
$FreeSpaceLabel.Text = "Free Space - $DisplayFreeSpace GB"
$UsedSpaceLabel.Text = "Used Space - $DisplayUsedSpace GB"
$FolderSpaceLabel.Text = "Selected Folder Space - $DisplayFolderSpace GB"
# Set the chart colors
$Series.Points[0].Color = [System.Drawing.Color]::FromArgb(255, 0, 0) # Red for used space
$Series.Points[1].Color = [System.Drawing.Color]::FromArgb(0, 255, 0) # Green for free space
$Series.Points[2].Color = [System.Drawing.Color]::FromArgb(0, 0, 255) # Blue for folder size
}
Breakdown of the Update-PieChart Function
Calculating the folder size
The first thing the Update-PieChart function does is call another function, Get-FolderSize. As the name suggests, this function calculates the total size of all files in the selected folder and its subfolders. It does this by recursively executing the Get-ChildItem cmdlet, starting from the selected path. The list of files gets mapped to the $Files variable, and the total folder size is determined using $Files.Length.
Calculating drive space
The function then executes the Get-PSDrive cmdlet on the designated hard disk. The command returns various statistics, such as free space and used space. These values are stored in the $FreeSpace and $UsedSpace variables, respectively. Since the Get-PSDrive cmdlet doesn’t provide the total disk size, I calculate it by adding $FreeSpace and $UsedSpace, storing the result in $TotalSpace.
Adding data to the pie chart
After populating the $FreeSpace, $UsedSpace, and $TotalSpace variables, I add $FreeSpace and $UsedSpace to the chart as a series. I also add the $FolderSize variable, which reflects the size of the selected folder.
Next, I create four new variables: $DisplayTotalSpace, $DisplayUsedSpace, $DisplayFreeSpace, and $DisplayFolderSpace. These store the total disk space, used space, free space, and space consumed by the selected folder, all converted to gigabytes. I use these variables for the text summary that appears beneath the chart.
Setting the pie chart colors
The last code section sets the chart colors: green for free space, red for used space, and blue for the space consumed by the selected folder.
Complete Script
Now that I have explained how the script’s components work, here is the script in its entirety:
$SelectedDrive = "W:"
# Load the necessary .NET assemblies for Windows Forms and Charting
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type -AssemblyName System.Windows.Forms.DataVisualization
# Create the Form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Folder Tree and Disk Usage"
$Form.Width = 1400
$Form.Height = 900
# Create the TreeView control
$FolderTree = New-Object System.Windows.Forms.TreeView
$FolderTree.Font = New-Object System.Drawing.Font("Arial", 12,[System.Drawing.FontStyle]::Regular)
$FolderTree.Location = "20,20"
$FolderTree.Size = "700,500"
$Form.Controls.Add($FolderTree)
# Create the Chart control for the pie chart
$Chart = New-Object System.Windows.Forms.DataVisualization.Charting.Chart
$Chart.Location = "800,20"
$Chart.Size = "500,500"
$Form.Controls.Add($Chart)
# Set up the chart area
$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$Chart.ChartAreas.Add($ChartArea)
# Add a series for the pie chart
$Series = New-Object System.Windows.Forms.DataVisualization.Charting.Series
$Series.ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Pie
$Chart.Series.Add($Series)
# Create a custom panel to hold the legend
$LegendPanel = New-Object System.Windows.Forms.Panel
$LegendPanel.Width = 400
$LegendPanel.Height = 400
$LegendPanel.Top = 600
$LegendPanel.Left = 1050
$Form.Controls.Add($LegendPanel)
# Add Labels to simulate legend
$TotalSpaceLabel = New-Object System.Windows.Forms.Label
$TotalSpaceLabel.Size = "300,25"
$TotalSpaceLabel.Text = "Used Space"
$TotalSpaceLabel.Font = New-Object System.Drawing.Font("Arial", 12,[System.Drawing.FontStyle]::Bold)
$TotalSpaceLabel.ForeColor = [System.Drawing.Color]::Black
$TotalSpaceLabel.Location = New-Object System.Drawing.Point(10, 10)
$LegendPanel.Controls.Add($TotalSpaceLabel)
# Add Labels to simulate legend
$UsedSpaceLabel = New-Object System.Windows.Forms.Label
$UsedSpaceLabel.Size = "300,25"
$UsedSpaceLabel.Text = "Used Space"
$UsedSpaceLabel.Font = New-Object System.Drawing.Font("Arial", 12,[System.Drawing.FontStyle]::Bold)
$UsedSpaceLabel.ForeColor = [System.Drawing.Color]::Red # Color corresponding to the "Used Space" part of the chart
$UsedSpaceLabel.Location = New-Object System.Drawing.Point(10, 40)
$LegendPanel.Controls.Add($UsedSpaceLabel)
$FreeSpaceLabel = New-Object System.Windows.Forms.Label
$FreeSpaceLabel.Size = "300,25"
$FreeSpaceLabel.Text = "Free Space"
$FreeSpaceLabel.Font = New-Object System.Drawing.Font("Arial", 12,[System.Drawing.FontStyle]::Bold)
$FreeSpaceLabel.ForeColor = [System.Drawing.Color]::Green # Color corresponding to the "Free Space" part of the chart
$FreeSpaceLabel.Location = New-Object System.Drawing.Point(10, 70)
$LegendPanel.Controls.Add($FreeSpaceLabel)
$FolderSpaceLabel = New-Object System.Windows.Forms.Label
$FolderSpaceLabel.Size = "300,25"
$FolderSpaceLabel.Text = "Selected Folder Space"
$FolderSpaceLabel.Font = New-Object System.Drawing.Font("Arial", 12,[System.Drawing.FontStyle]::Bold)
$FolderSpaceLabel.ForeColor = [System.Drawing.Color]::Blue # Color corresponding to the "Free Space" part of the chart
$FolderSpaceLabel.Location = New-Object System.Drawing.Point(10, 100)
$LegendPanel.Controls.Add($FolderSpaceLabel)
# Largest Files Label
$BigFilesLabel = New-Object System.Windows.Forms.Label
$BigFilesLabel.Location = "200,560"
$BigFilesLabel.Size = "300,25"
$BigFilesLabel.Font = New-Object System.Drawing.Font("Arial", 14,[System.Drawing.FontStyle]::Bold)
$BigFilesLabel.Text = "Largest Files"
$Form.Controls.Add($BigFilesLabel)
# Create the TextBox to display the largest files
$BigFiles = New-Object System.Windows.Forms.TextBox
$BigFiles.Multiline = $true
$BigFiles.ScrollBars = [System.Windows.Forms.ScrollBars]::Vertical
$BigFiles.Size = New-Object System.Drawing.Size(1000,250)
$BigFiles.Location = new-object System.Drawing.Size(20,600)
$BigFiles.Font = New-Object System.Drawing.Font("Arial", 12,[System.Drawing.FontStyle]::Regular)
$Form.Controls.Add($BigFiles)
# Function to calculate folder size (recursively)
Function Get-FolderSize {
Param (
[String]$FolderPath
)
$Size = 0
Try {
# Add all files in the folder and subfolders
$Files = Get-ChildItem -Path $FolderPath -Recurse -File -ErrorAction SilentlyContinue
Foreach ($File in $Files) {
$Size += $File.Length
}
} Catch {
Write-Host "Error calculating size for $FolderPath"
}
Return $Size
}
# Function to load folders into the TreeView recursively
Function Load-FolderTree {
Param (
[System.Windows.Forms.TreeNode]$ParentNode,
[string]$path
)
# Create the node for the current directory
$Node = New-Object System.Windows.Forms.TreeNode -ArgumentList (Get-Item $Path).Name
$Node.Tag = $Path
# Add the node to the parent node
$ParentNode.Nodes.Add($Node)
# Debugging: Print the current directory being processed
Write-Host "Processing folder: $Path"
# Try to load subfolders
Try {
$Subfolders = Get-ChildItem -Path $path -Directory -ErrorAction SilentlyContinue
ForEach ($Dolder in $Subfolders) {
# Recursively load subfolders
Load-FolderTree -ParentNode $node -path $Folder.FullName
}
} catch {
Write-Host "Error accessing folder: $path"
}
}
# Function to update the pie chart based on selected folder
Function Update-PieChart {
param (
[String]$FolderPath
)
# Get the size of the selected folder (in bytes)
$FolderSize = Get-FolderSize -FolderPath $FolderPath
# Calculate Used, Free, and Total Space on Drive
$DriveLetter = $SelectedDrive[0]
$Drive = Get-PSDrive -Name $DriveLetter
$FreeSpace = $Drive.Free
$UsedSpace = $Drive.Used
$TotalSpace = $Drive.Used + $Drive.Free
# Update the pie chart with disk space and folder size
$Series.Points.Clear()
$Series.Points.AddXY("Used Space", $UsedSpace)
$Series.Points.AddXY("Free Space", $FreeSpace)
$Series.Points.AddXY("Folder Size", $FolderSize)
$DisplayTotalSpace= $([math]::Round($TotalSpace / 1GB, 2))
$DisplayUsedSpace= $([math]::Round($UsedSpace / 1GB, 2))
$DisplayFreeSpace = $([math]::Round($FreeSpace / 1GB, 2))
$DisplayFolderSpace= $([math]::Round($FolderSize / 1GB, 2))
$TotalSpaceLabel.Text = "Total Disk Space: - $DisplayTotalSpace GB"
$FreeSpaceLabel.Text = "Free Space - $DisplayFreeSpace GB"
$UsedSpaceLabel.Text = "Used Space - $DisplayUsedSpace GB"
$FolderSpaceLabel.Text = "Selected Folder Space - $DisplayFolderSpace GB"
# Set the chart colors
$Series.Points[0].Color = [System.Drawing.Color]::FromArgb(255, 0, 0) # Red for used space
$Series.Points[1].Color = [System.Drawing.Color]::FromArgb(0, 255, 0) # Green for free space
$Series.Points[2].Color = [System.Drawing.Color]::FromArgb(0, 0, 255) # Blue for folder size
}
# Function to find the ten largest files on the system
function Get-LargestFiles {
# Search the entire C: drive for files (or another drive as necessary)
$Files = Get-ChildItem -Path "$SelectedDrive\" -Recurse -File -ErrorAction SilentlyContinue
# Sort the files by size and select the top 10
$LargestFiles = $Files | Sort-Object Length -Descending | Select-Object -First 10
# Format the result as a string
$FileList = "Size `t`t File `r`n"
ForEach ($File in $LargestFiles) {
$FileList += "$([math]::Round($File.Length / 1GB, 2)) GB `t`t $($File.FullName) `r`n"
}
# Update the TextBox with the largest files
$BigFiles.Text = $FileList
$BigFiles.SelectionStart = 0
$BigFiles.SelectionLength = 0
}
# Load the root directory
$RootPath = "$SelectedDrive\" # You can change this to another path
# Create the root node and add it to the TreeView
$RootNode = New-Object System.Windows.Forms.TreeNode -ArgumentList (Get-Item $RootPath).Name
$RootNode.Tag = $rootPath
$FolderTree.Nodes.Add($rootNode)
# Start loading subfolders for the root node
Load-FolderTree -ParentNode $RootNode -path $RootPath
# Call the function to display the ten largest files when the script runs
Get-LargestFiles
# Event handler for when a node is selected in the TreeView
$FolderTree.Add_AfterSelect({
Param ($Sender, $E)
# Get the selected folder path
$SelectedNode = $E.Node
$SelectedFolderPath = $SelectedNode.Tag
# Update the pie chart with the size of the selected folder
Update-PieChart -FolderPath $SelectedFolderPath
})
# Disable output to the console (suppress unwanted output)
[System.Windows.Forms.Application]::EnableVisualStyles()
# Ensure the form runs and appears
[System.Windows.Forms.Application]::Run($Form)
# Disable output to the console (suppress unwanted output)
[System.Windows.Forms.Application]::EnableVisualStyles()
# Ensure the form runs and appears
[System.Windows.Forms.Application]::Run($Form)
About the Author
You May Also Like