#Requires -Version 5
#Requires -RunAsAdministrator
#Requires -Module Hyper-V
<#
Written by David Ott
I stole some code from www.thesurlyadmin.com (set-alternatingrows function)
This script will compact FSLogix VHD/VHDX profiles in the profile share. It would also work for
any directory containing VHD/VHDX files.
Test before using!!
Search for "#####" to find the sections you need to edit for your environment
#>
Function Set-AlternatingRows {
[CmdletBinding()]
Param(
[Parameter(Mandatory,ValueFromPipeline)]
[string]$Line,
[Parameter(Mandatory)]
[string]$CSSEvenClass,
[Parameter(Mandatory)]
[string]$CSSOddClass
)
Begin {
$ClassName = $CSSEvenClass
}
Process {
If ($Line.Contains("
| "))
{ $Line = $Line.Replace(" |
","
")
If ($ClassName -eq $CSSEvenClass)
{ $ClassName = $CSSOddClass
}
Else
{ $ClassName = $CSSEvenClass
}
}
Return $Line
}
}
function checkFileStatus($filePath)
{
$fileInfo = New-Object System.IO.FileInfo $filePath
try
{
$fileStream = $fileInfo.Open( [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read )
$filestream.Close()
return $false
}
catch
{
return $true
}
}
function vhdmount($v) {
try {
Mount-VHD -Path $v -ReadOnly -ErrorAction Stop
return "0"
} catch {
return "1"
}
}
function vhdoptimize($v) {
$i = "0"
$o = [math]::Round((gi $v | select -expand length)/1mb,2)
try {
Optimize-VHD $v -Mode Full -ErrorAction stop
$r = 0
} catch {
$r = 1
}
$n = [math]::Round((gi $v | select -expand length)/1mb,2)
$dif = [math]::Round(($o-$n),2)
$i | select @{n='VHD';e={Split-Path $v -Leaf}},@{n='Before_MB';e={$o}},@{n='After_MB';e={$n}},@{n='Reduction_MB';e={$dif}},@{n='Success';e={if ($r -eq "0"){$true} else {$false}}},@{n='VHD_Fullname';e={$v}}
}
function vhddismount($v) {
try {
Dismount-VHD $v -ErrorAction stop
return "0"
} catch {
return "1"
}
}
$smtpserver = "smtpserver.fqdn" ##### SMTP Server
$to = "your email address" ##### email report to - "email1","email2" for multiple
$from = "fslogixreport@yourcompany.com" ##### email from
$rootfolder = "\\server\profile_share" ##### root path to vhd(x) files
$vhds = (gci $rootfolder -recurse -Include *.vhd,*.vhdx).fullname
[System.Collections.ArrayList]$info = @()
$t = 0
foreach ($vhd in $vhds) {
$locked = checkFileStatus -filePath $vhd
if ($locked -eq $true) {
"$vhd in use, skipping."
$info.add(($t | select @{n='VHD';e={Split-Path $vhd -Leaf}},@{n='Before_MB';e={0}},@{n='After_MB';e={0}},@{n='Reduction_MB';e={0}},@{n='Success';e={"Locked"}},@{n='VHD_Fullname';e={$vhd}})) | Out-Null
continue
}
$mount = vhdmount -v $vhd
if ($mount -eq "1") {
$e = "Mounting $vhd failed "+(get-date).ToString()
Send-MailMessage -SmtpServer $smtpserver -From $from -To $to -Subject "FSLogix VHD(X) ERROR" -Body "$e" -Priority High -BodyAsHtml
break
}
$info.add((vhdoptimize -v $vhd)) | Out-Null
$dismount = vhddismount -v $vhd
if ($dismount -eq "1") {
$e = "Failed to dismount $vhd "+(get-date).ToString()
Send-MailMessage -SmtpServer $smtpserver -From $from -To $to -Subject "FSLogix VHD(X) ERROR" -Body "$e" -Priority High -BodyAsHtml
break
}
}
$Header = @"
"@
$date = Get-Date
$timestamp = get-date $date -f MMddyyyyHHmmss
##### uncomment the next 2 lines if you would like to save a .htm report (also 2 more at the end)
#$out = Join-Path ([environment]::GetFolderPath("mydocuments")) ("FSLogix_Reports\VHD_Reduction_Report_$timestamp.htm")
#if (!(test-path (Split-Path $out -Parent))) {New-Item -Path (Split-Path $out -Parent) -ItemType Directory -Force | Out-Null}
$before = ($info.before_mb | measure -Sum).Sum
$after = ($info.after_mb | measure -Sum).Sum
$reductionmb = ($info.reduction_mb | measure -Sum).sum
$message = $info | sort After_MB -Descending | ConvertTo-Html -Head $header -Title "FSLogix VHD(X) Reduction Report" -PreContent "FSLogix VHD(X) Reduction Report
" -PostContent "
Pre-optimization Total MB: $before
Post-optimization Total MB: $after
Total Reduction MB: $reductionmb
"| Set-AlternatingRows -CSSEvenClass even -CSSOddClass odd
##### comment the next line if you do not wish the report to be emailed
Send-MailMessage -SmtpServer $smtpserver -From $from -To $to -Subject ("FSLogix VHD(X) Reduction Report "+($date).ToString()) -Body "$message" -BodyAsHtml
##### uncomment the next 2 lines to save the report to your My Documents\FSLogix_Reports directory, and open it in your default browser
#$message | Out-File $out
#Invoke-Item $out