Read Time:3 Minute, 40 Second

In this tutorial I show how to send data from SCCM (MEMCM) to Microsoft Teams using the built-in Teams webhook and some PowerShell.

Specifically, I will show how we can get the latest software update deployment information via PowerShell, wrap it in some JSON, and then fire it off to a Teams channel!

Management will be impressed and junior admins may consider you a god. Pretty cool right?


The first step is that you need to create a Teams channel! If you are unsure how to do this please go away and learn check this article. Once you are setup, hit the to the right of the channel and click on Connectors

Add a Teams channel connector

Now search for Incoming Webhook and click Add

The Teams Incoming Webhook connector

Click Add again

Add the webhook

You may need to go back in via the three dots but you should now see a Configure button for the connector

Configure the webhook

Give your webhook a name and choose an image (these will be visible in the channel when the webhook posts something) and then click Create

Give the webhook a name and image

Copy the unique URL as we will need this for our script and then click on Save

Copy the unique URL for the webhook

If you now check your channel you should see something like the below which indicates we are good to go!

The webhook is now configured

SCCM has its own PowerShell module and this can be accessed from any machine that has the console installed. More information can be found about the module and the available cmdlets here

Set-Location  'C:\Program Files\Microsoft Configuration Manager\AdminConsole\bin'
Import-Module .\ConfigurationManager.psd1

With the module now exposed we need to set up a PSDrive to the site server. Replace ABC with your three letter site code and with the FQDN of your site server

New-PSDrive -Name "ABC" -PSProvider "CMSite" -Root "" -Description "Primary site"

To run our cmdlets we now need to change directory to the logical drive (replace ABC with your SCCM site code)

Set-Location ABC:

With the above prep done we can now pull pretty much anything we want out of SCCM. In this example I am grabbing –

  • The Automatic Deployment Rule information (last run time and exit code)
  • A specific software update group and the updates it contains
  • Deployment details such as the collection the software update group targets
  • The status of the update installations on the collection members (two devices in my lab environment).

IMPORTANT – Remember to add in your unique URL at the bottom of the script 😉

### Get some ADR info, last run time and exit code

$ADR = Get-CMSoftwareUpdateAutoDeploymentRule -Name "Windows 11"

$ADRLastRun = $ADR.LastRunTime 
$ADRExitCode = $ADR.LastErrorCode

### Get the Software Update Group

$sugupdates = Get-CMSoftwareUpdateGroup -Name "Windows 11"

### Get the updates inside in the software update group and do a bit of formatting on the results

foreach ($update in $sugupdates.Updates)

 $CurrentUpdates += @(Get-CMSoftwareUpdate -Id $update)

$CurrentUpdatesName = $CurrentUpdates.LocalizedDisplayName

$CurrentUpdateNameFormatted = [string]::Join('<br>',$CurrentUpdatesName)

### Get the deployment details 

$sudeploy = Get-CMSoftwareUpdateDeployment -Name "Windows 11" -Summary

$CollectionName = $sudeploy.CollectionName
$NumberDevices = $sudeploy.NumberTargeted
$NumberInProgress = $sudeploy.NumberInProgress
$NumberErrors = $sudeploy.NumberErrors
$NumberSuccess = $sudeploy.NumberSuccess

### Prepare the payload

[String]$var = "Text which appears in the message content"
$JSONBody = [PSCustomObject][Ordered]@{
"@type" = "MessageCard"
"@context" = "<>"
"summary" = "Latest Update Deployment Information"
"themeColor" = '0078D7'
"title" = "Latest Update Deployment Information"

"text" = "
The ADR last ran <strong>$ADRLastRun</strong><br>
The ADR exit code was <strong>$ADRExitCode</strong><br>
The updates in the software update group are:<br><br>
The collection name is <strong>$CollectionName</strong><br>
The number of devices is <strong>$NumberDevices</strong><br>
Successes: <strong>$NumberSuccess</strong><br>
In Progress: <strong>$NumberInProgress</strong><br>
Errors: <strong>$NumberErrors</strong><br>

### Convert to JSON

$TeamMessageBody = ConvertTo-Json $JSONBody

### POST to URL

$parameters = @{
"Method" = 'POST'
"Body" = $TeamMessageBody
"ContentType" = 'application/json'

Invoke-RestMethod @parameters


And here we go! A nicely formatted message (thanks to the HTML tags in the JSON) and this is something that can easily be called from a scheduled task on a repeatable basis.

5 4 votes
Article Rating
Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Newest Most Voted
Inline Feedbacks
View all comments

Cool tutorial!


How would you automate the script execution? Daily task scheduler on the site server or something smarter?


Sadly not working for me.
Keeps getting error: Invoke-RestMethod : Invalid webhook request – Empty Payload


I did bypass the error by enforcing newer TLS protocols.
Also, i’ve removed the [Ordered] from the JSONBody, as i received error: “Unable to find type [Ordered].
At line:47 char:29
+ $JSONBody = [PSCustomObject][Ordered]”

Now i get the error: “Invoke-RestMethod : Summary or Text is required.”

NOTE: For the $ADR variable, i actually use “Windows 10 Updates” as well. I mistyped it in the pastebin.

Last edited 2 months ago by TimJ

Well executes better now.
I still need to force newer TLS protocols inorder to trigger the invoke-restmethod with:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor
[Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12

Otherwise i get the error: Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.

After that the script rans through. Sadly the message is to long to be displayed in teams.
In the teams channel it says: “This message is too long to display here. Please visit the external source app to view the message.”


The site server is running Server 2016 build 1607 with the April patch.

And yes, my SUG is very large and needs to be trimmed. It contains over 100 updates. Will have a look at trimming that, and retry at some point 🙂

Would love your thoughts, please comment.x