Monitoring disk space utilization of server(s) is critical and important job for any administrator. Keeping things organized might improve application availability and server availability. Being a database administrator for 10 years, I have faced and handled/managed lot of issues with disk space. This article takes us through the in-detail steps to read each drive and report every drive details based on threshold values. The output is integrated with excel charts. The step by step process quickly take us through the disk space utilization details of server(s). You'll basically feed a list of servers to watch over, and it will report back on these for you, meaning you could also use it as a more general "daily server disk space report"

Please refer technet article for more detailed information

Input CSV file DiskSpaceReport_With_Credential.ps1





#### Spreadsheet Location 
 $DirectoryToSaveTo = "c:\" 
 $date=Get-Date -format "yyyy-MM-d" 
 ##Get-credential always pop-up dialog box for entering a password, however you can save your securestring password to a file or directly feed the password. 
 ##The problem with this is that the password will be exposed to anyone with access to the file. 
####User Credentials to access servers 
 $User = "ccov648" 
 $Pass = ConvertTo-SecureString "thanVitha@2015" -AsPlainText -Force 
 $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User,$Pass 
# before we do anything else, are we likely to be able to save the file? 
# if the directory doesn't exist, then create it 
if (!(Test-Path -path "$DirectoryToSaveTo")) #create it if not existing 
  New-Item "$DirectoryToSaveTo" -type directory | out-null 
#PowerShell is made available to use Excel componment by invoking excel.application COM object that will allow us to work with excel to add data and format that data. 
#Create a new Excel object using COM 
$Excel = New-Object -ComObject Excel.Application 
#you can see the Excel sheet and helpful in troubleshooting 
$Excel.visible = $True 
#After instantiating the excel objects, It's a time use its respective methods and properties 
$Excel = $Excel.Workbooks.Add() 
$Sheet = $Excel.Worksheets.Item(1) 
#Save the initial row so it can be used later to create a border 
#Counter variable for rows 
$intRow = $row 
#FileFormat numbers in Mac Excel 
#These are the main file formats in Windows Excel 2007-2016: 
#51 = xlOpenXMLWorkbook (without macro's in 2007-2013, xlsx) 
#52 = xlOpenXMLWorkbookMacroEnabled (with or without macro's in 2007-2013, xlsm) 
#50 = xlExcel12 (Excel Binary Workbook in 2007-2013 with or without macro's, xlsb) 
#56 = xlExcel8 (97-2003 format in Excel 2007-2013, xls) 
#define the sheet name 
$sheet.Name = 'DiskSpace' 
$Sheet.Activate() | Out-Null 
#Create a Title for the first worksheet 
$row = 1 
$Column = 1 
$Sheet.Cells.Item($row,$column)= 'Disk Space Information' 
$range = $Sheet.Range("a1","h2") 
$range.Merge() | Out-Null 
# [Enum]::getvalues([Microsoft.Office.Interop.Excel.XLVAlign]) | select @{n="Name";e={"$_"}},value__ 
#To fetch the list of alignment values using the above the enumerator. 
$range.VerticalAlignment = -4160 
#Give it a nice Style so it stands out 
$range.Style = 'Title' 
#Increment row for next set of data 
#Save the initial row so it can be used later to create a border 
$initalRow = $row 
#Create a header for Disk Space Report; set each cell to Bold and add a background color 
$Sheet.Cells.Item($row,$column)= 'Computername' 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
$Sheet.Cells.Item($row,$column)= 'DeviceID' 
#Making the font Bold and adjusting the background color (using the Interior.ColorIndex property of each cell 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
$Sheet.Cells.Item($row,$column)= 'VolumeName' 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
$Sheet.Cells.Item($row,$column)= 'TotalSizeGB' 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
$Sheet.Cells.Item($row,$column)= 'UsedSpaceGB' 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
$Sheet.Cells.Item($row,$column)= 'FreeSpaceGB' 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
$Sheet.Cells.Item($row,$column)= '%Free' 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
$Sheet.Cells.Item($row,$column)= 'Status' 
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48 
#Set up a header filter 
$headerRange = $Sheet.Range("a3","o3") 
$headerRange.AutoFilter() | Out-Null 
#Increment Row and reset Column back to first column 
$Column = 1 
#Get the drives and filter out CD/DVD drives 
Import-Csv C:\server.csv|%{ 
$cserver = $_.Server 
$cdrivelt = $_.Drive 
$clowth = $_.LowTh 
$cwarnth = $_.WarnTh 
$ccritth = $_.CritTh 
$diskinfo= Get-WmiObject -Class Win32_LogicalDisk -ComputerName $cserver  -Filter "DeviceID='$cdrivelt'" -Credential $Credentials 
ForEach ($disk in $diskinfo) 
If ($diskinfo.Size -gt 0{$percentFree = [Math]::round((($diskinfo.freespace/$diskinfo.size) * 100))} 
Else {$percentFree = 0} 
#Process each disk in the collection and write to spreadsheet 
    $Sheet.Cells.Item($row,1)= $disk.__Server 
    $Sheet.Cells.Item($row,2)= $disk.DeviceID 
    $Sheet.Cells.Item($row,3)= $disk.VolumeName 
    $Sheet.Cells.Item($row,4)= [math]::Round(($disk.Size /1GB),2) 
    $Sheet.Cells.Item($row,5)= [math]::Round((($disk.Size - $disk.FreeSpace)/1GB),2) 
    $Sheet.Cells.Item($row,6)= [math]::Round(($disk.FreeSpace / 1GB),2) 
    $Sheet.Cells.Item($row,7)= ("{0:P}" -f ($disk.FreeSpace / $disk.Size)) 
    #Determine if disk needs to be flagged for warning or critical alert 
    If ($percentFree -le  $ccritth) { 
        $Sheet.Cells.Item($row,8) = "Critical" 
        #Check to see if space is near empty and use appropriate background colors 
        $range = $Sheet.Range(("A{0}"  -f $row),("H{0}"  -f $row)) 
        $range.Select() | Out-Null   
        #Critical threshold        
        $range.Interior.ColorIndex = 3 
    } ElseIf ($percentFree -gt $ccritth -AND $percentFree -le $cwarnth) { 
        $Sheet.Cells.Item($row,8) = "Warning" 
        $range = $Sheet.Range(("A{0}"  -f $row),("H{0}"  -f $row)) 
        $range.Select() | Out-Null       
        $range.Interior.ColorIndex = 6 
     ElseIf ($percentFree -ge $cwarnth -AND $percentFree -lt $clowth) { 
        $Sheet.Cells.Item($row,8) = "Low" 
        $range = $Sheet.Range(("A{0}"  -f $row),("H{0}"  -f $row)) 
        $range.Select() | Out-Null       
        $range.Interior.ColorIndex = 12 
    } Else { 
        $Sheet.Cells.Item($row,8) = "Good" 
#Add a border for data cells have used with the VerticalAlignment property. 
#[Enum]::getvalues([Microsoft.Office.Interop.Excel.XlBordersIndex]) | select @{n="Name";e={"$_"}},value__ 
$dataRange = $Sheet.Range(("A{0}"  -f $initalRow),("H{0}"  -f $row)) 
7..12 | ForEach { 
    $dataRange.Borders.Item($_).LineStyle = 1 
    $dataRange.Borders.Item($_).Weight = 2 
#Auto fit everything so it looks better 
$usedRange = $Sheet.UsedRange                                                          
$usedRange.EntireColumn.AutoFit() | Out-Null 
$sheet = $excel.Worksheets.Item(1) 
$beginChartRow = $Row 
$Sheet.Cells.Item($row,$Column) = 'Critical' 
$Sheet.Cells.Item($row,$Column) = 'Warning' 
$Sheet.Cells.Item($row,$Column) = 'Low' 
$Sheet.Cells.Item($row,$Column) = 'Good' 
$Column = 1 
#Critical formula 
#Warning formula 
#low formula 
#Good formula 
$Sheet.Cells.Item($row,$Column)= $good 
$endChartRow = $row 
$chartRange = $Sheet.Range(("A{0}" -f $beginChartRow),("d{0}" -f $endChartRow)) 
$chart = $sheet.Shapes.AddChart().Chart 
#Configure the chart 
##Use a 3D Pie Chart 
$chart.ChartType = 70 
$chart.Elevation = 40 
#Give it some color 
$sheet.Shapes.Item("Chart 1").Fill.ForeColor.TintAndShade = .34 
$sheet.Shapes.Item("Chart 1").Fill.ForeColor.ObjectThemeColor = 5 
$sheet.Shapes.Item("Chart 1").Fill.BackColor.TintAndShade = .765 
$sheet.Shapes.Item("Chart 1").Fill.ForeColor.ObjectThemeColor = 5 
$sheet.Shapes.Item("Chart 1").Fill.TwoColorGradient(1,1) 
#Set the location of the chart 
$sheet.Shapes.Item("Chart 1").Placement = 3 
$sheet.Shapes.Item("Chart 1").Top = 30 
$sheet.Shapes.Item("Chart 1").Left = 600 
$chart.HasTitle = $True 
$chart.ChartTitle.Text = "Disk Space Report" 
$chart.ChartStyle = 26 
$chart.PlotVisibleOnly = $False 
$chart.SeriesCollection(1).DataLabels().ShowValue = $True 
$chart.SeriesCollection(1).DataLabels().Separator = ("{0}" -f [char]10) 
$chart.SeriesCollection(1).DataLabels().Position = 2 
$chart.SeriesCollection(1).Points(1).Format.Fill.ForeColor.RGB = 255 
$chart.SeriesCollection(1).Points(2).Format.Fill.ForeColor.RGB = 65535 
$chart.SeriesCollection(1).Points(2).Format.Fill.ForeColor.RGB = 265535 
$chart.SeriesCollection(1).Points(3).Format.Fill.ForeColor.RGB = 5287936 
#Hide the data 
#$chartRange.EntireRow.Hidden = $True 
$sheet.Name = 'DiskInformation' 
$filename = "$DirectoryToSaveTo$filename.xlsx" 
if (test-path $filename ) { rm $filename } #delete the file if it already exists 
$Excel.SaveAs($filename, $xlOpenXMLWorkbook) #save as an XML Workbook (xslx) 
$Excel.Saved = $True 






  1. CSV input - Easy to maintain and manage 
  2. Cusotmization can be done at the each drive level as the threshold value may vary on every server and most of the drive depending the size of each drive
  3. Graphical representation of Disk Space Usage Utilization report
  4. Simplest way to keep a cap on every drive to set threshold value
  5. Proactive monitoring and alerting respective teams may avoid unforeseen disk space issues

Note:- I would prefer to read the blog references entered under reference section for more in depth information about charting with PoSH.