Clear Stuck FSLogix Profiles from Azure FileShare

 
param (
    [string]$Username = ""
)
 
$StorageAccountName = "XXXXXXX"
$SharesToCheck = @("fslogix-profiles", "fslogix-o365")
 
Write-Host "=== FSLogix Stuck Handle Cleanup Tool ===`n" -ForegroundColor Cyan
 
if (-not $Username) {
    $Username = Read-Host "Enter username (e.g. nwaiki)"
}
 
$UserPattern = "*$Username*"
 
Write-Host "Searching for handles for user: $Username" -ForegroundColor Yellow
 
# Get Storage Key
$StorageAccountKey = Read-Host "Enter Storage Account Key" -AsSecureString
$KeyPlain = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($StorageAccountKey))
 
$Context = New-AzStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $KeyPlain
 
$TotalClosed = 0
 
foreach ($ShareName in $SharesToCheck) {
    Write-Host "`nChecking share: $ShareName ..." -ForegroundColor Yellow
    $Handles = Get-AzStorageFileHandle -ShareName $ShareName -Recursive -Context $Context | 
               Where-Object { $_.Path -like $UserPattern }
    if ($Handles.Count -gt 0) {
        Write-Host "Found $($Handles.Count) handle(s)" -ForegroundColor Red
        $Handles | Format-Table ClientIP, OpenTime, Path, HandleId -AutoSize
        $Confirm = Read-Host "Close ALL handles for $Username in $ShareName? (YES)"
        if ($Confirm -eq "YES") {
            foreach ($h in $Handles) {
                Write-Host "Closing: $($h.Path)" -ForegroundColor Yellow
                Close-AzStorageFileHandle -ShareName $ShareName -Path $h.Path -CloseAll -Context $Context -Verbose
                $TotalClosed++
            }
            Write-Host "Handles closed in $ShareName" -ForegroundColor Green
        }
    } else {
        Write-Host "No handles found in $ShareName" -ForegroundColor Green
    }
}
 
Write-Host "`n=== Finished! Total handles closed: $TotalClosed ===" -ForegroundColor Cyan
(No Ratings Yet)