VMware Cloud Community
gerf0727
Enthusiast
Enthusiast
Jump to solution

Powershell/PowerCLI Dynamic Email Message Body with Datastores

Hello the following is related to this email but I am stuck in rounding the numbers

Powershell/PowerCLI Dynamic Email Message Body

I am getting an email with the following info:

Datastore HealthCheck vCenter

Datastore Space Available
Datastore                                UsedGB                                 Free GB                                 Perc Free
name1                                        273.30078125                         274.25                                    99%
name2                                        273.30078125                         274.25                                    99%
name3                                        268.466796875                         274.25                                    99%
name4                                        273.30078125                         274.25                                    99%

Three things that I am stuck: First, the UsedGB value, woud like to have it with only two decimal points, instead of having 273.30078125, nice to have 273.30. Second I am not getting the right percentage. Third: How do i sort the the Perf Free values from the lowest to the bigger percentage? Thanks for your help

Code:

$msg.Subject = "vCenter Datastore Health CompanyvCenter"  
    $array0 = @()
    $array1 = @()
    $array2 = @()
    start-sleep 1
    connect-VIServer $vcserver
    $array0 += Get-Datastore | Select-Object -ExpandProperty Name
    $array1 += Get-Datastore | Select-Object -ExpandProperty FreeSpaceGB
    $array2 += Get-Datastore | Select-Object -ExpandProperty CapacityGB
    $UsedSpace = [math]::round(($array2[$i] - $array1[$i]),2)
    $PercFree = [math]::Round((100 * $array1[$i] / $array2[$i]),0)
    $String0 = "$PercFree$Percent"
    $i = 0
    $j = 0
    # Header
    $msg.Body += "<FONT COLOR=black>Datastore HealthCheck CompanyvCenter</FONT><BR><BR>"
    # Datastore header
    $msg.Body += "<B><FONT COLOR=black>Datastore Space Available</FONT></B><BR>"
    $msg.Body += "<B><FONT COLOR=black>Datastore</FONT></B><B><FONT COLOR=black>                                             UsedGB</FONT></B>`
    <B><FONT COLOR=black>                                Free GB</FONT></B>`
    <B><FONT COLOR=black>                                Perc Free</FONT></B>"
    # Datasores
    0..($array0.Count-1) | %{
    $msg.Body += "<BR><FONT COLOR=Black>" + $array0[$_]
    $msg.Body += "</FONT>                                        <FONT COLOR=Black>" + [math]::round(($array2[$_] - $array1[$_]),2)
    #$msg.Body += "</FONT>                                        <FONT COLOR=Black>" + $array1[$_]
    $msg.Body += "</FONT>                         <FONT COLOR=Black>" + $array2[$_] + "</FONT>"
    #$msg.Body += "</FONT>                         <FONT COLOR=Black>" + [math]::round(($array2[$_] - $array1[$_]),2) + "</FONT>"
    $msg.Body += "                                     <FONT COLOR=Black>" + [math]::Round((100 * $array1[$i] / $array2[$i]),0)+"$Percent"+"</FONT><BR>"}
    $msg.Attachments.Add($att1)
    $msg.IsBodyHTML = $true
    $smtp.Send($msg)
    $att1.Dispose()
    Disconnect-VIServer $vcserver -Confirm:$false

Tags (2)
30 Replies
gerf0727
Enthusiast
Enthusiast
Jump to solution

I think there is something wrong with the following:

Function Report-Datastore {

    $output = @()

    Get-Datastore | % {$props = [ordered]@{'Name'=$_.Name;'UsedSpace'=[math]::Round(($_.CapacityGB - $_.FreeSpaceGB),2);'PercFree'=[math]::Round((100 * ($_.FreeSpaceGB/$_.CapacityGB)),0)}

        $output += New-Object -TypeName PSCUstomObject -Property $props

    }

    $output

}

0 Kudos
fabiendibot
Enthusiast
Enthusiast
Jump to solution

if you do

Function Report-Datastore {

    $output = @()

    Get-Datastore | % {

        $props = @{'Name'=$_.Name;

                            'UsedSpace' = [math]::Round(($_.FreeSpaceGB - $_.CapacityGB),2);

                            'PercFree' = [math]::Round((($_.CapacityGB/$_.FreeSpaceGB)*100),0)}

        $output += New-Object -TypeName PSCUstomObject -Property $props

    }

    $output

}

Connect-VIServer $vcserver

Report-Datastore

Does it work ?

0 Kudos
gerf0727
Enthusiast
Enthusiast
Jump to solution

But dont u need to have a ForEach on that function ?

Yes, i got results...

PercFree  : 100

Name      : cbesx06Local

UsedSpace : -0.95

PercFree  : 100

Name      : cbesx05Local

UsedSpace : -0.95

Message was edited by: gerf0727

0 Kudos
fabiendibot
Enthusiast
Enthusiast
Jump to solution

% is an alias of Foreach Smiley Happy

-> Get-Alias %

-> Get-Alias Foreach

0 Kudos
gerf0727
Enthusiast
Enthusiast
Jump to solution

Ok, I commented the following line:

$html_DS = Report-Datastore | Sort-Object PercFree | ConvertTo-HTML -Fragment | Out-String | Set-AlternatingCSSClasses -CSSEvenClass 'even' -CssOddClass 'odd'

and removed the CSSClasses part

$html_DS = Report-Datastore | Sort-Object PercFree | ConvertTo-HTML -Fragment | Out-String

$html_DS

Got the email with the following, it works but will be nice if we can format it

Capture.PNG

0 Kudos
fabiendibot
Enthusiast
Enthusiast
Jump to solution

What do yo mean by "format it" ?

You just have to  add object memebrs in $output var and you'll have ohter column ....

It worked for me with these function and $style variable...

function Set-AlternatingCSSClasses {

    [CmdletBinding()]

    param(

        [Parameter(Mandatory=$True,ValueFromPipeline=$True)]

        [string]$HTMLFragment,

       

        [Parameter(Mandatory=$True)]

        [string]$CSSEvenClass,

       

        [Parameter(Mandatory=$True)]

        [string]$CssOddClass

    )

    [xml]$xml = $HTMLFragment

    $table = $xml.SelectSingleNode('table')

    $classname = $CSSOddClass

    foreach ($tr in $table.tr) {

        if ($classname -eq $CSSEvenClass) {

            $classname = $CssOddClass

        } else {

            $classname = $CSSEvenClass

        }

        $class = $xml.CreateAttribute('class')

        $class.value = $classname

        $tr.attributes.append($class) | Out-null

    }

    $xml.innerxml | out-string

}

$style = @"

<style>

body {

    color:#333333;

    font-family:Calibri,Tahoma;

    font-size: 10pt;

}

h1 {

    text-align:center;

}

h2 {

    border-top:1px solid #666666;

}

th {

    font-weight:bold;

    color:#eeeeee;

    background-color:#333333;

}

.odd  { background-color:#ffffff; }

.even { background-color:#dddddd; }

</style>

"@

gerf0727
Enthusiast
Enthusiast
Jump to solution

Cool man. Thanks so much.  I am all set.

0 Kudos
gerf0727
Enthusiast
Enthusiast
Jump to solution

Fabien, not sure if you can help through this same thread. You helped me with the script and output sorts by PercFree. I did added another column to reflect FreeSpace on the following function:

Function Report-Datastore {

    $output = @()

    Get-Datastore | ForEach-Object {$props = [ordered]@{'Name'=$_.Name;'FreeSpace'=[math]::Round(($_.FreeSpaceGB),2);'UsedSpace'=[math]::Round(($_.CapacityGB - $_.FreeSpaceGB),2);'PercFree'=[math]::Round((100 * ($_.FreeSpaceGB/$_.CapacityGB)),0)}

        $output += New-Object -TypeName PSCUstomObject -Property $props

    }

    $output

}

But i added the sort-object FreeSpaceGB in HTML code section and does not sort.

$html_DS = Report-Datastore | Sort-Object FreeSpaceGB | ConvertTo-HTML -Fragment | Out-String | Set-AlternatingCSSClasses -CSSEvenClass 'even' -CssOddClass 'odd'

#$html_DS = Report-Datastore | Sort-Object PercFree | ConvertTo-HTML -Fragment | Out-String | Set-AlternatingCSSClasses -CSSEvenClass 'even' -CssOddClass 'odd'

The following is the output of the body email. Thanks for your help

Capture.PNG 

0 Kudos
fabiendibot
Enthusiast
Enthusiast
Jump to solution

You can't use sort on a member object that doesn't exist.

The FreeSpaceGB is not available, you should sort on FreeSpace instead !

gerf0727
Enthusiast
Enthusiast
Jump to solution

Ohh i got confused because of the following Get-Datastore | Sort-Object -Property FreeSpaceGB

0 Kudos
smiller3
Contributor
Contributor
Jump to solution

Fabien... I'm looking for some help with the 'you cannot call a method on a null-valued expression' error. My script was working. I added a few comments and cleaned up some white space. Now... it doesn't work.

Attaching File :-  test.log

You cannot call a method on a null-valued expression.

At C:\Stuff\evv_robo_status.ps1:46 char:11

+ $smtp.Send <<<< ($msg)

    + CategoryInfo          : InvalidOperation: (Send:String) [], RuntimeException

    + FullyQualifiedErrorId : InvokeMethodOnNull

Mail Sent Successfully

Here is the script...

# Parse scheduler log and create file

$yesterday = (get-date) - (new-timespan -day 1)

$events = get-winevent -FilterHashtable @{logname = "Microsoft-Windows-TaskScheduler/Operational"; ID = "201","202"; StartTime = $yesterday} | Format-List -Property Message | out-file "c:\stuff\test.log"

$events |foreach {

    $_

}

# Create new email

$smtpServer = “phcmail.peabodyenergy.com”

$msg = new-object Net.Mail.MailMessage

#From Address

$msg.From = "Monitoring Admin <tivnoreply@peabodyenergy.com>"

#To Address, Copy the below line for multiple recipients

$msg.To.Add(“smiller3@peabodyenergy.com”)

#Message Body

$msg.Body=”Attached is the status report for the EoM Midwest Engineering files copied to STLEN1.”

#Message Subject

$msg.Subject = “EoM Transfer report”

write-host "SENDING FILES"

#your file location

$files=Get-ChildItem “C:\Stuff\report\”

Foreach($file in $files)

{

Write-Host “Attaching File :- ” $file

$attachment = New-Object System.Net.Mail.Attachment –ArgumentList C:\Stuff\report\$file

$msg.Attachments.Add($attachment)

}

$smtp.Send($msg)

$attachment.Dispose();

$msg.Dispose();

write-host "Mail Sent Successfully"

And... if you know how to grab just a single task out of the scheduler log, that would be awesome!

Thanks,

Shawn

0 Kudos