Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

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

Posted on 2010-09-22
14
Medium Priority
?
4,097 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
13 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 71

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
 The Evil-ution of Network Security Threats

What are the hacks that forever changed the security industry? To answer that question, we created an exciting new eBook that takes you on a trip through hacking history. It explores the top hacks from the 80s to 2010s, why they mattered, and how the security industry responded.

 
LVL 71

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 71

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
 
LVL 71

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 71

Accepted Solution

by:
Chris Dent earned 1000 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 71

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

 The Evil-ution of Network Security Threats

What are the hacks that forever changed the security industry? To answer that question, we created an exciting new eBook that takes you on a trip through hacking history. It explores the top hacks from the 80s to 2010s, why they mattered, and how the security industry responded.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The following article is intended as a guide to using PowerShell as a more versatile and reliable form of application detection in SCCM.
In the absence of a fully-fledged GPO Management product like AGPM, the script in this article will provide you with a simple way to watch the domain (or a select OU) for GPOs changes and automatically take backups when policies are added, removed o…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
Screencast - Getting to Know the Pipeline

783 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