Click here to monitor SSC
  • Av rating:
  • Total votes: 51
  • Total comments: 43
Sean Duffy

Disk Space Monitoring and Early Warning with PowerShell

15 August 2011

Sean Duffy recently had an unwelcome encounter with Exchange Server Back Pressure, which cut off his message flow due to a lack of space on the server. To make sure it didn’t happen again, he found a way to automatically monitor all his servers from afar, with a little PowerShell magic.

Introduction

Monitoring server resources is an important job of any Systems Administrator. Lose track of what resources are being allocated where, and how much of these resources are currently free, and you could find your carefully maintained, delicately balanced servers coming to a grinding halt. Well, not in all cases, but in the case that you have an OS and a database or database log file disk, you really don’t want it running out of disk space.

I recently had a bad spate of disk space issues on an Exchange 2010 SP1 server, causing Back Pressure levels to increase, which resulted in mail delivery from the Internet ceasing to function. Needless to say, the company was not thrilled, but this particular client’s budget was tight, so the server was running on minimal resources (naturally, mainly in terms of disk space). To get around that, I needed some kind of early warning system that would alert the client, myself, or both, whenever the space on certain drives was getting low. This is where PowerShell and a disk space monitoring script came in.

In this write-up, I will use Exchange 2010 (SP1) Back Pressure as an example of where you could use a script like this, besides it being used as part of a daily reporting system. The primary goal will be to write a PowerShell script which will send us a regular email report on server disk space resources. By doing this, we can aim to keep a closer eye on specific disk space figures, and therefore have a better idea of when we may be approaching any thresholds.

This PowerShell script is not going to be specifically for monitoring your Exchange servers – it is quite flexible and can be used in just about any Windows environment to monitor your servers. You’ll basically feed it 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” if you wish.

Disk Space Monitoring and Exchange 2010 SP1 Back Pressure

Back Pressure is when Exchange 2010 attempts to prevent “service unavailability” (when crucial resources are under pressure, such as Memory or Hard Disk space). This resource monitoring system is a service that exists on Microsoft Exchange Server 2010 Hub Transport and Edge Transport servers. Here is a list of items monitored by Back Pressure, taken from the official Technet article.

  • Free space on the hard disk that stores the message queue database.
  • Free space on the hard disk that stores the message queue database transaction logs.
  • The number of uncommitted message queue database transactions that exist in memory.
  • The memory that's used by the EdgeTransport.exe process.
  • The memory that's used by all other processes.

A back pressure problem is fairly easy to find in your Hub/Edge Transport server event logs once you have seen one before.

There are three levels of resource utilisation that the back pressure feature watches for. This list is also taken from a Technet article, and gives a brief explanation of what happens under each level:

  • Normal - The resource isn't overused. The server accepts new connections and messages.
  • Medium - The resource is slightly overused. Back pressure is applied to the server in a limited manner. Mail from senders in the authoritative domain can flow. However, depending on the specific resource under pressure, the server uses tarpitting to delay server response or rejects incoming MAIL FROM commands from other sources.
  • High - The resource is severely overused. Full back pressure is applied. All message flow stops, and the server rejects all new incoming MAIL FROM commands.

Now, while it was an unwelcome encounter with Exchange Server Back Pressure that led me to pursue this script solution, I decided to focus on creating a script that would be usable in any Windows Server environment. While I’m keen to create a deeper integration with Exchange at a later date, I felt that a broader approach would be more useful for now!

Monitoring and Reporting on Disk Space using PowerShell

Previously I have only ever really delved into scripting with VBscript and batch files. I had taken a brief look at PowerShell before, but never really had the time to learn more about it. I figured this would be a nice little project to start using PowerShell on, as I do tend to learn quicker with practical projects. Given that I’m a PowerShell beginner, I’m sure there’s plenty of room for improvement, so if you do notice any areas that could be improved, please chime in with a comment at the end of this article!

So, enter PowerShell. My first impressions are that it is fairly easy to learn, and that you seem to be able to accomplish a lot with a comparatively small amount of script. Most Windows 7 installations, all Windows Server 2008 R2 installations (bar Core edition) come with PowerShell version 2.0 installed by default, and this is what the script below is written to work in. PowerShell 2.0 is included in SP2 for Windows Server 2003, so if you are running an older OS, you should be fine here too.

If you have never used PowerShell on your system before, chances are that your PowerShell “Execution Policy” is set to restrict execution of scripts on your machine, and you’ll have trouble running this script. To allow your scripts to execute, you need to set your Execution Policy to RemoteSigned. Here is the procedure to, first of all, check what yours is set to, and then, if necessary, set it to RemoteSigned.

  1. Run PowerShell as Administrator on your PC/Server
  2. Enter in and run the Get-ExecutionPolicy cmdlet – this will output the current setting. If it is not already RemoteSigned, or Unrestricted, then use the following cmdlet to set it to allow your scripts to run:

    Set-ExecutionPolicy RemoteSigned
  3. You should now be asked to confirm whether you are sure. Press Y to confirm, and then press Enter.

Setting your execution policy

Figure 1 - Setting your execution policy

Now that your environment is ready to run some cmdlets and scripts, let’s take a look at some of the code we will be using. I have added comments to each of the sections, explaining what is happening at each stage of the script. The end result will email you a neat, tabled report with all the disk space information you need about any disk drives that are below a specified free disk space threshold percentage.

A basic rundown of the script’s processes goes like this:

  1. Iterate through a list of servers you specify in a text file, checking disk space.
  2. Check each free disk space percentage figure against a pre-defined percent threshold figure.
  3. If the disk in question is below this threshold, then add the details to the report, if not, skip past it.
  4. Assemble an e-mail and send it off to the specified recipient(s) if any of the drives were below the free disk space threshold.

The nice thing about this script is that it will only report on disks that need your attention (you set the threshold yourself in the script). Therefore, you will only be bothered with an email if one or more disks in your servers are really getting low on disk space.

Don’t forget to set up your from and to email address as well as your SMTP (mail) server address.

The Script

#########################################################

#

# Disk space monitoring and reporting script

#

#########################################################

 

$users = "toaddress@yourdomain.com" # List of users to email your report to (separate by comma)

$fromemail = "fromaddress@yourdomain.com"

$server = "yourmailserver.yourdomain.com" #enter your own SMTP server DNS name / IP address here

$list = $args[0] #This accepts the argument you add to your scheduled task for the list of servers. i.e. list.txt

$computers = get-content $list #grab the names of the servers/computers to check from the list.txt file.

# Set free disk space threshold below in percent (default at 10%)

[decimal]$thresholdspace = 10

 

#assemble together all of the free disk space data from the list of servers and only include it if the percentage free is below the threshold we set above.

$tableFragment= Get-WMIObject  -ComputerName $computers Win32_LogicalDisk `

| select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `

| Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace} `

| ConvertTo-HTML -fragment

 

# assemble the HTML for our body of the email report.

$HTMLmessage = @"

<font color=""black"" face=""Arial, Verdana"" size=""3"">

<u><b>Disk Space Storage Report</b></u>

<br>This report was generated because the drive(s) listed below have less than $thresholdspace % free space. Drives above this threshold will not be listed.

<br>

<style type=""text/css"">body{font: .8em ""Lucida Grande"", Tahoma, Arial, Helvetica, sans-serif;}

ol{margin:0;padding: 0 1.5em;}

table{color:#FFF;background:#C00;border-collapse:collapse;width:647px;border:5px solid #900;}

thead{}

thead th{padding:1em 1em .5em;border-bottom:1px dotted #FFF;font-size:120%;text-align:left;}

thead tr{}

td{padding:.5em 1em;}

tfoot{}

tfoot td{padding-bottom:1.5em;}

tfoot tr{}

#middle{background-color:#900;}

</style>

<body BGCOLOR=""white"">

$tableFragment

</body>

"@

 

# Set up a regex search and match to look for any <td> tags in our body. These would only be present if the script above found disks below the threshold of free space.

# We use this regex matching method to determine whether or not we should send the email and report.

$regexsubject = $HTMLmessage

$regex = [regex] '(?im)<td>'

 

# if there was any row at all, send the email

if ($regex.IsMatch($regexsubject)) {

                        send-mailmessage -from $fromemail -to $users -subject "Disk Space Monitoring Report" -BodyAsHTML -body $HTMLmessage -priority High -smtpServer $server

}

 

# End of Script

Finally, to run this script you will need a text file, created in your script folder, that it uses as an argument. Call this list.txt and place it in your script folder. In the list.txt file, list each of the servers on your domain that need to be checked in the script, one server name per line. To run the script, create a batch file called start.bat, and use the following as its content:

powershell.exe -command "& 'C:\My Scripts\diskspace.ps1' 'C:\My Scripts\list.txt' "

Naturally, remember to modify the paths in the batch file to match your environment (and note that the above batch file allows you to have blank spaces in your script’s path, too). Once this is all ready, you can use Windows Task Scheduler to schedule in the batch file to run at a certain time or interval.

Download the full script and associated files here: Script Download

Conclusion

Whether you are looking for a script to actively monitor your server and guard against Exchange disk space back pressure, or you are just after a daily disk space report for your servers, this should do the job. It even goes one step further by trying to be non-obtrusive, emailing you only when disks are getting low on space. It doesn’t have to end here, though. Why not improve on the above script? You could use many other PowerShell cmdlets to provide additional information or checks. Some ideas that come to mind are:

  • Find certain processes running in memory and check to see if they are using more than a certain amount or percent of RAM – if so, report on those too.
  • Find the total amount of memory in each server or computer, work out the amount of free memory, then see if this amount is below a certain percentage and report on that.
  • If working out the percentage of free disk space or memory for Exchange Back Pressure, make some additional checks and calculations based on the technet article’s explanations of low, medium and high resource pressure percentages, and report on these different scenarios (or just before each scenario is reached, to provide ample warning).

Indeed, my fellow Simple-Talk author Laerte Junior has written extensively about using PowerShell to automate your morning checklist, and is now starting to employ WMI in his scripts. Powerful stuff, making these kinds of reporting tasks elegant and versatile.

Sometimes system administrators don’t always have the time to jump on to every server console and check on their health and resources. Or you may be lucky enough to have a central monitoring console that is fed with all kinds of information about each of your servers. If it is the former, then by monitoring your server resources more closely via a script such as the one we’ve just seen, you should be able to proactively sort out any issues before they arise. This could save you precious time which would have otherwise been used to fire fight the issue at hand.

Sean Duffy

Author profile:

All round IT geek living in the greater London area. Working as an IT Infrastructure engineer specialising in virtualisation, hosting and support. Sean enjoys all forms of IT, and writes about the bits that intrigue and entertain him on his Shogan.Tech blog. When he’s not learning about the latest Server hardware, platform or software, you'll probably find him developing iPhone apps in objectiveC, gaming online, or on a dirt bike riding enduro-X.

You should follow Sean on Twitter here (@Shogan85)

Search for other articles by Sean Duffy

Rate this article:   Avg rating: from a total of 51 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Nice
Posted by: laerte (view profile)
Posted on: Thursday, August 18, 2011 at 7:14 AM
Message: Nice one my friend. Keep up the good work :).. and thanks for the mention.

Subject: Thanks
Posted by: Shogan (view profile)
Posted on: Thursday, August 18, 2011 at 5:37 PM
Message: Thanks Laerte. There is some great PowerShell content on your blog and posts, so I'll be having a look around there too. I have only recently taken an interest, but am thoroughly enjoying it!

Subject: excellent script...if I could only get it to work!
Posted by: Jim P. (not signed in)
Posted on: Tuesday, August 23, 2011 at 9:03 AM
Message: Sean-

Excellent scripting skills, I must say. This past weekend I ran into an issue where my Exchange 2k10 environment was in a state of Back Pressure and mail wasn't flowing - easy enough to resolve the issue, but like you, I'm after a reporting tool to alert me ahead of time.

The script makes sense to me, with the exception of this line:

$list = $args[0] #This accepts the argument you add to your scheduled task for the list of servers. i.e. list.txt

I'm not too sure how to properly designate the argument. I tried using the actual path to the list.txt file on my C: drive, but that's not working. I'm contributing this to my lack of knowledge with power shell and i'm trying to look for an answer on the interwebz, but I figured I would post here too with props on the script and hopefully get you to shed some light on this particular part of the script.

Many thanks and keep up the awesome work man!

Jim P.

Subject: excellent script...if I could only get it to work!
Posted by: Jim P. (not signed in)
Posted on: Tuesday, August 23, 2011 at 10:49 AM
Message: Sean-

Excellent scripting skills, I must say. This past weekend I ran into an issue where my Exchange 2k10 environment was in a state of Back Pressure and mail wasn't flowing - easy enough to resolve the issue, but like you, I'm after a reporting tool to alert me ahead of time.

The script makes sense to me, with the exception of this line:

$list = $args[0] #This accepts the argument you add to your scheduled task for the list of servers. i.e. list.txt

I'm not too sure how to properly designate the argument. I tried using the actual path to the list.txt file on my C: drive, but that's not working. I'm contributing this to my lack of knowledge with power shell and i'm trying to look for an answer on the interwebz, but I figured I would post here too with props on the script and hopefully get you to shed some light on this particular part of the script.

Many thanks and keep up the awesome work man!

Jim P.

Subject: awesome!
Posted by: Jim P. (not signed in)
Posted on: Tuesday, August 23, 2011 at 10:51 AM
Message: Sean-

Sorry for the double post, hitting F5 after the fact will double post apparently. ;)

I was able to get the script working by modifying the $list line as follows:

$list = "C:\list.txt" #This accepts the argument you add to your scheduled task for the list of servers. i.e. list.txt


I'm not sure if that's entirely correct, but the script works like a champ and it looks great too!

Thanks again and awesome work!

Cheers,

Jim P.

Subject: Thanks Jim
Posted by: Shogan (view profile)
Posted on: Wednesday, August 24, 2011 at 3:22 AM
Message: Hi Jim,

Excellent - I am glad you got it working. That is one way of doing it (the way you have chosen). Basically by using the args method where you specify the list.txt file as an argument should work as follows. From your PowerShell prompt, enter the following:

./nameofyourscript.ps1 "list.txt"

Doing the above would provide list.txt as the argument, provided list.txt was located in the same directory/folder as your "nameofyourscript.ps1" file too. If you take a look at the script download: http://dl.dropbox.com/u/450727/scripts/diskspacereport.zip inside that zip file is a batch file, which allows you to run the script without already being in a PowerShell prompt. The contents of that batch file should give you an idea of how the argument parameter works too. (Things get a little complicated if your list.txt file is in a path containing spaces, but this batch file shows how to handle that).

Hope the above makes sense, and I am glad you got it working in your own way too!

Cheers,
Sean

Subject: Works only if System Locale is US-EN
Posted by: CypherBit (not signed in)
Posted on: Wednesday, August 24, 2011 at 6:06 AM
Message: Could this perhaps be fixed? I can't change the System Locale on any of my servers and nothing comes up otherwise (the script runs, but doesn't find any servers/disk that are below 10%).

If I do get-host I have sl-SI under CurrentCulture.

Subject: Locale
Posted by: Shogan (view profile)
Posted on: Friday, August 26, 2011 at 2:42 AM
Message: Hi CypherBit, this is interesting. I'll test it out and see if I can find a workaround for you.

Thanks,
Sean

Subject: Locale
Posted by: CypherBit (not signed in)
Posted on: Monday, August 29, 2011 at 7:06 AM
Message: Thank you very much Sean, looking forward to it. It's a great scipt indeed.

Subject: Locale
Posted by: Shogan (view profile)
Posted on: Friday, September 02, 2011 at 1:19 PM
Message: Hi CypherBit,

Ok this seems to do with your locale formatting the percentage free numbers with a comma instead of a decimal point. I'm trying to find a solution and will post back here when I do! Otherwise, if anybody else has a way of solving this please shout! I can't seem to get the Get-WmiObject -Locale parameter to work which I was hoping may return numbers with points.

Subject: Same problem as CypherBit
Posted by: Frenjon (view profile)
Posted on: Monday, September 05, 2011 at 3:53 PM
Message: Also Locale related (i think)..
Nothing happens - even if I set [decimal]$thresholdspace = 80

PS C:\Scripts\Disk-Space> get-host
CurrentCulture : da-DK
CurrentUICulture : en-US

Hoping this can be fixed.. Otherwise, a very good and detailed post Sean!

Subject: Locale issues - should be resolved now
Posted by: Shogan (view profile)
Posted on: Tuesday, September 06, 2011 at 6:31 AM
Message: Hi CypherBit and Frenjon,

Thanks again for reporting the issues when using a locale other than en-US or en-GB! As I suspected it was down to the other locales using commas instead of points in the numbers the script brings back.

Also, with the help of a user "jvierra" over at a PowerShell forum, I was able to see my mistake. I was essentially formatting the numbers in the above script first, then comparing them against the threshold. The issue here is that I was comparing converted values, not numbers. This worked fine in the cases of my locale, but was not a good method of doing this. I have therefore rewritten the script (some slight changes you'll notice we now compare the numbers then format the figures)!

Many thanks to "jvierra" at Sapien Technologies PowerShell forums for helping me out realising my error and the revised script :)

Here is a link to download the new script which should now work in any locale: http://dl.dropbox.com/u/450727/scripts/diskspacereport-new.zip

Please let me know if that works/fixes your issues?

Sean

Subject: Works great
Posted by: CypherBit (view profile)
Posted on: Wednesday, September 07, 2011 at 3:06 AM
Message: Thank you so much Sean (and jvierra), this one works great. Now I just need to solve: "Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)" on a couple of servers.

Subject: CypherBit
Posted by: Shogan (view profile)
Posted on: Wednesday, September 07, 2011 at 6:18 AM
Message: Cypherbit, great - glad it is now working! I have seen that error message when either A) the user running the script doesn't have elevated (high enough) permissions on the server in question, or B) when the server name the script is checking in the list.txt file is wrong (or the DNS name cannot be resolved to the right server). Try checking those two things. For example, from the place you are running the script from, try ping the name of the server as it appears in your list.txt file and make sure the ping resolves to the right server/IP address.

Otherwise glad you are almost there!

Sean

Subject: Sean
Posted by: CypherBit (view profile)
Posted on: Wednesday, September 07, 2011 at 6:50 AM
Message: I actually "resolved" it by executing the script on a different server. I did check the FW, DNS, RPC, Netbios, DCOM services before that, but nothing helped.

I'm 100% satisfied now.

Subject: Works!
Posted by: Frenjon (view profile)
Posted on: Friday, September 09, 2011 at 3:59 PM
Message: Hi Sean - Works here too.. Thanks for the quick fix :)

Will set this up as a Scheduled task soon!

I'm thinking of expanding the functionality a bit so that it enumerates all computers in a certain OU (Servers in our case) and makes a new .txt file before each run..

Found an easy way to do it with this script..

http://social.technet.microsoft.com/Forums/en/winserverManagement/thread/a0cebabf-3fc9-49b0-be55-5e4ff3232b7b

This means no manual update of the .txt file when adding and removing servers from the domain :)

Thanks again for the fix..

Subject: Awesome
Posted by: Shogan (view profile)
Posted on: Sunday, September 11, 2011 at 10:36 AM
Message: Hi Frenjon and Cypherbit,

Glad you guys are both up and running now. Frenjon, that is a great addition to the script. Nice find!

Sean

Subject: Love it......
Posted by: Derek Wharton (view profile)
Posted on: Monday, September 12, 2011 at 8:58 AM
Message: what about error handling? Such as "The RPC server is unavailable", is there a way to get the name from the list.txt where the server is unavailable?

Subject: Love it......
Posted by: Derek Wharton (view profile)
Posted on: Monday, September 12, 2011 at 9:01 AM
Message: what about error handling? Such as "The RPC server is unavailable", is there a way to get the name from the list.txt where the server is unavailable?

Subject: Love it......
Posted by: Derek Wharton (view profile)
Posted on: Monday, September 12, 2011 at 9:07 AM
Message: what about error handling? Such as "The RPC server is unavailable", is there a way to get the name from the list.txt where the server is unavailable?

Subject: Oops
Posted by: Derek Wharton (view profile)
Posted on: Monday, September 12, 2011 at 10:24 AM
Message: I apologize for the multiple post

Subject: Awesome
Posted by: Old Dog (view profile)
Posted on: Tuesday, September 13, 2011 at 2:36 AM
Message: Sean this script is great, keep up the good work.

Subject: Error handling
Posted by: Shogan (view profile)
Posted on: Tuesday, September 13, 2011 at 6:52 AM
Message: @Derek, yes this shouldn't be too difficult to achieve - we already hold a list of machine names in $computers, so using some error handling code, it should be easy to output which machine was not contactable and output this either in email or the console. I'll see if I can take a look at this in a couple of weeks time myself - just taking a short holiday so when I am back I'll see what I can do.

@Old Dog, thank you!

Subject: Perhaps a noob error?
Posted by: ous00ner (view profile)
Posted on: Monday, November 21, 2011 at 3:39 PM
Message: I am relatively new to PS and I follow this script mostly. It appears that my lists.txt is not being read or perhaps passed correctly. When I try to run it I get:

An empty pipe element is not allowed.
At C:\scripts\powershell\diskspace.ps1:32 char:2
+ | <<<< select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace
(Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : EmptyPipeElement


Subject: Perhaps a noob error?
Posted by: ous00ner (view profile)
Posted on: Tuesday, November 22, 2011 at 6:57 AM
Message: I am relatively new to PS and I follow this script mostly. It appears that my lists.txt is not being read or perhaps passed correctly. When I try to run it I get:

An empty pipe element is not allowed.
At C:\scripts\powershell\diskspace.ps1:32 char:2
+ | <<<< select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace
(Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : EmptyPipeElement


Subject: reply
Posted by: Shogan (view profile)
Posted on: Thursday, November 24, 2011 at 11:40 AM
Message: Hi ous00ner,

How does your list of machine names look? Are they (the machines) listed one per line and nothing else? Check that you have only listed machines you can access, or even just add one PC/Server to the list to start small with.

Also to check - are you executing the script from the shell and specifying the list.txt file as an argument correctly?

Let us know how you get on with the above.

Cheers,
Sean

Subject: Script terminated without checking the rest of the servers
Posted by: indomanna (view profile)
Posted on: Saturday, December 10, 2011 at 9:02 PM
Message: I have one server where I cannot map to the server admin share. When I put that server on the top of the list, the script throw error access denied and terminated.

Can we put error checking on this script by PING and try mapping admin share on the server? If the server is not responding then the script will skip the server and continue with the rest. Once all the servers are checked, the script will also send email regarding the unresponsive server.

Thanks,
Indo

Subject: Empty Pipe error
Posted by: Sam.Cayze (view profile)
Posted on: Tuesday, January 24, 2012 at 10:34 AM
Message: C:\Documents and Settings\user>powershell.exe -command "& 'C:\Scripts\DiskSpaceAlert\diskspace.ps1' 'C:\Scripts\DiskSpaceAlert\List.txt'"

An empty pipe element is not allowed.
At C:\Scripts\DiskSpaceAlert\diskspace.ps1:33 char:2
+ | <<<< select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace (Gb)';e={"{0:n2
}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : EmptyPipeElement

Tried using localhost, mutiple servers, IP addresses, etc in the list.txt file.
Powershell v2 on Windows Server 2003.latest, x86

Subject: Error trapping?
Posted by: dbamohsin (view profile)
Posted on: Thursday, January 26, 2012 at 5:50 AM
Message: Hi Sean.. excellent Script.

I tend to build scripts which will query more than one server like this, to have some error trapping in place:

$hostnamelist = Get-Content "$filelocation\hostList.txt"

#Run the query for each server
foreach($hostname in $hostnamelist)
{
$tableFragment+= Get-WMIObject -ComputerName $hostname Win32_LogicalDisk `
| select __SERVER, DriveType, VolumeName, Name, @{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},@{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, @{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
| Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace} `
| ConvertTo-HTML -fragment

#handle login failures
trap {
"Oops! $_ on server $hostname";
continue
}
}

Subject: repsonses to above comments
Posted by: dbamohsin (view profile)
Posted on: Thursday, January 26, 2012 at 5:53 AM
Message: By the way, for the guys above who are getting 'empty pipe element not allowed', it is more than likely due to a new line being started with pipe and the previous line does not end with ` as a continuation marker.

Some examples of error trapping etc are given in my blog.. http://dbamohsin.wordpress.com/2012/01/25/powershell-retrieve-sql-server-info-for-all-my-servers/

Mohsin
www.dbamohsin.wordpress.com

Subject: Disk Space Script error
Posted by: ColinTheDBA (view profile)
Posted on: Thursday, February 09, 2012 at 9:13 AM
Message: Great stuff!
However, I am getting error. ConvertTo-HTML A parameter cannot be found that maches parameter name 'fragment'. This occurs on the piped line and the previous line has ` to mark end of line. Would be great to overcome this issue.
Thanks.

Subject: No Email
Posted by: wald (view profile)
Posted on: Thursday, May 10, 2012 at 11:38 AM
Message: Hi Sean, I am able to run the script without any errors after I changed my server to "Unrestricted" but I never get the output email. I did change the $users, $fromemail, and $server variables to correct entries. Do you have ideas to why I couldn't send?

Subject: Pipe Errors
Posted by: LevelTen (view profile)
Posted on: Tuesday, May 29, 2012 at 9:06 AM
Message: For those getting pipe errors. If you copied and pasted the script from this web page it will put line break after the ' symbol in the #assemble together all of the free disk space data section.

Remove the line breaks and it will work.

Make:
|select __Server ..... '

|Where-Object

Into:
|select __Server .... '
|Where-Object

Subject: Most Excellent
Posted by: neiltunnah (view profile)
Posted on: Wednesday, August 08, 2012 at 9:20 AM
Message: This is most excellent, thank you so much for sharing your power scripting ninja skills.

For some of the users experiencing issues, make sure you have the "Remote Registry" service running on the machine you are trying to monitor. I enabled this through GPO.

Subject: rpc server unavailable
Posted by: goof1428 (view profile)
Posted on: Sunday, September 02, 2012 at 12:16 AM
Message: Great script Sean. I have been searching for something like this because we have been getting hammered with servers running out of disk space and scom alerting isn't working just right.

Although I have scoured google and pieced together your script with another because I wanted to get Volume and not just LogicalDisk because with LogicalDisk I wasnt able to see the other virtual volumes on a server.

The only error I get is that on some server RPC server is not available even though WMI and RPC services are running. I even enabled them on the windows firewall as an exception. Also some disks are not being reported if I change the value to 10%...but at 20% they do. weird.

Here is my script (Ive only changed the assembly part a bit):

####

#assemble together all of the free disk space data from the list of servers and only include it if the

percentage free is below the threshold we set above.
$tableFragment= Get-WMIObject Win32_Volume -filter "DriveType=3" -computer (get-content c:\scripts

\serversspace.txt) | Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f

($_.capacity/1gb))}},@{Name="freespace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@

{Name="PercentFree";Expression={"{0:P2}" -f(($_.freespace/1gb)/($_.capacity/1gb))}} | Where

{$_.PercentFree -lt"20.00 %"} | sort-object -Property "freespace(GB)" | convertto-html -fragment


######



And here are the errors I get on some servers:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand


Any help on the errors would be much appreciated or maybe some help on the script to make it work like yours but on volumes as well. Thanks again for the effort.

Subject: The RPC server is unavailable.
Posted by: goof1428 (view profile)
Posted on: Sunday, September 02, 2012 at 12:21 AM
Message: Great stuff Sean. Appreciate the time and effort.

I changed up the script so it can get a report on volumes as well. (searched google for that).
However my issue is I still get RPC errors on some servers and I had to raise the minimum to 20% for it on a few others. Is it a timeout issue? Can we tell the script to wait a few seconds to get WMI? like a pause?

######

#assemble together all of the free disk space data from the list of servers and only include it if the

percentage free is below the threshold we set above.
$tableFragment= Get-WMIObject Win32_Volume -filter "DriveType=3" -computer (get-content c:\scripts

\list.txt) | Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f

($_.capacity/1gb))}},@{Name="freespace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@

{Name="PercentFree";Expression={"{0:P2}" -f(($_.freespace/1gb)/($_.capacity/1gb))}} | Where

{$_.PercentFree -lt"20.00 %"} | sort-object -Property "freespace(GB)" | convertto-html -fragment

#####

Errors:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand



Any thoughts on this? all help is appreciated.

Subject: The RPC server is unavailable.
Posted by: goof1428 (view profile)
Posted on: Sunday, September 02, 2012 at 12:39 PM
Message: Great stuff Sean. Appreciate the time and effort.

I changed up the script so it can get a report on volumes as well. (searched google for that).
However my issue is I still get RPC errors on some servers and I had to raise the minimum to 20% for it on a few others. Is it a timeout issue? Can we tell the script to wait a few seconds to get WMI? like a pause?

######

#assemble together all of the free disk space data from the list of servers and only include it if the

percentage free is below the threshold we set above.
$tableFragment= Get-WMIObject Win32_Volume -filter "DriveType=3" -computer (get-content c:\scripts

\list.txt) | Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f

($_.capacity/1gb))}},@{Name="freespace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@

{Name="PercentFree";Expression={"{0:P2}" -f(($_.freespace/1gb)/($_.capacity/1gb))}} | Where

{$_.PercentFree -lt"20.00 %"} | sort-object -Property "freespace(GB)" | convertto-html -fragment

#####

Errors:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand



Any thoughts on this? all help is appreciated.

Subject: The RPC server is unavailable.
Posted by: goof1428 (view profile)
Posted on: Sunday, September 02, 2012 at 12:39 PM
Message: Great stuff Sean. Appreciate the time and effort.

I changed up the script so it can get a report on volumes as well. (searched google for that).
However my issue is I still get RPC errors on some servers and I had to raise the minimum to 20% for it on a few others. Is it a timeout issue? Can we tell the script to wait a few seconds to get WMI? like a pause?

######

#assemble together all of the free disk space data from the list of servers and only include it if the

percentage free is below the threshold we set above.
$tableFragment= Get-WMIObject Win32_Volume -filter "DriveType=3" -computer (get-content c:\scripts

\list.txt) | Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f

($_.capacity/1gb))}},@{Name="freespace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@

{Name="PercentFree";Expression={"{0:P2}" -f(($_.freespace/1gb)/($_.capacity/1gb))}} | Where

{$_.PercentFree -lt"20.00 %"} | sort-object -Property "freespace(GB)" | convertto-html -fragment

#####

Errors:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand



Any thoughts on this? all help is appreciated.

Subject: The RPC server is unavailable.
Posted by: goof1428 (view profile)
Posted on: Sunday, September 02, 2012 at 12:39 PM
Message: Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At C:\scripts\drivespacewithhtml.ps1:16 char:30
+ $tableFragment= Get-WMIObject <<<< Win32_Volume -filter "DriveType=3" -computer (get-content c:\sc
Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f($_.capacity/1
espace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@{Name="PercentFree";Expression={"
espace/1gb)/($_.capacity/1gb))}} | Where {$_.PercentFree -lt"20.00 %"} | sort-object -Property "frees
tto-html -fragment
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand




Great stuff Sean. Appreciate the time and effort.

I changed up the script so it can get a report on volumes as well. (searched google for that).
However my issue is I still get RPC errors on some servers and I had to raise the minimum to 20% for it on a few others. Is it a timeout issue? Can we tell the script to wait a few seconds to get WMI? like a pause?

######

#assemble together all of the free disk space data from the list of servers and only include it if the

percentage free is below the threshold we set above.
$tableFragment= Get-WMIObject Win32_Volume -filter "DriveType=3" -computer (get-content c:\scripts

\list.txt) | Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f

($_.capacity/1gb))}},@{Name="freespace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@

{Name="PercentFree";Expression={"{0:P2}" -f(($_.freespace/1gb)/($_.capacity/1gb))}} | Where

{$_.PercentFree -lt"20.00 %"} | sort-object -Property "freespace(GB)" | convertto-html -fragment

#####

Errors:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand



Any thoughts on this? all help is appreciated.

Subject: The RPC server is unavailable.
Posted by: goof1428 (view profile)
Posted on: Monday, September 03, 2012 at 8:25 PM
Message: Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At C:\scripts\drivespacewithhtml.ps1:16 char:30
+ $tableFragment= Get-WMIObject <<<< Win32_Volume -filter "DriveType=3" -computer (get-content c:\sc
Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f($_.capacity/1
espace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@{Name="PercentFree";Expression={"
espace/1gb)/($_.capacity/1gb))}} | Where {$_.PercentFree -lt"20.00 %"} | sort-object -Property "frees
tto-html -fragment
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand




Great stuff Sean. Appreciate the time and effort.

I changed up the script so it can get a report on volumes as well. (searched google for that).
However my issue is I still get RPC errors on some servers and I had to raise the minimum to 20% for it on a few others. Is it a timeout issue? Can we tell the script to wait a few seconds to get WMI? like a pause?

######

#assemble together all of the free disk space data from the list of servers and only include it if the

percentage free is below the threshold we set above.
$tableFragment= Get-WMIObject Win32_Volume -filter "DriveType=3" -computer (get-content c:\scripts

\list.txt) | Select SystemName,Caption,Label,@{Name="DiskSize(GB)";Expression={[decimal]("{0:N1}" -f

($_.capacity/1gb))}},@{Name="freespace(GB)";Expression={[decimal]("{0:N1}" -f($_.freespace/1gb))}},@

{Name="PercentFree";Expression={"{0:P2}" -f(($_.freespace/1gb)/($_.capacity/1gb))}} | Where

{$_.PercentFree -lt"20.00 %"} | sort-object -Property "freespace(GB)" | convertto-html -fragment

#####

Errors:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand



Any thoughts on this? all help is appreciated.

Subject: Inventing the wheel
Posted by: pmsousa (view profile)
Posted on: Friday, May 10, 2013 at 9:24 AM
Message: Hi Sean,

From a Powershell's perspective, this a nice article but aren't you "inventing the wheel"? To accomplish your goal there are several monitoring solutions based on SNMP or WMI queries that deliver the same results and on a better fashion. So why use a Powershell script with text files? That I used 20 years ago on old Unix or Novell networks...

Again, I started that from a Powershell's perspective/academic purpose it's fine but...

Subject: Great script!
Posted by: doalwa (view profile)
Posted on: Tuesday, September 24, 2013 at 3:42 AM
Message: Just wanted to congratulate you on your scripting skills and thank you for sharing your gift with us! :-)

Was able to put this script to good use on a couple of our servers. It worked without a hitch.

Since we're using the german version of Windows Server 2008 R2, I had to download the second iteration of the script from http://dl.dropbox.com/u/450727/scripts/diskspacereport-new.zip


Subject: Great script, but one question
Posted by: dbutts (view profile)
Posted on: Monday, March 31, 2014 at 6:14 AM
Message: How do I make this where it will only check ONE specific drive (e.g., the "T:\ "); not all drives on all servers ? Is there a way to do this with Get-WMIObject Win32_logicaldisk? Or do I have to take a different approach?

 

Top Rated

Migrating to Microsoft BPOS - Part II
 In his last article, Johan gave us a crystal clear guide to preparing to migrate from an on-premises... Read more...

Emulating the Exchange 2003 RUS for Out-of-Band Mailbox Provisioning in Exchange 2007
 Exchange's Recipient Update Service was important in Exchange 2000 or 2003 in order to complete the... Read more...

The Postmasters
 The Exchange Team introduces themselves, and keeps you up-to-date Read more...

For this Exchange Server Archiver, “Transparency” Fits
 Sometimes, it is a great relief when a user of your software gives it a tough test and then reports... Read more...

Hunting in Packs, Seamless-ness and Happy Holidays
 I attended DevConnections (Exchange) last month and was blown away by the technical talks. Speakers... Read more...

Most Viewed

Upgrade Exchange 2003 to Exchange 2010
  In this article, the first of two in which Jaap describes how to move from Exchange Server 2003... Read more...

Upgrade Exchange 2003 to Exchange 2010 - Part II
 In Jaap's second article on upgrading straight from Exchange Server 2003 to 2010, he explains how to... Read more...

Goodbye Exchange ExMerge, Hello Export-Mailbox
 ExMerge was a great way of exporting a mailbox to an Exchange PST file, or for removing all occurences... Read more...

Exchange E-mail Addresses and the Outlook Address Cache
 Because Exchange auto-complete cache uses X.500 addresses for e-mail sent to addresses within the... Read more...

Using Exchange 2007 for Resource Booking
 The process of booking various resources to go with a meeting room just got a whole lot easier with... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.