?
Solved

Help with a powershell script that generates server drive space data

Posted on 2011-11-01
8
Medium Priority
?
720 Views
Last Modified: 2012-05-12
Greetings Powershell Gurus,

Quite some time ago, I (with a significant amount of help from all of you) created a powershell script that basically reported the drive space for each of my servers.  The data was generated, dropped into an html report and emailed to me each morning.  I have tweaked the script and now all I get is a blank email.  I originally thought I may have messed up the code to pull the drive space data.  However, I have tested that code and it returns the appropriate drive space information.  That code is as follows:

  add-PSSnapin quest.activeroles.admanagement -ea SilentlyContinue

# Declare $OnlineServers as an array
$OnlineServers = @()

# Find all servers managed by CCIT and check to see if they respond to a ping
Get-QADComputer -managedby ccit | Sort-Object | foreach{
  $PingResult = Get-WmiObject -Query "SELECT * FROM win32_PingStatus WHERE address='$($_.Name)'"
  If ($PingResult.StatusCode -eq 0) {
 
    # If server responded to a ping , then it's current name is added to the array
    $OnlineServers += "$($_.Name)"
  }
}
## Execute Get-WMIObject for every element in the $OnlineServers array
## Added the filter to the WMI query rather than using Where-Object. No point in returning more than we must.
Get-WmiObject Win32_LogicalDisk -ComputerName $OnlineServers -Filter "DriveType='3'" | `
  Select-Object `
    @{n="Server";e={$_.SystemName}},`
    @{n="Drive Letter";e={$_.DeviceID}},`
    @{n="Volume Name";e={$_.VolumeName}},`
    @{n="Total Size (GB)";e={"{0:n2}" -f($_.size/1GB)}},`
    @{n="Free Space (GB)";e={"{0:n2}" -f($_.FreeSpace/1GB)}},`
    @{n="Used Space (GB)";e={"{0:n2}" -f(([Int64]$_.size/1gb) - ([Int64]$_.FreeSpace/1gb))}},`
    @{n="Percentage Used";e={"{0:P2}" -f((1-[Int64]$_.FreeSpace/[Int64]$_.Size))}}

When we originally made the script, I understood how Powershell generated the drive space data and how it emailed the report.  However, the conversion to HTML and the formatting of the report was confusing to me.  Since I have tested the data generation portion of the script and that is working, I think my issue is in the formatting of the HTML report.  I was hoping some of you could take a look at the code and help me find the issue that is causing my report to be blank.  The code of the entire script is given below.

add-PSSnapin quest.activeroles.admanagement -ea SilentlyContinue

#
### HEADER SECTION ###
 
$Header = "<style type='text/css'>`n" + `
  "td { width: 200px }`n" + `
  "th { text-align: left }`n" + `
  "</style>"


# Declare $OnlineServers as an array
$OnlineServers = @()

# Find all servers managed by MCIT and check to see if they respond to a ping
Get-QADComputer -managedby ccit | Sort-Object | foreach{
  $PingResult = Get-WmiObject -Query "SELECT * FROM win32_PingStatus WHERE address='$($_.Name)'"
  If ($PingResult.StatusCode -eq 0) {
 
    # If server responded to a ping , then it's current name is added to the array
    $OnlineServers += "$($_.Name)"
  }
}
# Execute Get-WMIObject for every element in the $OnlineServers array
# Added the filter to the WMI query rather than using Where-Object. No point in returning more than we must.
$Body = Get-WmiObject Win32_LogicalDisk -ComputerName $OnlineServers -Filter "DriveType='3'" | `
  Select-Object `
    @{n="Server";e={$_.SystemName}},`
    @{n="Drive Letter";e={$_.DeviceID}},`
    @{n="Volume Name";e={$_.VolumeName}},`
    @{n="Total Size (GB)";e={"{0:n2}" -f($_.size/1GB)}},`
    @{n="Free Space (GB)";e={"{0:n2}" -f($_.FreeSpace/1GB)}},`
    @{n="Used Space (GB)";e={"{0:n2}" -f(([Int64]$_.size/1gb) - ([Int64]$_.FreeSpace/1gb))}},`
    @{n="Percentage Used";e={"{0:P2}" -f((1-[Int64]$_.FreeSpace/[Int64]$_.Size))}} | `
  ConvertTo-HTML -Title "Server Disk Report" -Head $Header
 
 
### EMAIL REPORT SECTION ###
 
$Mail = New-Object System.Net.Mail.MailMessage( `
  "ServerAdmin@coconino.az.gov", `
  "nick@mycompany.com", `
  "Server Drive Space Report", `
  $Body)
 
$Mail.IsBodyHTML = $True
 
$Smtp = New-Object System.Net.Mail.SmtpClient("exchange.mycompany.internal")
$Smtp.Send($Mail)

Thanks in advance.
Regards,
Nick Dalmolin
0
Comment
Question by:ndalmolin_13
  • 4
  • 3
8 Comments
 
LVL 9

Accepted Solution

by:
chrismerritt earned 2000 total points
ID: 37065234
This works for me, hope you don't mind made some changes:

#Add QAD Snapin if needed
Add-PSSnapin Quest.ActiveRoles.ADManagement -ErrorAction "SilentlyContinue"

#Ping Status collection for all servers
$PingStatuses = @()

#Find all servers managed by MCIT and check to see if they respond to a ping
[array]$Computers = Get-QADComputer | Sort Name

#If one or more results are returned
if ($Computers.Count -gt 0)
{
	#Loop through all machine names
	foreach ($Computer in $Computers)
	{
		#Uses the DNSName to ensure correct DNS resolution
		$PingResult = Get-WmiObject -Query "SELECT * FROM Win32_PingStatus WHERE address='$($Computer.DNSName)'"
		#Add the current machines PingResult into the PingStatuses array
		$PingStatuses += $PingResult
	}
}
else
{
	Write-Host "no machines found, exiting"
	Start-Sleep 3
	exit
}

#Returns machines from the PingStatuses array where the StatusCode is 0 for ping status. i.e. all machines that are alive.
$OnlineServers = @()
$PingStatuses | ? {$_.StatusCode -eq 0} | % {$OnlineServers += $_.Address}

#Checks to see if any online servers in the array
if ($OnlineServers.Count -gt 0)
{
	### HEADER SECTION ###
	 
	$Header = "<style type='text/css'>`n" + `
	  "td { width: 200px }`n" + `
	  "th { text-align: left }`n" + `
	  "</style>"

	#Execute Get-WMIObject for every element in the $OnlineServers array
	#Added the filter to the WMI query rather than using Where-Object. No point in returning more than we must.
	$Body = Get-WmiObject Win32_LogicalDisk -ComputerName $OnlineServers -Filter "DriveType='3'" | `
	  Select-Object `
		@{n="Server";e={$_.SystemName}},`
		@{n="Drive Letter";e={$_.DeviceID}},`
		@{n="Volume Name";e={$_.VolumeName}},`
		@{n="Total Size (GB)";e={"{0:n2}" -f($_.size/1GB)}},`
		@{n="Free Space (GB)";e={"{0:n2}" -f($_.FreeSpace/1GB)}},`
		@{n="Used Space (GB)";e={"{0:n2}" -f(([Int64]$_.size/1gb) - ([Int64]$_.FreeSpace/1gb))}},`
		@{n="Percentage Used";e={"{0:P2}" -f((1-[Int64]$_.FreeSpace/[Int64]$_.Size))}} | `
	  ConvertTo-HTML -Title "Server Disk Report" -Head $Header
	 
	 
	### EMAIL REPORT SECTION ###
	 
	$Mail = New-Object System.Net.Mail.MailMessage( `
	  "sender@domain.com", `
	  "recipient@domain.com", `
	  "Server Drive Space Report", `
	  $Body)

	#This sets the body type to HTML
	$Mail.IsBodyHTML = $True
	 
	$Smtp = New-Object System.Net.Mail.SmtpClient("Server Address Here")
	$Smtp.Send($Mail)
}
else
{
	Write-Host "No Online machines found, exiting"
	Start-Sleep 3
	exit
}

Open in new window

0
 
LVL 9

Expert Comment

by:chrismerritt
ID: 37065239
You will want to change Line 8 to this, I had the filter off for testing.

[array]$Computers = Get-QADComputer -managedby ccit | Sort Name
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 37066759
chrismerritt,
any reason for not using Test-Connection instead of WMI Win32_PingStatus? WMI is costly in general.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 9

Expert Comment

by:chrismerritt
ID: 37066805
Test-Connection works in a similar way to be honest (It actually uses WMI Win32_PingStatus anyway). I just used the logic from the OP's script.

"Unlike the traditional "ping" command, Test-Connection returns a Win32_PingStatus object that you can investigate in Windows PowerShell, but you can use the Quiet parameter to force it to return only a Boolean value."

Test-Connection, like a lot of the built in PowerShell commands is simpler to write out and control but they will both get the job done.

Speed should be a bigger concern if there are a lot of servers to process, if the OP only has like 5 servers to check then it probably will make little to no difference.



0
 
LVL 1

Author Comment

by:ndalmolin_13
ID: 37083533
Hello All,

I've been out sick until this morning.  Sorry about that.  I've tried the changes that Chris made in his post above, but my email is still showing up blank.  When I break the script out into sections, the data is being pulled corrrectly, so I think my issue is in the formatting.
0
 
LVL 9

Expert Comment

by:chrismerritt
ID: 37088523
Is it possible your mail server is stripping out the content? as I am 100% sure my code worked when I ran it and I got an email with the right content in it as well!
0
 
LVL 1

Author Comment

by:ndalmolin_13
ID: 37094667
I will check.  Thanks
0
 
LVL 1

Author Closing Comment

by:ndalmolin_13
ID: 37102884
I think I found the issue.  Thanks for your help
0

Featured Post

Creating Active Directory Users from a Text File

If your organization has a need to mass-create AD user accounts, watch this video to see how its done without the need for scripting or other unnecessary complexities.

Question has a verified solution.

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

This script can help you clean up your user profile database by comparing profiles to Active Directory users in a particular OU, and removing the profiles that don't match.
Previously, on our Nano Server Deployment series, we've created a new nano server image and deployed it on a physical server in part 2. Now we will go through configuration.
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…
Loops Section Overview

850 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