MSEndpointMgr
Teams Notification Card Sample

How to notify a Microsoft Teams Channel when a new Windows device has enrolled in Microsoft Intune

Recently I was at a customer site, where several people where deploying Windows 10 devices and Hybrid enrolling them in Intune MDM via GPO. However they sometimes struggled with keeping track of when the computers where successfully enrolled with Intune, and had begun policy provisioning.

We had already setup notifications in Microsoft Teams, for computers that had been deployed with MDT/ConfigMgr – So the natural course of action was to extend this to Intune.

Overview

When dealing with Notification in Intune, we usually have to design a custom JSON payload, and send that to Teams using a Connector. Now, I know that not all Intune admins are JSON ninjas. So I took it upon myself to build a “framework script” to make deploying this as simple as possible, allowing you to get started with little to no PowerShell and JSON knowledge. While building this I stumbled upon an excellent PowerShell Module called PSTeams, that actually takes care of all the JSON stuff – which just makes things much easier for me and for you.

So in this article we will cover the following:

  • How to setup an “Incoming Webhook” connector on a Microsoft Teams Channel.
  • How to send a notification to an Incoming Webhook from a PowerShell script.
  • How to publish a PowerShell script to a Windows 10 client via Intune.
  • How to make the people deploying computers to Intune happier Smile.

Prerequisites

Even though I have tried to simplify everything as much as possible, there are still some things you need to take care of before getting into the deployment of this solution. Some might seem obvious, but nevertheless they are the key to getting this show on the road!

So make sure you have the following:

  • An active Intune tenant (you have to be Intune administrator).
  • Intune License assigned to the user enrolling a Windows 10 device.
  • A somewhat basic understanding of variables in a PowerShell script
  • A Microsoft Teams Channel to send the notifications to.
  • A “can-do” attitude.

Got it? Alright let’s get to the chopper!

How to setup an Incoming Webhook connector on a Microsoft Teams channel

I am assuming you have a Teams with a Channel, ready for receiving notifications, and that you are not using this channel for anything else, because that will get messy as some point.

  • So start by opening the Teams client, and click your way through to your Team of choice, and hover the cursor on the Channel that you want the notifications to appear in.
  • Clicking the three dots (…) menu to the right of the channel name to access channel features – you should have the option called “Connectors”, as illustrated below.
    adding_a_channel_connector_teams
  • Now find the “Incoming Webhook” connector – it’s located under “Developer Tools”, as illustrated below.
    adding_a_channel_connector_teams_2
  • On the next page, don’t make any changes, just click “Install”.
    image
  • Now you need to specify a name for the Incoming Webhook, and click “Create”, as illustrated below.
  • Optionally: you can customize the image associated with the channel posts that the webhook creates (It’s like an account picture).
    image
  • When you have clicked “Create”, the page will change to include the generated Webhook URL.
  • You need to copy this URL to a temporary location for later use – notepad is always a good choice if you don’t have clipboard history enabled.
  • Now click “Done”.
    image
  • You can now close the connectors dialog, and get on with the next part of this article.

That is all there is to creating an Incoming Webhook for Microsoft Teams! It has a ton of uses, which I am sure you will find out.

How to remove a Microsoft Teams Connector

You might have mistakenly added the connector to the wrong channel, and wish to remove it.

Well just go back into the menu where you would normally add a connector, but instead of finding a connector to add, click on “Configured” in the “MANAGE” section of the menu on the left, then click on the “Configured” drop down link, and then “Manage”, as illustrated below.

image

Now scroll down a bit, and click on the “Remove” button, answer the questions on the next page, and then click “Remove” again.

Coincidentally, this is also where you could retrieve the Webhook URL from, in case you forgot to save it earlier.

image

How to send a notification to an Incoming Webhook from a PowerShell script

Now comes the fun part! Sending the actual notification from a PowerShell script.

You can (and should) test this on your own computer, before deploying the script to Microsoft Intune. During the test, we will deactivate the function that checks that the script is being run on a newly deployed Windows 10 device, so don’t forget to undo that, when you deploy the script in production. I will try and remember to remind you when we get to that part.

You should grab the latest version of the Intune-TeamsNotification.ps1 script from GitHub, before continuing.

https://github.com/mardahl/intune-TeamsNotification

image

Configuring the script

I have made an effort to “sectionize” the script, separating it in “Configuration, Functions and Execution” sections. For beginners, I suggest only concerning yourself with the “Configuration” section. The other sections have been fairly well commented. If you want to get more advanced, please have a look at the PSTeams module GitHub page.

Configuration items that you can tweak

  • Webhook URL
    • This is obviously the URL we got from the first part of this blog, where we configured the Incoming Webhook for our Microsoft Teams Channel. Just paste the one you got, in-place of the dummy one I put in the script – don’t forget the surrounding ‘ ‘ marks.
  • Enable Testing
    • If you are testing this script on your own computer, you can use this to have the script post to the channel on every run. Very useful variable indeed! (remember I told you earlier about needing to deactivate something before putting the script into production? This is it! Don’t, I repeat don’t forget to set this to $false when deploying into production environments. Values are either $true or $false
  • Custom logic subsection
    • This is where you would put any custom PowerShell code that you need to get data into the notification. Your code should output to string variables, to be used later on in the design section. I have put in some simple examples that could be useful to you, in your quest to impress colleagues with awesome notifications.
      • Get Current User
      • Get Teamviewer ID
      • Get OS Install Date / Time
      • Get OS Name and Release ID
    • Here’s a screenshot of the custom section where to put the code:
      image
  • Notification card color
    • A simple line of color can adorn the top of the notification card in Teams.
    • I have chosen a pretty blue color, but you can change this to your liking.
    • Inspiration available here: https://encycolorpedia.com/1e90ffimage
  • Other variables
    • The next few variables are pretty self-explanatory, but where they fit into the notification card might be confusing for some, so I have mapped them out in sequence, to match the screenshot below.
      • Message title
      • Message text
      • Activity title
      • Activity subtitle
      • Activity text
      • Activity image link
      • Facts table
      • Buttons table
image

Understanding the Facts and Button tables:

The Fact table is a list of well facts, and that’s a fact! In fact I would go as far as to say, that putting fiction into this table is as stupid as this paragraph. So try and fill the table with output from the “custom logic” section, maintaining the order that you want them presented in, and paying attention to the fact that labels must be unique. Labels are the first part of each line in the table (I.e. “Computer name”). The same applies to buttons in the Buttons table. Buttons are essentially links, which you could also just put in as links in a fact, but they stand out more.

  • A useful case for the buttons would be if you could link to an asset management system, to get more info about the device.
  • Maybe you would even go as far, as have some custom logic in the script that registers this device in your asset management system, and fetching a direct URL to the asset!

Or you could just add a link to azure automation that deletes the device from Intune? I would call that button “OK” (that a really funny joke btw).

image

How to publish a PowerShell script to a Windows 10 client via Intune

In order to successfully have this script work as intended, we need to deploy it using Microsoft Intune as a device configuration PowerShell script. We could also have leveraged the Win32 app deployment option. But the PowerShell way is just so easy.

This gives us a few benefits like:

  • Knowing that the device has surely enrolled, otherwise it simply would not have run.
  • Easy execution in the system context.
  • Intune Management Extension has been deployed (because that is what actually executes the script).
  • The script will just get executed once (unless you change something in the policy)
    • Just to be clear – I have made efforts in the script to avoid duplicate execution. A “cookie” file is placed on the device to ensure this.

Steps to deploy the script

  • Firstly you must logon to https://endpoint.microsoft.com with an Intune Admin role account.
  • Click on the menu item “Device Configuration”.
  • Click on the menu item “PowerShell scripts”.
  • Click on the “Add” button.
  • Fill in the “name” of the PowerShell policy.
  • Add an optional description.
  • Select the script from you local computer (it will be uploaded to a special storage account within Intune)
  • Click on the menu item “Settings”.
  • Make sure the options in “Script settings” are as shown in the image below and click “OK
  • You should now be able to see your newly added PowerShell script in the list of scripts. Before anything can happen, you need to assign the script to a group of users or devices, I think devices make most sense in this case. In my case I have made a dynamic group in Azure AD that contains all devices running Windows 10, you could do the same.
  • Click on the name you gave the script policy, in the list of scripts, and follow along with the next steps.
  • Click on the menu item “Assignments”.
  • Click on the “Select groups” button.
  • Search for a security group to target, select it, and then click on the blue “Select” button at the bottom, and finally the blue “Save” icon.

That’s it!

How to make the people deploying computers to Intune happier

You have done yourself and your co-workers a solid favour today but adding something useful for them to look at in Microsoft Teams. But make sure you actually tell them about the channel in Teams, and ask them if there is any other information that they would find useful in the notifications? I think it goes without saying; that you should add them as members to the Team that holds the notification channel, otherwise it’s gonna be awfully lonely in there.

Did you remember to disable the “testing” mode in the script before deploying it with Intune?

Some tips on working with the notifications in Intune

When you now have all these notification cards per-device, I find it useful to @mention people as a reply action on the cards. This way you can call out a specific person or group of people to take certain actions on the device, and report back on the same card, by using the same cards reply function. Example: “Hey @bob, this device reports that secure boot is not enabled, could you follow up on that and report back here? Thanks

This way you have a sort of history on the device deployment. Generally it’s a good practice to use the reply function in Teams instead of starting a new thread each time you type something.

Final words

There is a lot more you can do with the notification cards, and learning about it starts here:

https://docs.microsoft.com/da-dk/outlook/actionable-messages/message-card-reference

I am sure you will come up with some awesome custom logic and card designs, so why not make it available to others on GitHub!

Michael Mardahl

Michael Mardahl is a seasoned IT pro with over 25 years of experience under his belt. He's a Microsoft Certified Cloud Architect at APENTO in Denmark, where he helps customers move from traditional infrastructure to the cloud while keeping security top of mind. When he's not working, Michael's either spending time with his family and friends or passionately blogging about Microsoft cloud technology. His expertise in this area has even earned him the prestigious title of Microsoft Most Valuable Professional (MVP) in both the Enterprise Mobility and Security categories. In short, Michael is the IT equivalent of a rockstar, but don't expect him to act like one - he's way too down-to-earth for that.

19 comments

  • Thanks for this. This is great!

    Unfortunately Microsoft haven’t updated the Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion ProductName value for Windows 11 so a little tweaking was required to report the correct OS.

    • I will share here on the blog if anyone has the same issue maybe they will comment. or if you solved it, then please leave another comment.

  • Hi,

    I’ve added a piece so you can get the enrolled user in the notification.

    Custom logic section:

    #Get Enrolled User
    $AADInfo = Get-Item “HKLM:/SYSTEM/CurrentControlSet/Control/CloudDomainJoin/JoinInfo”

    $guids = $AADInfo.GetSubKeyNames()
    foreach ($guid in $guids) {
    $guidSubKey = $AADinfo.OpenSubKey($guid);
    $UPN = $guidSubKey.GetValue(“UserEmail”);
    }

    $Username = $UPN -split (“@”)
    $Username = $Username[0]

    Notifcation

    $facts = [ordered]@{
    “Computername” = “$($env:COMPUTERNAME)”
    “Enrolled User” = “$Username”
    “Operating System” = “$OSDisplayName”
    “Install Date” = “$myinstallDate”
    }

  • Hello Michael,

    Thanks for the great Stuff. I was successfully able to test this in my LAB. I also added the Button as described by Dave in the comments to GoTo the MEM portal for the device.

    Thanks

  • HI Michael, very nice implementation, I extended it a little bit with a button which opens the device directly in a browser session, maybe this could be usefull for some of you:

    Custom logic section:

    # Get MDM Device ID
    $DeviceID = Get-ItemPropertyValue HKLM:\SOFTWARE\Microsoft\Provisioning\Diagnostics\Autopilot\EstablishedCorrelations -Name EntDMID -ErrorAction SilentlyContinue

    Button:
    “Endpoint Manager Portal – Device” = “https://endpoint.microsoft.com/#blade/Microsoft_Intune_Devices/DeviceSettingsBlade/overview/mdmDeviceId/$DeviceID”

  • Thanks for this!
    I had some problems with the script stopping on
    “NuGet provider is required to continue
    PowerShellGet requires NuGet provider version ‘2.8.5.201’ or newer to interact with NuGet-based repositories.” Do you want PowerShellGet to install and import the NuGet provider now?”
    and then the intune script would just hang until it timed out. Solved it by adding the following three lines before “Install-Module PSTeams -Force -ErrorAction Stop” :

    Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
    Import-PackageProvider NuGet -Force
    Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

    • Thanks for sharing back Jings!
      I probably have something else that keeps the NuGet provider updated already in my tests, so glad that you spotted this.

  • Hi there!

    Thanks for the Script. I deployed it via Intune, but when I enroll a Device its not working. I tested the script on my PC with the TestOption set to $true, its working when i run it as Admin.
    But when the script is deployed via Intune in a Autopilot enrollment, its not working. However in Intune Device Management I see that the script runs sucessfully on the Autopilot Devices. Any ideas how to troubleshoot?

    • Hi Sascha,
      Sorry for the Covid delay!
      Maybe the comment by Jings can help you out.

    • Hi Sarsha,
      I have the same issue you are having and wondered if you found a solution?
      Thanks
      Anthony

  • Hello Michael.

    This script is great, congratulations.

    But I found problems generating the buttons and facts in the notification.
    I detected that in the functions to create the buttons and facts there is a typo, the $ hashtable variable is written as $ hastable, correcting that I was able to generate the information successfully.

    function makeButtonsFromHashtable($Hashtable) {
    # Generating Buttons Code from Hashtable in config section
    foreach ($Button in $Hastable.Keys) {
    New-TeamsButton -Name $Button -Link $Hastable[“$Button”]
    }
    }

    function makeFactsFromHashtable($Hashtable) {
    # Generating Facts Code from Hashtable in config section
    # Currently this does not support multi-line facts, instead you will have to add those kind of facts manually.
    foreach ($Fact in $Hastable.Keys) {
    New-TeamsFact -Name $Fact -Value “$($Hastable[“$Fact”])”
    }
    }

    • Hi Marcelo, thanks for commenting! 🙂
      I apologise to everyone who has had this problem – I did not think further about it until you wrote this comment, because the bug had actually been caught a month back, but the commit to github failed somehow. But now I looked again, and did the edit directly in github.

      You are also always welcome to do a pull request of any of my scripts, and I will merge the requests back if they seem valid 🙂

      Thanks for being a part of the community.

  • This is a great Script and we would implement it in our Environment.
    But the ActionDetails are not created. We only got the first Five lines. What is wrong there?

    • Hi Henrik, I am happy to assist, but as there is nothing called “ActionDetails” in the script, I am unsure what you are referring to?
      Please try and setup the script AS-IS with you own $WebhookURL, enable testing mode – then see if you get the full amount of data.
      From there on I would start to modify slightly.
      Also keep in mind that the script does not support multi line output from custom logic in it’s current form.

      • I think he means the ActivityDetails and Buttons, having the same issue as well. The facts and buttons are not created

Sponsors

Categories

MSEndpointMgr.com use cookies to ensure that we give you the best experience on our website.