28 February 2024 : Script is updated with extra option to only delete Office cache container.
When you have a share with FSLogix containers you probably want to keep this in sync with you active directory. Users who are deleted, inactive or disabled can still claim space on the file server. This script will read all container folders and match them against the active directory useraccounts and delete the containers if needed.
All information is in the script. Have fun with it and leave a comment when using or when having issues.
Keep in mind, I’m not a scripter/devver 😉 So the script can be shorter/smarter but this works either. I’m not responsable for any damage or deleted containers 😉 Usage of the script is your own responsability.
<#
.SYNOPSIS
This script checks the path where FSLogix containers are stored.
For each folder it will check the active directory for the status of the specific useraccount.
The following checks will be performed:
1. Does the user still exists?
2. Is the user disabled?
3. What is the last logon date?
There are a couple of variables to set to tune the script for your needs:
1. $FSLogixPath : The location where the containers are stored.
2. $ExcludeFolders : Is the location has folders which must not be processed you can add them here.
3. $DaysInactive : Minimum amount of days when the last logon occured.
4. $DeleteDisabled : Set this to 0 or 1. 0 will NOT delete conainters from disabled user accounts. 1 will ;)
5. $DeleteNotExisting : When an user is deleted and the conainers aren't deleted set this to 1 and the containers will be deleted.
6. $DeleteInactive : Users with a last logon longer the the $DaysInactive will be deleted if this is set to 1.
7. $OnlyDeleteODFC : Only the Office cache container will be deleted. Keeping the Profile container.
8. $FlipFlopEnabled : Set this to 0 when the containers are stored in a folder starting with the user SID.
When the folder starts with the username set this to 1.
9. $ShowTable : Set this to 1 to show a table at the end of the script.
10. $DryRun : When this is set to 1, nothing will be deleted regardless the settings.
This will also output more information which containers are claiming space.
.DESCRIPTION
Can automatically cleanup FSLogix containers if they match the criteria. This will reduce the used space.
.NOTES
Version : 1.4
Date : 28 February 2024
Created by : Jeroen Tielen - Tielen Consultancy B.V.
Email : jeroen@tielenconsultancy.nl
History:
1.0 : 12 June 2022 - Initial setup script;
1.1 : 13 March 2023 - Add FlipFlop Switch;
1.2 : 19 March 2023 - Added beter layout;
1.3 : 21 March 2023 - Added table option;
1.4 : 28 February 2024 - Added only deleting Office Cache.
#>
# Tune this variables to your needs
$FSLogixPath = "\\NUTANIX_FILES\UserProfiles" # Set FSLogix containers path.
[string[]]$ExcludeFolders = @('FSLogix_Redirections', 'Template') # Excluded directories from the FSLogix containers path.
$DaysInactive = 90 # Days of inactivity before FSLogix containers are removed.
$DeleteDisabled = 0 # Delete containers from disabled users.
$DeleteNotExisting = 0 # Delete containers from not existing users.
$DeleteInactive = 1 # Delete containers from inactive users.
$OnlyDeleteODFC = 1 # When this is 1 only the office cache container will be deleted and not the profile container.
$FlipFlopEnabled = 1 # When 1 the default naming convention of the folders is used.
$ShowTable = 1 # Show table at the end of the script.
$DryRun = 1 # Override switch, nothing will be deleted, script will also output user names and what will be deleted.
# Script Start
$PotentialSpaceReclamation = 0
$SpaceReclaimed = 0
$SpaceDisabled = 0
$SpaceNotExisting = 0
$SpaceInactive = 0
$Counter = 0
$UsersTable = @()
If ($DryRun -eq 1) { Write-Host "!! DryRun Active, nothing will be deleted !!" -ForegroundColor Green -BackgroundColor Blue } Else {
Write-Host "!! DryRun NOT Active, containers will be deleted !!" -ForegroundColor Red -BackgroundColor White
Write-Host -nonewline "Continue? (Y/N) "
$Response = Read-Host
If ($Response -ne "Y") { EXIT }
}
$PathItems = Get-ChildItem -Path "$($FSLogixPath)" -Directory -Exclude $ExcludeFolders
Foreach ($PathItem in $PathItems) {
If ($FlipFlopEnabled -eq 1) { $UserName = $PathItem.Name.Substring(0, $PathItem.Name.IndexOf('_S-1-5')) }
If ($FlipFlopEnabled -eq 0) { $UserName = $PathItem.Name.Substring($PathItem.Name.IndexOf('_') + 1) }
$Counter ++
Try {
$Information = Get-ADUser -Identity $UserName -Properties sAMAccountName, Enabled, lastLogon, lastLogonDate
If ($False -eq $Information.Enabled) {
$UserSpace = (Get-ChildItem -Path "$PathItem" | Measure Length -Sum).Sum / 1Gb
$UsersTable += (@{UserName="$UserName";State="Disabled";SpaceinGB="$UserSpace"})
If ($DryRun -eq 1) { Write-host "User $UserName is disabled. Dryrun activated, nothing will be deleted." -ForegroundColor Green }
$PotentialSpaceReclamation = $PotentialSpaceReclamation + $UserSpace
$SpaceDisabled = $SpaceDisabled + $UserSpace
# Deleting Disabled Users.
If ($DeleteDisabled -eq 1) {
If ($DryRun -eq 0) {
If ($OnlyDeleteODFC -eq 1) {
Write-Host "Deleting only ODFC container from $UserName" -ForegroundColor Red
$SpaceReclaimed = $SpaceReclaimed + $UserSpace
$DeleteFile = $PathItem.FullName + "\ODFC*.*"
Remove-Item -Path $DeleteFile -Force
} Else {
Write-Host "Deleting containers from $UserName" -ForegroundColor Red
$SpaceReclaimed = $SpaceReclaimed + $UserSpace
Remove-Item -Path $PathItem -Recurse -Force
}
}
}
# Deleting Inactive Users
ElseIf ($Information.lastLogonDate -lt ((Get-Date).Adddays( - ($DaysInactive)))) {
$UserSpace = (Get-ChildItem -Path "$PathItem" | Measure Length -Sum).Sum / 1Gb
$UsersTable += (@{UserName="$UserName";State="Inactive";SpaceinGB="$UserSpace"})
If ($DryRun -eq 1) { Write-Host "User $UserName is more than $DaysInactive days inactive. Dryrun activated, nothing will be deleted." -ForegroundColor Green }
$PotentialSpaceReclamation = $PotentialSpaceReclamation + $UserSpace
$SpaceInactive = $SpaceInactive + $UserSpace
If ($DeleteInactive -eq 1) {
If ($DryRun -eq 0) {
If ($OnlyDeleteODFC -eq 1) {
Write-Host "Deleting only ODFC container from $UserName" -ForegroundColor Red
$SpaceReclaimed = $SpaceReclaimed + $UserSpace
$DeleteFile = $PathItem.FullName + "\ODFC*.*"
Remove-Item -Path $DeleteFile -Force
} Else {
Write-Host "Deleting containers from $UserName" -ForegroundColor Red
$SpaceReclaimed = $SpaceReclaimed + $UserSpace
Remove-Item -Path $PathItem -Recurse -Force
}
}
}
}
}
}
# Non Existing Users in AD.
Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
$UserSpace = (Get-ChildItem -Path "$PathItem" | Measure Length -Sum).Sum / 1Gb
$UsersTable += (@{UserName="$UserName";State="DoesntExist";SpaceinGB="$UserSpace"})
If ($DryRun -eq 1) { Write-Host "User $UserName doesn't exist. Dryrun activated, nothing will be deleted." -ForegroundColor Green }
$PotentialSpaceReclamation = $PotentialSpaceReclamation + $UserSpace
$SpaceNotExisting = $SpaceNotExisting + $UserSpace
If ($DeleteNotExisting -eq 1) {
If ($DryRun -eq 0) {
If ($OnlyDeleteODFC -eq 1) {
Write-Host "Deleting only ODFC container from $UserName" -ForegroundColor Red
$SpaceReclaimed = $SpaceReclaimed + $UserSpace
$DeleteFile = $PathItem.FullName + "\ODFC*.*"
Remove-Item -Path $DeleteFile -Force
} Else {
Write-Host "Deleting containers from $UserName" -ForegroundColor Red
$SpaceReclaimed = $SpaceReclaimed + $UserSpace
Remove-Item -Path $PathItem -Recurse -Force
}
}
}
}
}
$PotentialSpaceReclamation = "{0:N2} GB" -f $PotentialSpaceReclamation
$SpaceReclaimed = "{0:N2} GB" -f $SpaceReclaimed
$SpaceDisabled = "{0:N2} GB" -f $SpaceDisabled
$SpaceNotExisting = "{0:N2} GB" -f $SpaceNotExisting
$SpaceInactive = "{0:N2} GB" -f $SpaceInactive
Write-Host ""
If ($ShowTable -eq 1) {
Write-Host "========================================="
$UsersTable | ForEach {[PSCustomObject]$_} | Format-Table UserName,State,SpaceinGB
}
Write-Host "========================================="
Write-Host "Processed Container Folderss:"$Counter
If ($DryRun -eq 1) { Write-Host "Potential $PotentialSpaceReclamation can be reclaimed." }
Write-Host "Disabled users are claiming $SpaceDisabled"
Write-Host "Not Existing users are claiming $SpaceNotExisting"
Write-Host "Inactive users are claiming $SpaceInactive"
Write-Host "$SpaceReclaimed total reclaimed."
Hi Jeroen,
Thank you for this script. We are not using FSLogix Flip Flop, but I can’t figure out what to change about the script to make it work. Could you help me with this?
Kind regards,
Joep
Ahh you are the one in a thousand which is not using flip flop 😉 You need to change the script so it reads the username from the last part of the foldername. I never ever use that kind of naming convention as it is not easy to find the user his profile.
Thanks for the inspiration! Did not exactly use yours but served as a great basis to develop my own. Should it help you, you can find it here! I built a flipflop switch into it as well.
https://github.com/tompatta/PowerShell/tree/main/FSLogix%20Cleanup
Ahh lovely Tom. That is community power. Thanks for sharing.
This script looks amazing and exactly what I have been trying to build myself. When I try and run it in my environment I am getting the following error:
Exception calling “Substring” with “2” argument(s): “Length cannot be less than zero.
Parameter name: length”
At line:58 char:5
+ $UserName = $pathItem.Name.Substring(0, $PathItem.Name.IndexOf(‘_ …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException
Get-ADUser : Cannot validate argument on parameter ‘Identity’. The argument is null. Provide a valid value for the argument, and then try running the command again.
At line:60 char:45
+ $Information = Get-ADUser -Identity $UserName -Properties sAM …
+ ~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-ADUser], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADUser
in my case there were folders in the fslogix directory that did not have and underscore in it and were not added to the exclusions part of the script.
OMG! You are great hero. Thank you for this script. This saves a lot of time and makes life simple :).
You are welcome