• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4380
  • Last Modified:

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

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
RyanMyers83
Asked:
RyanMyers83
  • 7
  • 6
1 Solution
 
RyanMyers83Author Commented:
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
 
Chris DentPowerShell DeveloperCommented:

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
 
RyanMyers83Author Commented:
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
Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

 
Chris DentPowerShell DeveloperCommented:

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
 
RyanMyers83Author Commented:
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
 
Chris DentPowerShell DeveloperCommented:

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
 
Chris DentPowerShell DeveloperCommented:

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
 
RyanMyers83Author Commented:
Messing with it now...Thanks Chris
0
 
RyanMyers83Author Commented:
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
 
Chris DentPowerShell DeveloperCommented:

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
 
RyanMyers83Author Commented:
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
 
Chris DentPowerShell DeveloperCommented:

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
 
RyanMyers83Author Commented:
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

[Webinar] Kill tickets & tabs using PowerShell

Are you tired of cycling through the same browser tabs everyday to close the same repetitive tickets? In this webinar JumpCloud will show how you can leverage RESTful APIs to build your own PowerShell modules to kill tickets & tabs using the PowerShell command Invoke-RestMethod.

  • 7
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now