Delete Inactive FSLogix Profiles using PowerShell

FSLogix has changed the game when it comes to profile management, in particular in the realms of Non-Persistent Desktops. We can now create Non-Persistent workloads and not have to worry about profiles, as a user logs on to a new desktop their respective FSLogix profile gets mounted to the desktop and their profile loads as if it were present locally on the desktop. Now that we have such a simple and effective solution to a long-running issue, there are only 2 questions that we need to answer for this solution; 1. How much space is required?; 2. Can the storage perform with the extra load imposed by FSLogix? It can become a potential IOPS issue.

In this post I will be addressing the first question and to be honest unless you are restricting the size that the FSLogix container can grow to it will depend very much on the user. There are a few things that you can implement, someone has created a PowerShell script which compacts the FSLogix profiles on a daily basis which slows down the growth, I won’t be going into this solution as it can be found on Google.

I have created a simple PowerShell script which will detect when the FSLogix profile was last used. If it was used 30(+) days ago, the script will delete the FSLogix profile as it is deemed inactive and is using up precious space on our storage solution, the script will then email the administrators to inform them which profiles have been deleted and how much space was recovered during the process.

Please see the script below:

# Import ActiveDirectory Module #
Import-Module ActiveDirectory
# Set Date Variables #
$EmailDate = (Get-Date).AddDays(-23)
$FormatDate = Get-Date -Format dd-MM-yyyy
$Date = (Get-Date).AddDays(-30)
# Set Current $ErrorActionPreference so that it can be put back to normal #
$old_ErrorActionPreference = $ErrorActionPreference
# Set $ErrorActionPreference to SilentlyContinue to bypass Get-ADComputer Errors #
$ErrorActionPreference = "SilentlyContinue"
# Import all VHD(X) files into $VHDs variable #
$VHDs = Get-ChildItem -Recurse -Path \\\CIFS\Lon\Win10Profiles\FSLogix | Where-Object {$_.Name -like "*.vhdx"} | Select Name,Length,FullName,CreationTime,LastWriteTime
# Run through the loop and report on the activity of the FSLogix profiles #
ForEach($VHD in $VHDs){ 
    If($VHD.LastWriteTime -lt $Date){
        $VHDLWT = Get-Date $VHD.LastWriteTime -Format "dd-MM-yyyy"
        $VHDCT = Get-Date $VHD.CreationTime -Format "dd-MM-yyyy"
        $Username = ($VHD.Name).Split('_')[1] | ForEach{$_.SubString(0,$_.length-5)}
        $Profile = ($VHD.Length | Measure-Object -Sum).Sum /1GB | Out-String
        $ProfileSize = $Profile | ForEach{$_.SubString(0,$_.Length-8)<#+"GB"#>}
        $UserDetails = Get-ADUser -Identity $Username -Properties DisplayName,Mail | Select SamAccountName,DisplayName,Mail -ErrorAction SilentlyContinue
        $Report = New-Object PSObject # Creates a Custom Report #
        $Report | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $UserDetails.DisplayName
        $Report | Add-Member -MemberType NoteProperty -Name "SamAccountName" -Value $UserDetails.SamAccountName
        $Report | Add-Member -MemberType NoteProperty -Name "Email" -Value $UserDetails.Mail
        $Report | Add-Member -MemberType NoteProperty -Name "ProfileName" -Value $VHD.Name
        $Report | Add-Member -MemberType NoteProperty -Name "ProfileSize(GB)" -Value $ProfileSize
        $Report | Add-Member -MemberType NoteProperty -Name "CreationTime" -Value $VHDCT
        $Report | Add-Member -MemberType NoteProperty -Name "LastWriteTime" -Value $VHDLWT
        $Report | Add-Member -MemberType NoteProperty -Name "ProfilePath" -Value $VHD.FullName
        $Report | Export-Csv -Append -NoTypeInformation ('C:\Masters\Scripts\Remove-InactiveFSLogixProfiles\Reports\Inactive_FSLogix_Profiles_Report_'+$FormatDate+'.csv')
        Remove-Item -Path $VHD.FullName -Force -Confirm:$false
# Calculate utilized space #
$csv = Import-Csv ('C:\Masters\Scripts\Remove-InactiveFSLogixProfiles\Reports\Inactive_FSLogix_Profiles_Report_'+$FormatDate+'.csv')
$TotalSize = (($csv | Measure-Object 'ProfileSize' -Sum).Sum).ToString($_)+"GB"
# Build Email #
$Recipient = ""
$Sender = ""
$SMTP = ""
$Subject = ('CCA-UK - FSLogix Inactive Profile Report for '+$FormatDate)
$Attachment = ('C:\Masters\Scripts\Remove-InactiveFSLogixProfiles\Reports\Inactive_FSLogix_Profiles_Report_'+$FormatDate+'.csv')
$Body = 
('To Administrator,

Attached, please find the Inactive FSLogix Profiles Report for '+$FormatDate+'. This report contains a list of FSLogix Profiles that have not been accessed for 30 or more days, they should be targeted for deletion.

Currently, these inactive profiles are using '+$TotalSize+' of space.


EUC Engineering')
Send-MailMessage -To $Recipient -From $Sender -Subject $Subject -Body $Body -Attachments $Attachment -SmtpServer $SMTP
# Set Original $ErrorActionPreference back to normal #
$ErrorActionPreference = $old_ErrorActionPreference

This will output an email to your chosen administrators which will look like:

The attached CSV will look something like this:

I understand that it isn’t always simple to agree a flat-out deletion of profiles in most business’ but if you can make a case to get something like this in place it will save you an administrative headache further down the line.

I hope this is useful

Thanks for reading and take care!

Callan Halls-Palmer

*If you want the source code please email me*

10 thoughts on “Delete Inactive FSLogix Profiles using PowerShell

  1. Dear, I liked your script but it is not giving the first 3 details like givenname, email, sam in the report.
    Acutally variable Username is not resolving.


    1. Apologies, this could be because in my example my Fslogix VHDs append the SID to the name, so when the $Username variable is declared it takes that into consideration. Can you give me an example of your vhd naming scheme?


      1. I’m in the same situation as Bharat Gulati: my file names are “Profile_Username.vhdx”. How can we exclude the SID out of the $username variable? Thanks!


  2. I like the work you have put into this script, very thoughtful, capturing all the data that an admin would want to know. However, I find no place where it is removing the file. Did that line get removed by accident?

    Liked by 1 person

    1. Hi Tom, That’s a good spot.. the trouble is I have a staging area that I use to generalize these scripts and I seem to have missed off the removal.. I have amended this now and added to the script.. Thanks 🙂


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s