Skip to content

Instantly share code, notes, and snippets.

@SMSAgentSoftware
Created August 15, 2018 13:27
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save SMSAgentSoftware/c0b0a03d6cac2d350be2483a9dfcd635 to your computer and use it in GitHub Desktop.
Save SMSAgentSoftware/c0b0a03d6cac2d350be2483a9dfcd635 to your computer and use it in GitHub Desktop.
Creates csv and html disk usage reports using WizTree portable
# Script to export html and csv reports of file and directory content on the system drive
# Use to identify large files/directories for disk space cleanup
# Uses WizTree portable to quickly retrieve file and directory sizes from the Master File Table on disk
# Download and extract the WizTree64.exe and place in the same directory as this script
# Set the running location
$RunLocation = $PSScriptRoot
#$RunLocation = "C:\temp"
$TempLocation = "C:\temp"
# Set Target share to copy the reports to
$TargetRoot = "\\server-01\sharename\DirectorySizeInfo"
# Free disk space thresholds (percentages) for summary report
$script:Thresholds = @{}
$Thresholds.Warning = 80
$Thresholds.Critical = 90
# Custom function to exit with a specific code
function ExitWithCode
{
    param
    (
        $exitcode
    )
    $host.SetShouldExit($exitcode)
    exit
}
# Function to set the progress bar colour based on the the threshold value in the summary report
function Set-PercentageColour {
param(
[int]$Value
)
If ($Value -lt $Thresholds.Warning)
{
$Hex = "#00ff00" # Green
}
If ($Value -ge $Thresholds.Warning -and $Value -lt $Thresholds.Critical)
{
$Hex = "#ff9900" # Amber
}
If ($Value -ge $Thresholds.Critical)
{
$Hex = "#FF0000" # Red
}
Return $Hex
}
# Define Html CSS style
$Style = @"
<style>
table {
border-collapse: collapse;
}
td, th {
border: 1px solid #ddd;
padding: 8px;
}
th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4286f4;
color: white;
}
</style>
"@
# Set the filenames of WizTree csv's
$FilesCSV = "Files_$(Get-Date -Format 'yyyyMMdd_hhmmss').csv"
$FoldersCSV = "Folders_$(Get-Date -Format 'yyyyMMdd_hhmmss').csv"
# Set the filenames of customised csv's
$ExportedFilesCSV = "Exported_Files_$(Get-Date -Format 'yyyyMMdd_hhmmss').csv"
$ExportedFoldersCSV = "Exported_Folders_$(Get-Date -Format 'yyyyMMdd_hhmmss').csv"
# Set the filenames of html reports
$ExportedFilesHTML = "Largest_Files_$(Get-Date -Format 'yyyyMMdd_hhmmss').html"
$ExportedFoldersHTML = "Largest_Folders_$(Get-Date -Format 'yyyyMMdd_hhmmss').html"
$SummaryHTMLReport = "Disk_Usage_Summary_$(Get-Date -Format 'yyyyMMdd_hhmmss').html"
# Run the WizTree portable app
Start-Process -FilePath "$RunLocation\WizTree64.exe" -ArgumentList """$Env:SystemDrive"" /export=""$TempLocation\$FilesCSV"" /admin 1 /sortby=2 /exportfolders=0" -Verb runas -Wait
Start-Process -FilePath "$RunLocation\WizTree64.exe" -ArgumentList """$Env:SystemDrive"" /export=""$TempLocation\$FoldersCSV"" /admin 1 /sortby=2 /exportfiles=0" -Verb runas -Wait
#region Files
# Remove the first 2 rows from the CSVs to leave just the relevant data
$CSVContent = Get-Content -Path $TempLocation\$FilesCSV -ReadCount 0
$CSVContent = $CSVContent | Select -Skip 1
$CSVContent = $CSVContent | Select -Skip 1
# Create a table to store the results
$Table = [System.Data.DataTable]::new("Directory Structure")
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Name",[System.String]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (Bytes)",[System.Int64]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (KB)",[System.Decimal]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (MB)",[System.Decimal]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (GB)",[System.Decimal]))
# Populate the table from the CSV data
Foreach ($csvrow in $CSVContent)
{
$Content = $csvrow.split(',')
[void]$Table.rows.Add(($Content[0].Replace('"','')),$Content[2],([math]::Round(($Content[2] / 1KB),2)),([math]::Round(($Content[2] / 1MB),2)),([math]::Round(($Content[2] / 1GB),2)))
}
# Export the table to a new CSV
$Table | Sort 'Size (Bytes)' -Descending | Export-CSV -Path $TempLocation\$ExportedFilesCSV -NoTypeInformation -UseCulture
# Export the largest 100 results into html format
$Table |
Sort 'Size (Bytes)' -Descending |
Select -First 100 |
ConvertTo-Html -Property 'Name','Size (Bytes)','Size (KB)','Size (MB)','Size (GB)' -Head $style -Body "<h2>100 largest files on $env:COMPUTERNAME</h2>" -CssUri "http://www.w3schools.com/lib/w3.css" |
Out-String | Out-File $TempLocation\$ExportedFilesHTML
#endregion
#region Folders
# Remove the first 2 rows from the CSVs to leave just the relevant data
$CSVContent = Get-Content -Path $TempLocation\$FoldersCSV -ReadCount 0
$CSVContent = $CSVContent | Select -Skip 1
$CSVContent = $CSVContent | Select -Skip 1
# Create a table to store the results
$Table = [System.Data.DataTable]::new("Directory Structure")
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Name",[System.String]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (Bytes)",[System.Int64]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (KB)",[System.Decimal]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (MB)",[System.Decimal]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Size (GB)",[System.Decimal]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Files",[System.String]))
[void]$Table.Columns.Add([System.Data.DataColumn]::new("Folders",[System.String]))
# Populate the table from the CSV data
Foreach ($csvrow in $CSVContent)
{
$Content = $csvrow.split(',')
[void]$Table.rows.Add($($Content[0].Replace('"','')),$Content[2],([math]::Round(($Content[2] / 1KB),2)),([math]::Round(($Content[2] / 1MB),2)),([math]::Round(($Content[2] / 1GB),2)),$Content[5],$Content[6])
}
# Export the table to a new CSV
$Table | Sort 'Size (Bytes)' -Descending | Export-CSV -Path $TempLocation\$ExportedFoldersCSV -NoTypeInformation -UseCulture
# Export the largest 100 results into html format
$Table |
Sort 'Size (Bytes)' -Descending |
Select -First 100 |
ConvertTo-Html -Property 'Name','Size (Bytes)','Size (KB)','Size (MB)','Size (GB)','Files','Folders' -Head $style -Body "<h2>100 largest directories on $env:COMPUTERNAME</h2>" -CssUri "http://www.w3schools.com/lib/w3.css" |
Out-String | Out-File $TempLocation\$ExportedFoldersHTML
#endregion
#region Create HTML disk usage summary report
# Get system drive data
$WMIDiskInfo = Get-CimInstance -ClassName Win32_Volume -Property Capacity,FreeSpace,DriveLetter | Where {$_.DriveLetter -eq $env:SystemDrive} | Select Capacity,FreeSpace,DriveLetter
$DiskInfo = [pscustomobject]@{
DriveLetter = $WMIDiskInfo.DriveLetter
'Capacity (GB)' = [math]::Round(($WMIDiskInfo.Capacity / 1GB),2)
'FreeSpace (GB)' = [math]::Round(($WMIDiskInfo.FreeSpace / 1GB),2)
'UsedSpace (GB)' = [math]::Round((($WMIDiskInfo.Capacity / 1GB) - ($WMIDiskInfo.FreeSpace / 1GB)),2)
'Percent Free' = [math]::Round(($WMIDiskInfo.FreeSpace * 100 / $WMIDiskInfo.Capacity),2)
'Percent Used' = [math]::Round((($WMIDiskInfo.Capacity - $WMIDiskInfo.FreeSpace) * 100 / $WMIDiskInfo.Capacity),2)
}
# Create html header
$html = @"
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<body>
"@
# Set html
$html = $html + @"
<h2>Disk Space Usage for Drive $($DiskInfo.DriveLetter) on $env:COMPUTERNAME</h2>
<table cellpadding="0" cellspacing="0" width="700">
<tr>
<td style="background-color:$(Set-PercentageColour -Value $($DiskInfo.'Percent Used'));padding:10px;color:#ffffff;" width="$($DiskInfo.'Percent Used')%">
$($DiskInfo.'UsedSpace (GB)') GB ($($DiskInfo.'Percent Used') %)
</td>
<td style="background-color:#eeeeee;padding-top:10px;padding-bottom:10px;color:#333333;" width="$($DiskInfo.'Percent Used')%">
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" width="700">
<tr>
<td style="padding:5px;" width="80%">
Capacity: $($DiskInfo.'Capacity (GB)') GB
</td>
</tr>
<tr>
<td style="padding:5px;" width="80%">
FreeSpace: $($DiskInfo.'FreeSpace (GB)') GB
</td>
</tr>
<tr>
<td style="padding:5px;" width="80%">
Percent Free: $($DiskInfo.'Percent Free') %
</td>
</tr>
</table>
"@
If ($DiskInfo.'FreeSpace (GB)' -lt 20)
{
$html = $html + @"
<table cellpadding="0" cellspacing="0" width="700">
<tr>
<td style="padding:5px;color:red;font-weight:bold" width="80%">
You need to free $(20 - $DiskInfo.'FreeSpace (GB)') GB on this disk to pass the W10 readiness check!
</td>
</tr>
</table>
"@
}
# Close html document
$html = $html + @"
</body>
</html>
"@
# Export to file
$html |
Out-string |
Out-File $TempLocation\$SummaryHTMLReport
#endregion
#region Copy files to share
# Create a subfolder with computername if doesn't exist
If (!(Test-Path $TargetRoot\$env:COMPUTERNAME))
{
$null = New-Item -Path $TargetRoot -Name $env:COMPUTERNAME -ItemType Directory
}
# Create a subdirectory with current date-time
$DateString = ((Get-Date).ToUniversalTime() | get-date -Format "yyyy-MM-dd_HH-mm-ss").ToString()
If (!(Test-Path $TargetRoot\$env:COMPUTERNAME\$DateString))
{
$null = New-Item -Path $TargetRoot\$env:COMPUTERNAME -Name $DateString -ItemType Directory
}
# Set final target location
$TargetLocation = "$TargetRoot\$env:COMPUTERNAME\$DateString"
# Copy files
$Files = @(
$ExportedFilesCSV
$ExportedFoldersCSV
$ExportedFilesHTML
$ExportedFoldersHTML
$SummaryHTMLReport
)
Try
{
Robocopy $TempLocation $TargetLocation $Files /R:10 /W:5 /NP
}
Catch {}
#endregion
# Cleanup temp files
$Files = @(
$FilesCSV
$FoldersCSV
$ExportedFilesCSV
$ExportedFoldersCSV
$ExportedFilesHTML
$ExportedFoldersHTML
$SummaryHTMLReport
)
Foreach ($file in $files)
{
Remove-Item -Path $TempLocation\$file -Force
}
# Force a code 0 on exit, in case of some non-terminating error.
ExitWithCode 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment