Get an overview of user profile folder sizes with Powershell

In particular on a terminal server it is important to keep the sizes of user profiles under control. This can be a rather challenging task. Although you can use disk quota to prevent a user profile from taking too much disk space on a server there still can arise some problems. For example if a user runs out of his disk space he might be unable to log onto the terminal server the next time.

Another problem could be controlling all temporary and update files a user unknowingly leaves behind in his profile. A lot can be done by using group policies but it still might be important to inspect the profiles from time to time and to find out which folders and files cause excessive disk space use.

The Explorer of all Windows versions up to date does a very poor job in providing you with information on folder sizes. On the internet you can find the excellent tool GetFolderSize and what’s more: it’s free.. The problem with all tools you can find on the internet is that you should be of course very – very very! - reluctant to install any of them on a corporate network, let alone on a corporate server. Although it can be very tempting I must admit, especially when you spend hours - like I did - trying to find the right tool within the Windows server OS itself or on Microsoft web sites.

Powershell gives you the possibility to get a nice overview of folder sizes without having to install any third-party tools. I must admit it is very primitive in comparison to GetFolderSize. Also it is slower in getting the result. But it does get you the information you need in the end.

Powershell knows the cmdlet Measure-Object which gives you the possibility to get folder size. In this script the information per user is saved in a custom object to be able to sort a whole list of user profiles.


#    NAME:    GetProfilesize.ps1
#    PURPOSE: Show an overview of various foldersizes in the user profiles on a machine. 

$ErrAction = "SilentlyContinue"

$rootPath = "C:\Users\" #This could also be a network path e.g. "\\terminalserver\c$\users"

$colProfileSizes = @()

$ProfSubfolder = @()
$ProfSubfolder += @{
                   SubPath="\AppData\Local\Microsoft\Windows\Temporary Internet Files\"
                   Size = 0
$ProfSubfolder +=  @{Name="Desktop"
$ProfSubfolder += @{Name="Appdata"
#You could add more subfolders here the same way as above. Then also add an extra line to format$
$ProfileSizes = @{FullName=""
$ProfileSizes = New-Object PSObject -Property $ProfileSizes

for ($i=0; $i -lt $ProfSubfolder.length; $i++) {
    $ProfileSizes | Add-Member -type NoteProperty -name $ProfSubfolder[$i].Name `
                                                                     -value $ProfSubfolder[$i].Size -force

$colUserProfiles = Get-ChildItem $rootPath |Where {($_.psIsContainer -eq $true)}

foreach ($UserProfile in $colUserProfiles)
     $colItems = (Get-ChildItem -recurse $UserProfile.FullName -force -ErrorAction $ErrAction |
                                               Measure-Object -property length -sum -ErrorVariable errors `
                                                                                   -ErrorAction $ErrAction)
     $ProfileSizes.FullName = $UserProfile.FullName
     $ProfileSizes.TotalSize = $colItems.sum
     for ($i=0; $i -lt $ProfSubfolder.length; $i++) {
        $colItems = Get-ChildItem -recurse ($UserProfile.FullName + $ProfSubfolder[$i].SubPath) `
                 -force -ErrorAction $ErrAction | 
                         Measure-Object -property length -sum -ErrorVariable errors  -ErrorAction $ErrAction  
        $ProfileSizes.($ProfSubfolder[$i].Name) = $colItems.sum        
     $ProfileSizes | ft
     $colProfileSizes += $ProfileSizes
     $ProfileSizes = $ProfileSizes.PSObject.Copy()

$format = 
    @{Expression={$_.FullName};Label="Path Profile";width=40},
    @{Expression={"{0:N2}" -f ($_.TotalSize / 1MB)};Label="TotalSize(KB)";align="right";width=10}
$format +=  @{Expression={"{0:N2}" -f ($_.($ProfSubfolder[0].Name)/ 1KB)};
                                Label= $ProfSubfolder[0].Name;align="right";width=10}
$format +=  @{Expression={"{0:N2}" -f ($_.($ProfSubfolder[1].Name)/ 1KB)};
                                Label= $ProfSubfolder[1].Name;align="right";width=10}
$format +=  @{Expression={"{0:N2}" -f ($_.($ProfSubfolder[2].Name)/ 1KB)};
                                Label= $ProfSubfolder[2].Name;align="right";width=10}
$colProfileSizes | Sort-Object TotalSize -descending | ft $format -autosize