15 August 2011

Disk Space Monitoring and Early Warning with PowerShell

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.

1339-image002.jpg

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

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.

Keep up to date with Simple-Talk

For more articles like this delivered fortnightly, sign up to the Simple-Talk newsletter

This post has been viewed 112134 times – thanks for reading.

Tags: , , , , , , ,

  • Rate
    [Total: 63    Average: 4.6/5]
  • Share

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)

Follow on

View all articles by Sean Duffy

  • laerte

    Nice
    Nice one my friend. Keep up the good work :).. and thanks for the mention.

  • Shogan

    Thanks
    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!

  • Jim P.

    excellent script…if I could only get it to work!
    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.

  • Jim P.

    excellent script…if I could only get it to work!
    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.

  • Jim P.

    awesome!
    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.

  • Shogan

    Thanks Jim
    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

  • CypherBit

    Works only if System Locale is US-EN
    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.

  • Shogan

    Locale
    Hi CypherBit, this is interesting. I’ll test it out and see if I can find a workaround for you.

    Thanks,
    Sean

  • CypherBit

    Locale
    Thank you very much Sean, looking forward to it. It’s a great scipt indeed.

  • Shogan

    Locale
    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.

  • Frenjon

    Same problem as CypherBit
    Also Locale related (i think)..
    Nothing happens – even if I set [decimal]$thresholdspace = 80

    PS C:ScriptsDisk-Space> get-host
    CurrentCulture : da-DK
    CurrentUICulture : en-US

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

  • Shogan

    Locale issues – should be resolved now
    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

  • CypherBit

    Works great
    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.

  • Shogan

    CypherBit
    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

  • CypherBit

    Sean
    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.

  • Frenjon

    Works!
    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..

  • Shogan

    Awesome
    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

  • Derek Wharton

    Love it……
    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?

  • Derek Wharton

    Love it……
    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?

  • Derek Wharton

    Love it……
    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?

  • Derek Wharton

    Oops
    I apologize for the multiple post

  • Old Dog

    Awesome
    Sean this script is great, keep up the good work.

  • Shogan

    Error handling
    @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!

  • ous00ner

    Perhaps a noob error?
    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:scriptspowershelldiskspace.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

  • ous00ner

    Perhaps a noob error?
    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:scriptspowershelldiskspace.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

  • Shogan

    reply
    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

  • indomanna

    Script terminated without checking the rest of the servers
    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

  • Sam.Cayze

    Empty Pipe error
    C:Documents and Settingsuser>powershell.exe -command “& ‘C:ScriptsDiskSpaceAlertdiskspace.ps1’ ‘C:ScriptsDiskSpaceAlertList.txt'”

    An empty pipe element is not allowed.
    At C:ScriptsDiskSpaceAlertdiskspace.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

  • dbamohsin

    Error trapping?
    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 “$filelocationhostList.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
    }
    }

  • dbamohsin

    repsonses to above comments
    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
    http://www.dbamohsin.wordpress.com

  • ColinTheDBA

    Disk Space Script error
    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.

  • wald

    No Email
    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?

  • LevelTen

    Pipe Errors
    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

  • neiltunnah

    Most Excellent
    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.

  • goof1428

    rpc server unavailable
    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.

  • goof1428

    The RPC server is unavailable.
    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.

  • goof1428

    The RPC server is unavailable.
    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.

  • goof1428

    The RPC server is unavailable.
    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.

  • goof1428

    The RPC server is unavailable.
    Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
    At C:scriptsdrivespacewithhtml.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.

  • goof1428

    The RPC server is unavailable.
    Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
    At C:scriptsdrivespacewithhtml.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.

  • pmsousa

    Inventing the wheel
    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…

  • doalwa

    Great script!
    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

  • dbutts

    Great script, but one question
    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?

  • yorkman

    Still get email even though threshold doesn’t match 10%
    I’m running the .bat file and I get the email but I shouldn’t get any emails since all the volumes have well more than 10% free space.

    Great looking script and email otherwise.

    Any ideas why it might not be working for me?

  • yorkman

    Still get email even though threshold doesn’t match 10%
    I’m running the .bat file and I get the email but I shouldn’t get any emails since all the volumes have well more than 10% free space.

    Great looking script and email otherwise.

    Any ideas why it might not be working for me?

  • yorkman

    Never mind, got it working.
    Must’ve had a typo somewhere.

  • kk19115

    Mapped volumes
    This is excellent and works perfectly for my physical drives. I see in some comments that someone was working on having it check mapped drives as well.

    I need this to check mapped drives. Can you help me?

  • kk19115

    Mapped volumes only
    I got this working for only mapped volumes by changing this line:

    $disks = Get-WmiObject -ComputerName $computer -class "win32_mappedlogicaldisk" -namespace "rootCIMV2"

  • killerb255

    Exact Firewall Rules (Ports, etc.)
    So what are the exact firewall rules that need to be added to the remote servers that are being queried for disk info? I have one server that I keep getting "The RPC Server Is Unavailable" on, but that’s only if Windows Firewall is turned on. If it’s turned off, then the script will gather the appropriate data.

  • Shashank17287

    Get-WmiObject : Cannot validate argument on parameter ‘ComputerName’
    Hi Sean,

    This Script is excellent and gives me the desired output on low disk space issues for my lab environment.
    I referred the same script to my friend for his lab environment and he received the below error:
    "Get-WmiObject : Cannot validate argument on parameter ‘ComputerName’. The argument is null or empty. Supply an
    argument that is not null or empty and then try the command again.
    At D:Scriptdiskspace.ps1:17 char:45
    + $tableFragment= Get-WMIObject -ComputerName $computers Win32_LogicalDisk | Where …
    + ~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Get-WmiObject], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetWmiObjectCommand

    Please help

  • Shashank17287

    Get-WmiObject : Cannot validate argument on parameter ‘ComputerName’
    I figured out it was a space issue.
    Script is now working.

  • firat

    Hi
    First of all thank you for sharing your knowledge,
    I have a problem about connecting the SMTP server, i think i have to add password but i dont know how

  • Malvarkie

    Hi

    I am getting below Error. How fix this error so I can start using the script?

    Error

    Get-WMIObject : Invalid parameter
    At line:1 char:17
    + $tableFragment= Get-WMIObject -ComputerName $computers Win32_LogicalDisk | Where …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

    Thx