Solved

Having trouble getting drive information on servers using powershell

Posted on 2009-07-09
4
932 Views
Last Modified: 2012-08-13
Hello PowerShell Experts,

My PowerShell project for the day is to create a script that ping all the servers in my domain and provide disk information for  any servers that are online.  The script will then put this information into the body of an email and send it to my mailbox.  I have some PowerShell code that will list the servers on the domain, so I wasnt too worried about getting that part of the script to work.  I decided to start out with the part of the script that will return disk information.  To make things run a bit faster, I decided to collect disk information on one server.  By going through previous posts here at Experts-Exchange and reading different resources on the web and going through my Powershell books, here is the code I came up with:

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

### SINGLE SERVER TO QUERY SECTION ###

$OnlineServers = "Mail01"

### BODY OF REPORT SECTION ###

$Body = Get-WmiObject -Query "select * from win32_logicaldisk" -ComputerName $OnlineServers | `
Where-Object {$_.drivetype -eq "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@test.com", `
  "nick@test", `
  "Server Disk Report", `
  $Body)
 
$Mail.IsBodyHTML = $True
 
$Smtp = New-Object System.Net.Mail.SmtpClient("cas-hub01.test.states")
$Smtp.Send($Mail)

The code above worked great.  I received the email report in the format I expected shown below (trust me, this formatting is good in an email, just not in this post):

Server      Drive Letter      Volume Name      Total Size (GB)      Free Space (GB)      Used Space (GB)      Percentage Used
MAIL01      C:            67.01      38.02      29.00      43.27 %
MAIL01      D:      Exchange Databases      1,465.95      1,309.17      156.79      10.70 %
MAIL01      E:      Exchange Logs      366.49      362.49      4.00      1.09 %

At this point, Im thinking all I need to do now is insert the code at the top of the script that will go out and get a list of all the servers that are online on my domain.  Here is a copy of the script after this code had been added:

### HEADER SECTION ###

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

### COMPILE A LIST OF SERVERS ONLINE SECTION ###

$Servers = Get-QADComputer -OSName "Windows*Server*" | foreach{$_.name} | Sort-Object
$OnlineServers = ""
Foreach ($item in $Servers) {
$PingResult = Get-WmiObject -Query "Select * From win32_PingStatus Where address='$item'"
If ($PingResult.statuscode -eq 0) {
      $OnlineServers = $OnlineServers+ "$item`n"
      }
}

### BODY OF REPORT SECTION ###

$Body = Get-WmiObject -Query "select * from win32_logicaldisk" -ComputerName $OnlineServers | `
Where-Object {$_.drivetype -eq "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@test.com", `
  "nick@test", `
  "Server Disk Report", `
  $Body)
 
$Mail.IsBodyHTML = $True
 
$Smtp = New-Object System.Net.Mail.SmtpClient("cas-hub01.test.states")
$Smtp.Send($Mail)

The script is not working with the code that compiles the list of servers online.  The error Im getting is:

Bad path to object (Exception from HRESULT: 0x80080004 (CO_E_BAD_PATH))
At :line:16 char:21
+ $Body = Get-WmiObject <<<<  -Query "select * from win32_logicaldisk" -ComputerName $OnlineServers | `

From what I can gather, PowerShell is having problems using the list of servers created.  Any ideas on how to solve this issue?

As always, any and all help is appreciated.

Regards,
Nick
0
Comment
Question by:ndalmolin_13
  • 2
  • 2
4 Comments
 
LVL 70

Accepted Solution

by:
Chris Dent earned 500 total points
Comment Utility

Morning Nick :)

You run into a problem with the list of servers you're building. Get-WMIObject will happily accept a list of server names if they're in an array. It's the line-break delimited string it doesn't like (Get-WMIObject sees the entire thing as a single server name).

A few comments in-line :)

Chris
### HEADER SECTION ###
 

$Header = "<style type='text/css'>`n" + `

  "td { width: 200px }`n" + `

  "th { text-align: left }`n" + `

  "</style>"
 

### COMPILE A LIST OF SERVERS ONLINE SECTION ###
 

# Declare $OnlineServers as an array

$OnlineServers = @()

Get-QADComputer -OSName "Windows*Server*" | %{

  $PingResult = Get-WmiObject -Query "SELECT * FROM win32_PingStatus WHERE address='$($_.Name)'"

  If ($PingResult.StatusCode -eq 0) {
 

    # Add the current name to the array

    $OnlineServers += "$($_.Name)"

  }

}
 

### BODY OF REPORT SECTION ###
 

# 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@test.com", `

  "nick@test", `

  "Server Disk Report", `

  $Body)

 

$Mail.IsBodyHTML = $True

 

$Smtp = New-Object System.Net.Mail.SmtpClient("cas-hub01.test.states")

$Smtp.Send($Mail)

Open in new window

0
 
LVL 1

Author Comment

by:ndalmolin_13
Comment Utility
Hello Chris,

Thanks for the response.  I'm out of the office today, but will give your suggestion a try Monday morning.  Have a good weekend.
0
 
LVL 70

Expert Comment

by:Chris Dent
Comment Utility

No worries, have a good weekend too :)

Chris
0
 
LVL 1

Author Closing Comment

by:ndalmolin_13
Comment Utility
This worked great.  I think I should start using arrays more instead of simple lists.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Utilizing an array to gracefully append to a list of EmailAddresses
The article will show you how you can maintain a simple logfile of all Startup and Shutdown events on Windows servers and desktops with PowerShell. The script can be easily adapted into doing more like gracefully silencing/updating your monitoring s…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

771 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

12 Experts available now in Live!

Get 1:1 Help Now