vSphere Reports in Microsoft Teams

By joining PowerCLI to interrogate a VMware vSphere environment and the Webhook API to post Microsoft Teams messages, we can send informational reports on the state of a virtual environment to channels in Teams.

In this example I have a weekly report on the number of hosts and VMs in an environment. This is fairly straightforward, but more complicated information surfaced by PowerCLI could easily be included.


Setting up the WebHook

The Webhook allows messages to be pulled into the Teams channel of choice. You’ll need to setup an Incoming Webhook on your channel of choice.

To do this

  1. Right-click on the Teams Channel and choose Connectors
  2. Find Webhook in the list and click on the adjacent Confugure button.
  3. Enter a name, and choose an icon for the Webhook as prompted. Click on Create and a URL will be generated- this is needed for the script below.

Storing vCenter credentials

As this will be run as a scheduled task we need to store credentials so that the script doesn’t try to prompt for a password. There’s a number of ways of doing this- here I’ve used the Get-Credential cmdlet to prompt for the username and password and then the Export-CliXml cmdlet to save those credentials to a file.

 $Credential = Get-Credential

$Credential |

Export-CliXml -Path C:\Users\myuser\readonlyuser.cred

For the vCenter operations in the script below (counting hosts and VMs) then a user account with Read-Only access is sufficient.

The Script

Finally the script. This can be run manually or set as a scheduled task. The URL of the webhook created above needs to be entered as the value of the $TeamsWebhookURI variable at the top, along with the vCenter credentials and the name of the vCenter.

#Set the Webhook URI to send the message to
$TeamsWebhookURI="https://outlook.office.com/webhook/[email protected]/IncomingWebhook/zzzzzzzzz/zzzzz-zzzz"
#Use pre-defined credentials
$credential = import-clixml -Path C:\Users\myuser\readonlyuser.cred
#What is the address of the vCenter?
#Connect to vCenter
Connect-VIServer -Server $vCenter -Credential $credential
#Count the VMs and hosts
$poweredoff = @(get-vm | Where-object{$_.PowerState -ne "PoweredOn" } | measure-Object -Line).Lines
$poweredon = @(get-vm | Where-object{$_.PowerState -eq "PoweredOn" } | measure-Object -Line).Lines
$hostCount=(Get-VMHost | Measure-Object).Count
#Disconnect from vCenter
Disconnect-viserver -Server $vCenter -Confirm:$false

#Build the JSON for the Body of the message
$JSONBody = [PSCustomObject][Ordered]@{
"@type" = "MessageCard"
"@context" = "http://schema.org/extensions"
"summary" = "Weekly Infrastructure Stats"
"themeColor" = '0078D7'
"sections" = @(
"activityTitle" = "Virtual Infrastructure"
"activitySubtitle" = "Statistics"
"activityImage" = "https://mydomain.com/infoicon.svg"
"facts" = @(
"name" = "Num. of Hosts: "
"value" = $hostcount
"name" = "Powered On VMs: "
"value" = $poweredon
"name" = "Powered Off VMs: "
"value" = $poweredoff
"name" = "Total VMs: "
"value" = ($poweredon+$poweredoff)
"markdown" = $true

$TeamMessageBody = ConvertTo-Json $JSONBody -Depth 100

#Build the API call
$parameters = @{
"URI" = $TeamsWebhookURI
"Method" = 'POST'
"Body" = $TeamMessageBody
"ContentType" = 'application/json'
#Make the API Call
Invoke-RestMethod @parameters