Solved

Powershell Script to notify if Disk Space is less than Certain %

Posted on 2010-09-22
14
2,895 Views
Last Modified: 2012-08-14
Hi All,

I am currently trying to put together a script that will notify me when available disk space goes below a certain percentile.  I have scoured the Internet and came across the following website:

http://ye110beard.spaces.live.com/blog/cns!952F95CB5DE3F349!2472.entry

The above website seems to hold the answer I require however the get-wmiobject win32_volume that is mentioned in the code does not seem to work in powershell for me.  When running the script (with the appropriate fields changed to include smtp info) I recieve the following error below:


Get-WmiObject : Invalid class
At C:\PS_Scripts\InProgress\Hard_Disk.ps1:3 char:25
+ $driveinfo=get-wmiobject <<<<  win32_volume | where { $_.driveletter -eq 'C:' } | select-object freespace, capacity, drivetype, driveletter
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

I have also verified that I am running PowerShell v2 as the script mentions it requires.


Here is the code copied from the site:

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

# Change C: to whichever letter you'd like monitored

$driveinfo=get-wmiobject win32_volume | where { $_.driveletter -eq 'C:' } | select-object freespace, capacity, drivetype, driveletter

# 10 percent 10/100

$Percent=.10

# XXX % of maximum space is our warning level
$WarningLevel=$driveinfo.capacity *  $Percent

if ($driveinfo.freespace -lt $WarningLevel)
{
send-mailmessage -from "Server01 <server01@contoso.local>" -to "MyAdministrator <networkAdmin@contoso.local>" -subject "I'm all out of space" -body "I'm all out of space, I'm so lost without you, please get me some more now, the users are crying...I have $driveinfo.freespace bytes leftover! Hurry!" -priority High -dno onSuccess, onFailure -smtpServer smtp.contoso.local
}

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


I have tried replacing "get-wmiobject win32_volume" with "get-wmiobject win32_LogicalDisk" as I have found from a similar script, but while this does not return an error, it doesn't return any information either.


Any help provided would be greatly appreciated!
0
Comment
Question by:RyanMyers83
  • 7
  • 6
14 Comments
 

Author Comment

by:RyanMyers83
ID: 33735330
I would also like to change this around to run from a remote Server as well if possible.  I'm sure there is a way to do it, but I would be happy if I just got this to work locally and set as a scheduled task.
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 33735582

Win32_Volume is only available from Vista / 2008 upwards. What operating system are you running this against?

You should be able to use...


Get-WmiObject Win32_LogicalDisk -ComputerName "TheComputer" -Filter "Name='C:'" |
  Select-object FreeSpace, Size, DriveType, Name


Then do your math using .Size instead of .Capacity :)

HTH

Chris
0
 

Author Comment

by:RyanMyers83
ID: 33735710
I was testing the script against my local computer running XP Pro, however I will be aiming this script at a 2003 Server once I feel it works properly.  I will try making the adjustments you mentioned and update you with progress.  Thanks for the comment!
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 33735748

Cool, the WMI class above should be pretty easy, it works against all moderately recent versions of Windows (at the very least XP / 2003 up).

Chris
0
 

Author Comment

by:RyanMyers83
ID: 33737116
I'm afraid I'm not as good with Powershell as some users on here but I'm trying.  I have played with Powershell for a couple hours trying to lookup and use different combination's but I can't seem to get the code to work.  I tried to change it around from using a % of free space to a set number of 150GB since this would be more useful in my particular case.  

I know this is completely wrong, but maybe it might illustrate my intentions:

# Get C: free space in GB
$WarningLevel=$driveinfo.freespace "C:" /(1024*1024*1024)

if ($driveinfo.freespace -lt 150)
{
(need to output data to file, e-mail preferably)
}



I also have a feeling that the e-mail section won't work since I did not provide credentials for the user account.  I have seen in other scripts that you can output the result of whatever you are trying to do to an e-mail but some include a line to add e-mail credentials (password).  I will have to try mashing parts of one of those scripts into this one towards the end.  
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 33737616

No worries, you can ask as many questions about this as you want you know? :)

Anyway, it's a good illustration, and I did enjoy your message body :-D

Regarding the mail, it will send without authentication provided the SMTP port is open and it's not relaying (the recipient is internal).

Chris
# The threshold, anything below this will generate a warning.
# Current value is 5%, 0.05 when we use a numeric value
$Threshold = 0.05

# How to read a list of computers from a text file
Get-Content "SomeFile.txt" | ForEach-Object {

  # This is the computer name, a line from the text file: $_
  $Computer = $_

  # Convert any values up to Gb, and add a custom property called PercentFree to the output
  # This can be made to execute for all disks by removing the filter for Name (type 3 represents physical disks)
  # The sizes and percentage will be reported to two decimal places (N = Number, P = Percentage)
  $DiskReport = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter "Name='C:' AND DriveType='3'" |
    Select-object Name, DriveType, 
      @{n='FreeSpace';e={ '{0:N2}' -f ($_.FreeSpace / 1Gb) }},
      @{n='Size';e={ '{0:N2}' -f ($_.Size / 1Gb) }},
      @{n='PercentFree';e={ '{0:P2}' -f ($_.FreeSpace / $_.Size) }}

  # Filter the list further, return everything with less than $Threshold % remaining
  $DiskReport | Where-Object { $_.PercentFree -lt $Threshold } | ForEach-Object {

    # We're generating an e-mail per disk. We don't have to, we can combine everything into a single report, 
    # or one per server, or do something else

    Send-MailMessage -From "Server01 <server01@contoso.local>" -To "MyAdministrator <networkAdmin@contoso.local>" `
      -Subject "I'm all out of space" 
      -Body "I'm all out of space, I'm so lost without you, please get me some more now, the users are crying...I have $($_.FreeSpace) Gb left over! Hurry!" `
      -Priority High -DNO onSuccess, onFailure -SmtpServer smtp.contoso.local

  }
}

Open in new window

0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 70

Expert Comment

by:Chris Dent
ID: 33737746

A few bits of the snippet above comes without significant explanation (the formatters, the custom properties, etc). If you'd like me to expand on anything please do say, I only didn't want to overload the snippet with comments before you've had a chance to prod and play.

Chris
0
 

Author Comment

by:RyanMyers83
ID: 33737891
Messing with it now...Thanks Chris
0
 

Author Comment

by:RyanMyers83
ID: 33738170
Looks like it may be failing at the e-mail section, but because it doesn't seem to recognize -Body as an argument.  I tried bringing -body up to the same line as -subject and the colors changed from gray to blue in the powershell_ise as if I did something correct - but alas...no workie.  

I think the hardest part about this for me, is I don't know what the names of all the arguments are so I don't know how to change things around.  I pulled this snippet below from another powershell script I managed to get to work that used e-mail...but they use a different method to define items:

##################
# Mail variables #
##################
$enablemail="yes"
$smtpServer = "mail.test.local"
$mailfrom = "user <from@test.com"
$mailto = "test@test.com"



######################
# E-mail HTML output #
######################
if ($enablemail -match "yes")
{
$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($filelocation)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = $mailfrom
$msg.To.Add($mailto)
$msg.Subject = “subject”
$msg.Body = “body”
$msg.Attachments.Add($att)
$smtp.Send($msg)
}


Not that I'm trying to change what you already posted - I could care less which method I use.  I just need something that works.  
0
 
LVL 70

Accepted Solution

by:
Chris Dent earned 250 total points
ID: 33738615

You can find the names nice and easily:

Get-Help Send-MailMessage
Or:
Get-Help Send-MailMessage -Full | more

In PS these tend to be some of the most useful commands:


Get-Help
Get-Command
Get-Member
Format-List *


Anyway, I missed a ` character off, that's what's letting it spread the parameters out across lines, it escapes the line break.

Chris
# The threshold, anything below this will generate a warning.
# Current value is 5%, 0.05 when we use a numeric value
$Threshold = 0.05

# How to read a list of computers from a text file
Get-Content "SomeFile.txt" | ForEach-Object {

  # This is the computer name, a line from the text file: $_
  $Computer = $_

  # Convert any values up to Gb, and add a custom property called PercentFree to the output
  # This can be made to execute for all disks by removing the filter for Name (type 3 represents physical disks)
  # The sizes and percentage will be reported to two decimal places (N = Number, P = Percentage)
  $DiskReport = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter "Name='C:' AND DriveType='3'" |
    Select-object Name, DriveType, 
      @{n='FreeSpace';e={ '{0:N2}' -f ($_.FreeSpace / 1Gb) }},
      @{n='Size';e={ '{0:N2}' -f ($_.Size / 1Gb) }},
      @{n='PercentFree';e={ '{0:P2}' -f ($_.FreeSpace / $_.Size) }}

  # Filter the list further, return everything with less than $Threshold % remaining
  $DiskReport | Where-Object { $_.PercentFree -lt $Threshold } | ForEach-Object {

    # We're generating an e-mail per disk. We don't have to, we can combine everything into a single report, 
    # or one per server, or do something else

    Send-MailMessage -From "Server01 <server01@contoso.local>" -To "MyAdministrator <networkAdmin@contoso.local>" `
      -Subject "I'm all out of space" `
      -Body "I'm all out of space, I'm so lost without you, please get me some more now, the users are crying...I have $($_.FreeSpace) Gb left over! Hurry!" `
      -Priority High -DNO onSuccess, onFailure -SmtpServer smtp.contoso.local

  }
}

Open in new window

0
 

Author Comment

by:RyanMyers83
ID: 33738775
Getting closer...at least I'm now getting an e-mail. The failure is now as shown below:

Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At C:\PS_Scripts\InProgress\Hard_Disk.ps1:14 char:30
+   $DiskReport = Get-WmiObject <<<<  Win32_LogicalDisk -ComputerName $Computer -Filter "Name='C:' AND DriveType='3'" |
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand


An email is sent to me structured as it should be in the template, however there is no value input for freespace as there should be.  

I have verified I am using an account with proper credentials to execute the script across the domain. I have also verified that the RPC Service is running at the remote locations as indicated in the error.  The error marker indicates a problem with the WmiObject reference...not sure why.  
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 33746622

Sorry for the late reply.

RPC server is unavailable isn't a code error really. It's generally a network level error, either the name doesn't resolve or the system cannot be reached.

To test that, run:

nslookup TheComputer
ping TheComputer
Get-WmiObject Win32_ComputerSystem -Computer TheComputer

Only when that succeeds will we get useful information in the e-mail. It shouldn't really have sent you the e-mail at all if it failed to get anything useful.

Chris
0
 

Author Comment

by:RyanMyers83
ID: 33778656
This question is not abandoned...I simply have not had a chance to try the new solution.  I will reply back when I get a chance
0

Featured Post

Complete VMware vSphere® ESX(i) & Hyper-V Backup

Capture your entire system, including the host, with patented disk imaging integrated with VMware VADP / Microsoft VSS and RCT. RTOs is as low as 15 seconds with Acronis Active Restore™. You can enjoy unlimited P2V/V2V migrations from any source (even from a different hypervisor)

Join & Write a Comment

Learn about cloud computing and its benefits for small business owners.
This article will help you understand what HashTables are and how to use them in PowerShell.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now