Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Get Disk Quota

Posted on November 23, 2009October 27, 2014

During a recent class I was teaching, a student asked about a way to get disk quota reports from Windows file servers.  I knew there was a WMI class, Win32_DiskQuota, and had some old VBScript files. However, they were pretty basic and not as robust as I would have liked. So I worked up PowerShell v2 function called Get-DiskQuota.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

The function includes parameter help, as so almost all of my v2 scripts, so that  you can get help and examples.

captured_Image.png

The function takes a computername as a parameter, although it defaults to the local computer. You can retrieve quota information for all volumes and users on the server, or only for a particular volume and/or user. Because the function uses WMI, it also supports PSCredentials. Here’s a sample using an alias, gdq, for the Get-DiskQuota function.

PS C:\> gdq -Computername jdhit-dc01 -Volume e: -credential $jdhit

Volume           : E:
Computername     : JDHIT-DC01
Username         : jdhitsolutions\jhicks
UsedSpaceMB      : 73.228515625
PercentUsed      : 1.43 %
LimitGB          : 5
LimitRemainingGB : 4.93
WarningGB        : 3
OverWarning      : False
OverLimit        : False

The PSCredential must be passed as an object. I created the $jdhit object earlier with Get-Credential.

Here’s the code for you to look at and then I’ll go over a few key steps.

Function Get-DiskQuota {
#Requires -version 2.0

<#
.Synopsis
    Retrieve quota usage information for all users or a user from all volumes on a server or a single volume.
.Description
    This function connects to the specified computer, default is the localhost, and returns quota
    usage information. Quota information will NOT be returned for the Domain Admins group or the 
    Administrator account. It will also exclude entries without a quota limit. Quota information for
    all volumes is returned by default. Otherwise you can filter by volume, by user or by volume
    and user. The Domain parameter is used to more accurately define the user account. If you want
    to filter by domain alone, then run the function without any user filtering and pipe it to 
    Where-Object where you can filter by the domain name.
    
    This function uses WMI so you must have RPC connectivity and appropriate credentials. You do
    not need PowerShell installed on the remote computer.
    
.Parameter Computername
    The name of the computer to query.
.Parameter Volume
    Return quota information for a specific volume on the remote server such as E:.
.Parameter Username
    Return quota information for a specific user. Use the SAMAccountname.
.Parameter Domain
    The NETBIOS domain name of the user account you are querying. The default is the domain of the
    current user running the function.  
.Parameter Credential
    A PSCredential object to use for alternate credential authentication. This must be a previously
    created object.

.Example
    PS C:\> get-diskquota server02
    
    Get quota usage for all users on all volumes on SERVER02.
.Example
    PS C:\> get-diskquota server01 -volume F: -cred $admin
    
    In this example, quota information for all users on volume F: is returned. The query is made
    using alternate credentials, previously saved as $admin.

.Example
    PS C:\> get-diskquota "File01","File02" -user jfrost -domain MyCompany
    
    Query servers File01 and File02 for all quota entries for user mycompany\jfrost on all volumes.
    
.Example
    PS C:\> get-content servers.txt | get-diskquota -user Jhicks | Export-csv jhicks-quota.csv
    
    This example will take every server name in servers.txt and pipe it to the Get-Diskquota function
    which searches all volumes for the jhicks user account. The quota usage information is then piped
    to a CSV file using Export-CSV.
    
.Inputs
    Accepts strings as pipelined input
.Outputs
    A custom object with quota entry information  

.Link
https://jdhitsolutions.com/blog/2009/11/get-disk-quota/
           
.Link
   Get-WmiObject
         
.Notes
 NAME:      Get-DiskQuota
 VERSION:   1.1
 AUTHOR:    Jeffery Hicks
 LASTEDIT:  12/8/2009


#>

[CmdletBinding()]

Param (
    [Parameter(
    ValueFromPipeline=$True, Position=0, Mandatory=$False,
    HelpMessage="The computername to query")] 
    [string[]]$Computername=$env:computername,
    
    [Parameter(
    ValueFromPipeline=$False,Mandatory=$False,
    HelpMessage="The volume name on the remote server. Use a value like E:.")] 
    [string]$Volume,
    
    [Parameter(
    ValueFromPipeline=$False,Mandatory=$False,
    HelpMessage="The samAccountname of a user such as JDOE")] 
    [string]$Username,
    
    [Parameter(
    ValueFromPipeline=$False,Mandatory=$False,
    HelpMessage="The domain name of the queried user such as MyCompany")] 
    [string]$Domain=$env:Userdomain,
    
    [Parameter(
    ValueFromPipeline=$False,
    Mandatory=$False,
    HelpMessage="A previously created PSCredential object.")] 
    [Parameter(ParameterSetName="Set2")] 
    [management.automation.pscredential]$credential
     
    ) #end Parameter declaration


    BEGIN {
        Write-Verbose "Starting function"
        
        if ($Username) { Write-Verbose "Looking for entries for $domain\$username"}
               
          #only retrieve quota entries that are limited
          $query="Select * from win32_diskquota where limit < 18446744073709551615"
        
        if ($Volume -AND $Username) {
            Write-Verbose "Building volume and username query"
            $query=$query + " AND QuotaVolume=""Win32_LogicalDisk.DeviceID='$volume'"" AND User =""Win32_Account.Domain='$domain',Name='$Username'"""
        }
        elseif ($Volume) {
            Write-Verbose "Building volume filter query"
             $query=$query + " AND QuotaVolume=""Win32_LogicalDisk.DeviceID='$volume'"""
        }
        elseif ($Username) {
            Write-Verbose "Building username filter query"
            $query=$query + " AND User =""Win32_Account.Domain='$domain',Name='$Username'"""
        }
        else {
            Write-Verbose "Getting all quota entries"
        }
        
        Write-Verbose "Query = $query"
    } #end BEGIN

    PROCESS {
    
        
        $Computername | foreach {    
        
        
            #define an error handling trap in the same scope
            Trap {
                Write-Warning "There was an exception retrieving quota information from $computer)"
                Write-Warning $_.Exception.Message
                #bail out
                Return
            }
           
            $computer=$_.ToUpper()
            Write-Verbose "Querying $computer"
            
            if ($credential) {
                $quotas=get-wmiobject -query $query -computer $computer -Credential $credential -ea Stop
            }
            else {
                $quotas=get-wmiobject -query $query -computer $computer  -ea Stop
               }
            
            #get quota entries and filter off local user accounts, administrator and domain admins
            $entries = $quotas | where {$_.user -notmatch "$computer|Administrator|Domain Admins"}
            
            if ($entries) {
                Write-Verbose "Found $($entries.count) entries"
                foreach ($entry in $entries) {
                  Write-Verbose "Processing entry"
                  #remove quotes from user property and split the user entry at the comma
                  #assuming no commas in the domain or username
            
                  $replaced=($entry.user).Replace('"',"")
                  Write-Verbose "`$replace = $replaced"
            
                  $userdata=$replaced.split(",")
                      
                  #item 0 will be the domain and item 1 will be the user. Each item needs
                  #to be further split.  The domain and username values should be the same as any
                  #values passed as paramters.  I'll override the default domain parameter value. 
                  #Otherwise, if it isn't specified and the admin running the script isn't in the domain
                  #you'll get the wrong domain listed.
                  $domain=$userdata[0].Split("=")[1]
                  $username=$userdata[1].Split("=")[1]
                   
                  Write-Verbose "Parsed out $domain and $username"
            
                  #parse QuotaVolume and strip off quotes
                  $Volume=($entry.quotavolume.split("=")[1]).Replace('"',"")    
                  $Volume=$Volume.ToUpper()
                  Write-Verbose "`$volume=$volume"
                
                  #calculate % of quota used
                  $percentUsed="{0:P2}" -f ([double]$entry.DiskSpaceUsed/[double]$entry.Limit)
                  Write-Verbose "`$percentused = $percentused"
                  
                  #calculate limit remaining space
                  [double]$limitRemaining="{0:N2}" -f (([double]$entry.limit - [double]$entry.DiskSpaceUsed)/1GB)
                  Write-Verbose "`$limitRemaining = $limitRemaining"
                  
                  #is user over the warning limit?
                  if ($entry.diskspaceused -gt $entry.WarningLimit) {
                	$Warning=$True
                   }
                  else {
                	$Warning=$False
                  }
                  Write-Verbose "`$Warning=$warning"
                  
                 #is user over the hard limit?
                  if ($entry.diskspaceused -gt $entry.Limit) {
                	$OverLimit=$True
                   }
                  else {
                	$OverLimit=$False
                  }
                  Write-Verbose "`$overlimit=$overlimit"
                  Write-Verbose "Creating blank object"
            
                  #create a blank object
                  $obj = New-Object PSObject
                  Write-Verbose "Adding properties to the object"
                
                  #add some properties to the object
                  $obj | Add-Member -membertype NoteProperty -Name Volume -Value $Volume
                  $obj | Add-Member -membertype NoteProperty -Name Computername -Value $computer
                  $obj | Add-Member -membertype NoteProperty -Name Username -Value "$domain\$username"       
                  $obj | Add-Member -membertype NoteProperty -Name UsedSpaceMB -Value (($entry.DiskSpaceUsed/1MB) -as [double])
                  $obj | Add-Member -membertype NoteProperty -Name PercentUsed -Value $percentUsed
                  $obj | Add-Member -membertype NoteProperty -Name LimitGB -Value (($entry.Limit/1GB) -as [int])
                  $obj | Add-Member -membertype NoteProperty -Name LimitRemainingGB -Value $limitRemaining
                  $obj | Add-Member -membertype NoteProperty -Name WarningGB -Value (($entry.WarningLimit/1GB) -as [int])
                  $obj | Add-Member -membertype NoteProperty -Name OverWarning -Value $Warning
                  $obj | Add-Member -membertype NoteProperty -Name OverLimit -Value $OverLimit
                
                  #write object to the pipeline
                  Write-Verbose "Writing the object to the pipeline"
                  write $obj
                
                } #end ForEach 
                
            } #end if
            
            else {
              Write-Warning "No quota entries found that match your query on $computer"
              Write-Warning $query
            }
        } #end ForEach Computername
    } #end PROCESS

    END {
        Write-Verbose "Exiting function"
    } #end END
    
} #end Function

Set-Alias gdq    Get-DiskQuota

#end Script
# help gdq

The function only returns quota information for volumes which are configured with limits.

$query="Select * from win32_diskquota where limit < 18446744073709551615"

The function builds a query based on the parameter values you pass. The filtering for user account is a little tricky because WMI retrieves an associated Win32_Account object

$query=$query + " AND User =""Win32_Account.Domain='$domain',Name='$Username'"""

The function defaults to the current domain, but you can specify  a domain. The Domain parameter is used to more accurately define the user account. If you want to filter by domain alone, then run the function without any user filtering and pipe it to Where-Object where you can filter by the domain name.

All of the query string building in accomplished in the BEGIN script block. The query is executed in the PROCESS script block. You can pipe a collection of server names to the function.

PS C:\> get-content servers.txt | get-diskquota -user Jhicks | Export-csv jhicks-quota.csv

The function takes the resulting WMI information, parses and massages and writes a custom object to the pipeline. The END script block isn’t used, unless you include the –Verbose common parameter. The function will display progress information which can be helpful when debugging or troubleshooting. I encourage you to use code like this in your PowerShell v2 scripts and function.

Thanks to Wes Stahler, Aubrey Moren and Arnaud Petitjean for kicking my code around but of course any problems or bugs are mine and I hope you’ll let me know.

Download Get-DiskQuota


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

4 thoughts on “Get Disk Quota”

  1. Trevor Sullivan says:
    November 23, 2009 at 12:12 pm

    Hmmm, would it be possible to pipe in a list of DirectoryEntry objects from Active Directory? One potentially useful scenario for this function, would be the ability to pass in a list of Directory objects straight from AD, and then have the function be intelligent enough to strip out just the system name.

    Just an idea for enhancement 🙂

    Cheers,
    -Trevor Sullivan

    1. Jeffery Hicks says:
      November 23, 2009 at 12:32 pm

      All you need is code to retrieve a computername and pipe it to the function or pass it as a parameter. So sure, it shouldn’t be too difficult. Using the free Quest cmdlets is the easiest approach.

  2. Jeffery Hicks says:
    November 23, 2009 at 12:35 pm

    You don’t want to bog down PowerShell functions with too many bells and whistles, I prefer to keep them focused on single tasks. So create a function to write a computername to the pipeline then pipe it to Get-DiskQuota.

    Get-MyComputers | Get-DiskQuota | Export-CSV QuotaReport.csv

  3. Pingback: Shay Levy

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d