Cleanup unused FSLogix Office 365 Containers

It’s this time of the year again: Our graduate students left and the new ones started. As every year we have to do some housekeeping on our file servers to cleanup the unused home directories and user profiles of the students who left our school. With the implementation of FSLogix Office 365 Containers there is now a third piece of user related data we have to take into account. Here is how to accomplish this task with a simple Powershell script.

It’s this time of the year again: Our graduate students left and the new ones started. As every year we have to do some housekeeping on our file servers to cleanup the unused home directories and user profiles of the students who left our school. With the implementation of FSLogix Office 365 Containers there is now a third piece of user related data we have to take into account. Here is how to accomplish this task with a simple Powershell script.

To cleanup the orphaned home directories and profiles we already have a small Powershell script. The script does parse the file share and compares every folder name against the active directory to determine if there is still a user account. If no corresponding user is found, the directory is moved to a decommission folder or share from where we can archive or delete the content. It’s a simple script but works great for us – there’s only one caveat: the folder names of the home directories and profiles have to match the user’s active directory sAMAccountName.

By default FSLogix stores the container files (VHD / VHDX) in a new folder whose name begins with the user’s SID followed by an underscore and the sAMAccountName in the location specified in VHDLocations.

S-1-5-21-2887591454-600243807-2941061327-15115_testuser

Setting the registry key FlipFlopProfileDirectoryName to ‘1’ changes this behavior and the SID folder is created as “%username%_%sid%” instead of the default “%sid%_%username%”.

There’s also a way to customize the naming by specifying a string pattern used to create and match (find) the SID directory in the registry keys SIDDirNamePattern and SIDDirNameMatch. Variable names are delimited with ‘%’ characters. Supported variables are

%username%, %userdomain%, %sid%, %osmajor%, %osminor%, %osbuild%, %osservicepack%, %profileversion%, %clientname%, and any environment variable.

If you prefer to apply those customization settings through GPOs, FSLogix has you covered with the latest admx templates too.

fslogix_admx
FSLogix GPO to set VHD name matching sting and VHD name pattern string

Well since our SID directories last from the days before customizing the SID directory names, we had to extract the sAMAccountName from the directory name. Big thanks to fellow CitrixCTA Martin Zugec, who helped me with the correct syntax of the corresponding LDAP filter!

(sAMAccountName=$($folder.Name.split(‘_’)[1]))

This filter splits the string containing the folder name into two separate variables (separated by the underscore) and uses only the second variable to match with the sAMAccountName. If your folders are in the %username%_%sid% format you simply can use the first value of the array by using

(sAMAccountName=$($folder.Name.split(‘_’)[0]))

Here is the source code of the script we use. Set $ODFCShareSource to the directory you want to scan for unused folders and $ODFCShareDestination to the path where you want the script to move those directory not in use anymore. Line 12 is where you want to customize your LDAP filter. To use the full directory name, for example to check your home and profile directories, where the folder name matches the sAMAccountName you can use the following LDAP filter.

(sAMAccountName=$folder)

import-module ActiveDirectory

$ODFCShareSource = "\\MyServer\SourceShare"
$ODFCShareDestination = "\\MyServer\DestinationShare"
$UnusedDirMoveLogPath = "C:\UnusedHomeDirMove_log.txt"
$OutPutErrorLogPath = "C:\UnusedHomeDirMove_OutputErrors_log.txt"

$folders = Get-ChildItem $ODFCShareSource

ForEach ($folder in $folders)
{
    $User = Get-ADUser -LDAPFilter "(sAMAccountName=$($folder.Name.split('_')[1]))"
    If ($User -eq $Null)
    {
        $ODFCDir = $ODFCShareSource+"\"+$folder
        $ODFCShareDestinationDir = $ODFCShareDestination+"\"+$folder
        $ErrorActionPreference = "Stop"
        Try
        {
            Copy-Item -Recurse $ODFCDir $ODFCShareDestinationDir -Force
        }
        Catch
        {
            "--- ERROR" | Out-File $OutPutErrorLogPath -Append
            "$folder" | Out-File $OutPutErrorLogPath -Append
             $_ | Out-File $OutPutErrorLogPath -Append
            "---------" | Out-File $OutPutErrorLogPath -Append
        }
            if ((Test-Path -path $ODFCShareDestinationDir) -eq $True)
            {
                $ErrorActionPreference = "Stop"
                Try
                {
                    cmd.exe /c RD /S /Q $ODFCDir
                        if ((Test-Path -path $HomeDir) -eq $True)
                        {
                            Start-Sleep -s 10
                            cmd.exe /c RD /S /Q $ODFCDir
                        }
                }
                Catch
                {
                    "--- ERROR" | Out-File $OutPutErrorLogPath -Append
                    "$folder" | Out-File $OutPutErrorLogPath -Append
                    $_ | Out-File $OutPutErrorLogPath -Append
                    "---------" | Out-File $OutPutErrorLogPath -Append
                }
            }
         if ((Test-Path -path $ODFCDir) -eq $False)
         {
             if ((Test-Path -path $ODFCShareDestinationDir) -eq $False)
             {
                $LogEntryDate = Get-Date –Format G
                Add-Content -Path $UnusedDirMoveLogPath -Value "--- ERROR"
                Add-Content -Path $UnusedDirMoveLogPath -Value "$LogEntryDate"
                Add-Content -Path $UnusedDirMoveLogPath -Value "$folder"
                Add-Content -Path $UnusedDirMoveLogPath -Value "Folder did not move correctly"
             }
             Else
             {
                $LogEntryDate = Get-Date –Format G
                Add-Content -Path $UnusedDirMoveLogPath -Value "--- OK"
                Add-Content -Path $UnusedDirMoveLogPath -Value "$LogEntryDate"
                Add-Content -Path $UnusedDirMoveLogPath -Value "$folder"
                Add-Content -Path $UnusedDirMoveLogPath -Value "Folder was moved correctly"
             }
         }
         Else
         {
            $LogEntryDate = Get-Date –Format G
            Add-Content -Path $UnusedDirMoveLogPath -Value "--- ERROR"
            Add-Content -Path $UnusedDirMoveLogPath -Value "$LogEntryDate"
            Add-Content -Path $UnusedDirMoveLogPath -Value "$folder"
            Add-Content -Path $UnusedDirMoveLogPath -Value "Folder did not move correctly"
         }
    }
}

7 thoughts on “Cleanup unused FSLogix Office 365 Containers”

  1. Thanks for this script. Saved me a headache writing similar from scratch. A neat script and a timesaver! Much appreciated.

    I have a suggestion, which likely since time passed after posting might have already been iterated on your end.

    Powershell 3.0+

    Change:
    $folders = Get-ChildItem $ODFCShareSource
    To:
    $folders = Get-ChildItem $ODFCShareSource -Directory

    Change:
    if ((Test-Path -path $HomeDir) -eq $True)
    To:
    if ((Test-Path -path $ODFCDir) -eq $True)

    Once again, big thanks! 🙂

    Like

Leave a comment