Set the custom Focusing status in Microsoft Teams from To Do using Power Automate

I am happy to announce that I have a free NoCode alternative for setting the Focusing status in Microsoft Teams! This is a follow up post to one of my most popular blog posts in 2020, Set the custom Focusing status in Microsoft Teams using Power Automate invoked through PowerShell.

Update 06.10.20: Updated the flow to better handle expected failure, should now exit as success if the task has no number. Download and import the Power Automate flow from GitHub. Found a logical issue 08.10.20, the Flow is now updated👍

The Focusing custom Teams status can only be set by MyAnalytics via a calendar event called ‘Focus time‘. I have not been able to recreate this calendar event type manually, so it must be something in the header. During a ‘Focus time‘ calendar event, the Teams client sets the status to Do Not Disturb with a custom name called Focusing. I don’t like the current way MyAnalytics schedules this event since it is two hours long and weeks in advance. I need a way to set this status at the time I am focusing, to mute distractions and tell my peers that I am in a focus, deep work, flow Pomodoro sprint. This is why I created this routine

Instead of using the premium HTTP request trigger, I now use the free NoCode Microsoft To Do trigger. When a new task is created, the Power Automate flow runs, finds your default calendar, finds an existing Focus time calendar event in your language and sets the time for your Pomodoro sprint duration. It even has an option to use IFTTT to mute your phone during the sprint.


I am a Pomodoro Technique enthusiast. During a Pomodoro sprint it is important to mute distractions. This worked fine with custom presence states in Skype for Business, which is one of my most popular blog posts to date. I also published a very popular blog post on a routine to use HTTP request trigger in Power Automate to set the Focusing custom mode in Microsoft Teams. The problem with that routine is that it required coding and you needed to trigger it in PowerShell using a premium trigger. To Do triggers are included in most Office 365 SKU’s. Download and import the Power Automate flow from GitHub to see how the flow is built.

How it works

  • Make sure all prerequisites are met as the described below
  • Open Microsoft To Do
  • In any list, you create a new task and in the subject you put the time interval you want to do a Pomodoro sprint to achieve deep work/flow state/focus time
    • This technique even works from mobile and web!
    • I recommend you create a Pomodoro list in To Do to keep them all in the same place and so they don’t clutter your actual Tasks
  • Up to 3 minutes later, the Power Automate flow will trigger
    • I have tuned the timers in such a way that both the calendar event and the IFTTT trigger will start at the time you created the To Do task, and not when the flow is triggered
  • The flow will then access your primary calendar and create a copy of the current Focus time event and call it “Old Focus time” for historical purposes
    • This works regardless of language of the calendar and the Focus time calendar event, I check for primary calendar and use criteria to find the correct calendar event
  • Then the flow will get the latest Focus time event and update it with the time your To Do task was created and end the event using the number you put in the To Do task subject
  • When the calendar event is created, Teams will almost instantly update it’s status and put you in to the custom Focusing status, which has the same capabilities as if you set yourself to Do Not Disturb
  • When the calendar event is done, you will revert back to the correct status for your current time, busy if you are busy in calendar or available if you do not have anything else in your calendar
  • Now you can go to your meeting or evaluate which task is most important for you and trigger a new Pomodoro sprint :)


  • Calendar must be in Exchange Online
  • You must have MyAnalytics as part of your license and enabled
    • Schedule 1 period with MyAnalytics to get the calendar event
    • Available in Enterprise SKU’s
    • I recommend to turn it off again after the first run, so that you calendar does not get flooded with weekly Focusing time events
  • Download and import the Power Automate flow from GitHub
    • Go to Power Automate in
    • Navigate to My flows and click Import
    • No changes are needed in the actual flow after import is finished
    • When importing you need to use the following connectors
  • Find one of your Focus time calendar event and set priority to low
    • This can only be done in Outlook desktop client
  • In order to find the correct calendar entry we are checking for the following
    • Priority low
    • Category: Green Category
      • In my tests the category will be named Green even though you are using a different language
    • We find the first one and edit that event, to make sure we are not editing all events
      • The flow stops after one event is edited
  • Optional bonus, not required
    • If you install the flow app on your mobile, you can get a notification on you mobile when the Pomodoro sprint starts and when it stops
    • You an use that notification to trigger an IFTTT action on Android and iOS to set them to do not disturb at the start and turn it off again
    • I even use the IFTTT trigger to control a hue light in my office, set it to red during the Pomodoro sprint and green when finishing :)
    • Read more about IFTTT triggers for pomodoro sprint here
    • In order to enable the IFTTT part of the flow, you need to go in and edit it and set the IFTTTIntegration variable to 1. It is set to 0, disabled, by default

Power Automate techniques I used to accomplish this flow

In the coming weeks I will publish separate blog posts on how I created a universal flow which works out of the box in any environment. In the meantime you can download the flow from GitHub and take a look

  • How to find the default Outlook calendar for a person regardless of language
  • How to find the default Microsoft To Do tasks list for a person regardless of language
  • How to find a specific calendar event based on category
  • How I used ticks() to find time difference in Power Automate and what I used it for
  • Substring() techniques in Power Automate
  • If() in Power Automate
  • Math is hard in Power Automate, here is how i used sub(), div(), addminutes() and length()
  • Named variables and comments in Power Automate

Use Power Automate to send Teams messages to To Do #NoCode

I am a productivity enthusiast. I use Microsoft To Do for my individual task management. When someone has a task for me in Microsoft Teams I need to get them in to To Do. MVP Vesa Nopanen created a Power Automate routine for doing this which works great. In his blog post, he talks about how to create it and how to share it with select users within your organization. I have tuned this routine to make it universally available so that no changes to the code is need for it to run in your organization. How? Read on

I created the universal routine which you can download from GitHub and try for yourself. Just import it, authorize access to Microsoft Teams and Microsoft To Do and you are good to go. Check out Vesa’s blogpost for how to share it in the organization

Originally the routine checked for the name of your tasks folder, but I found a way to do that programmatically, since the name of the folder is different depending on your language. The flow will look up the lists in user context and from there we can check which is the default one. Tasks is always the default one.

I did one more thing. When capturing the text to go in the task, I wanted to limit the length of the subject to 150 characters.

  1. I had to convert the output from Teams to plain text
  2. Then I checked the length of the body
    • if it was short than 150 characters, I used that as length,
    • if the body was more than 150 characters I limited it to 150.
    • if(lessOrEquals(length(outputs(‘Html_to_text’)?[‘body’]),150),length(outputs(‘Html_to_text’)?[‘body’]),150)
  3. Finally I created a string variable which is no longer than 150 characters and used it in the subject.
    • substring(outputs(‘Html_to_text’)?[‘body’],0,outputs(‘Compose’))

That’s it, simple and effective. You can download the flow from GitHub, make sure you read the original blog post for full details. MVP Yannick Reekmans has a different take to accomplish this using a graph approach. You still need the above routine to get the default task list.

When importing the flow, you need to have these connectors available so that you can complete the import. All connectors are part of your Office 365 subscription

Set the custom Focusing status in Microsoft Teams from PowerShell using Power Automate

Update 05.10.20: I have created a free way to do this using Microsoft To Do task as a trigger. No need for code adjustment, just download and use it. Read more here! If you want to use premium Power Automate trigger and PowerShell to set the status keep on reading :)

I am a Pomodoro Technique enthusiast. During a Pomodoro sprint it is important to mute distractions. This worked fine with custom presence states in Skype for Business, which is one of my most popular blog posts to date, on a daily basis. With Microsoft Teams, this has been a challenge, until now.

The Focusing custom Teams status can only be set by MyAnalytics via a calendar event called ‘Focus time‘. I have not been able to recreate this calendar event type manually, so it must be something in the header. During a ‘Focus time calendar event, the Teams client sets the status to Do Not Disturb with a custom name called Focusing. I don’t like the current way MyAnalytics schedules this event since it is two hours long and weeks in advance. I need a way to set this status at the time I am focusing, to mute distractions and tell my peers that I am in a focus, deep work, flow Pomodoro sprint.

The result using my Pomodor PowerShell timer

The Teams Focusing status fits well with the PowerShell Pomodoro Timer. As you see, it may take up to 3 minutes for the status to update, but I take what I can get :)

How I solved it

I trigger a Power Automate flow using a HTTP request trigger using Invoke-WebRequest in PowerShell. The flow takes two inputs, duration and a secret. If the secret is correct, to make sure the flow can’t be easily hacked, it gets my calendar and searches for calendar event with subject ‘Focus time’. It takes the first entry and changes start time and stop time for the event using the duration I have set, usually 25 minutes. Now I have a ‘Focus time’ calendar event that is set at the same time as my Pomodoro sprint with the same duration. After 1-3 minutes, my status will be updated to Focusing. After 25 minutes, plus 1-3 minutes, my status will be reset. BOOM, how cool is that!?


  • Calendar must be in Exchange Online
  • You must have MyAnalytics as part of your license and enabled
    • Schedule 1 period with MyAnalytics to get the calendar event
    • Available in Enterprise SKU’s
  • You must have Power Automate license and ability to use Premium triggers
    • The trigger used is HTTP request and is a Premium trigger
    • You may find that you can use other free triggers as well
    • Premium triggers are included in Dynamics 365 SKU’s
    • Premium triggers are not included in Microsoft 365 SKU’s
    • The standalone $15 Per User plan can run Premium triggers
  • If you want to use a trigger included in your Office 365 plan, check out my other method, using Microsoft To Do task as trigger

Creating the calendar event and importing the Power Automate flow

  • Create the calendar event in MyAnalytics
  • Import the flow in your Power Automate
    • Download the file here
    • Navigate to your personal Power Automate dashboard at
    • Go to My flows in the left menu and click Import
    • Click Upload and choose the zip file
    • To be able to complete the import you must click the wrench in the first line and choose Create as new under Setup
    • Next you must create the Outlook connector by clicking on the wrench in the second line for Related resources
      • Click Create new
      • Scroll down to Office 365 Outlook, click Create and authenticate as your user
      • Now you have created the Outlook connector, go back to the flow import website and select you new connector and Save
      • Import the flow by clicking Import
      • The import should be successful, navigate to My flows
    • Edit your new flow called RescheduleFocusTimeCalendarEvent
    • Now, let’s go through it and update the flow for your environment

Configuring the Power Automate flow

Click Edit on the flow and expand When a HTTP request is received and copy the HTTP POST URL and save it for later

Expand Condition and change MySecret to your own and take note of it

If no is there to trigger if the secret is wrong, it is a small security measure so that people not easily can steal you flow URL, but they also need the secret, or you can change it if it does get lost

Under If yes, expand Connections, click connect and delete the current guid, then you will be able to choose your calendar

Click advanced options in Get Events (V4) and validate that we are finding calendar events with subject ‘Focus time’ and we are getting the first entry. This means it does not matter how many events of ‘Focus time’ you have in your calendar. Expand Current time and Get future time. Future time is controlled by the duration variable we sent to the HTTP trigger.

Expand Apply to each and Update event (V4). Again, you need to choose your calendar. Id is the ‘Focus time’ calendar event, Subject is the same, Start time is our current time, End time is our future time and choose your timezone

That’s it! You are now ready to invoke your flow. In PowerShell you need to run the following code

[int]$Minutes = 25 #Duration of your Pomodoro Session, default is 25 minutes
[string]$Secret = "MySecret" #Secret for the flow trigger
[string]$AutomateURI = "YourFlowTriggerURI" #The URI used in the webrequest to your flow

#Invoking PowerAutomate to change set current time on your Focus time calendar event, default length is 25 minutes
    $body = @()
    $body = @"
Invoke-RestMethod -Method Post -Body $Body -Uri $AutomateURI -ContentType "application/json"

Go back to Power Automate and validate that the flow ran, check your Outlook calendar that the ‘Focus time’ event was moved to now and wait up to 3 minutes to see your status change. When the calendar time is over, your status will be reset and you are available again.

The practical approach with the Pomodoro PowerShell timer

With the ability to control the status in Teams, I believe the Pomodoro PowerShell timer is feature complete. One thing is to be unavailable and reduce distractions, but it is very important to automatically become available again. The reason for WHY you would use this kind of timer and automation is to avoid getting distracted which breaks your flow and deep work. Research shows that it takes between 7-30 minutes to get back in to flow after you have seen just one email or message. Here is what the script does

  • Starts presentation mode to block popups on your computer
  • Hides badges on taskbar so that you do not get distracted by seing that you have a new mail, task or chat
  • Opens you favorite flow and deep work Spotify playlist so that you do not spend time figuring out what to listen to
  • Uses IFTTT to mute your phone, works with Android and iOS
  • Finally set your status in Teams to Focusing
  • After the Pomodoro sprint is over, everything will be turned back on again

Below is a sample code to run the Start-SimplePmodoro.ps1 script which you can download from GitHub

Start-SimplePomodoro `
-SpotifyPlayList spotify:playlist:XXXXXXXXXXXXXXXXXX `
-IFTTTMuteTrigger pomodoro_start `
-IFTTTUnMuteTrigger pomodoro_stop `
-Secret YourFlowSecret  `
-AutomateURI YourAutomateURI `

Why is it important to automatically become available?

You have been gone for 25 minutes, use the pause to check if anyone has been trying to reach you, re-prioritize your tasks, get more coffee and then dive in to a new Pomodoro sprint. After 25 minutes it is OK to get distracted, but if nothing happens, just stay in the flow you jump started and get stuff done. Download the Pomodoro PowerShell timer from GitHub

Discover all headsets used in #MicrosoftTeams PowerBI report

Part of succeeding with Microsoft Teams in the organization is to use certified for Microsoft Teams devices. I wrote about this in my article Why certified for Microsoft Teams devices are important. To succeed with this we need visibility and knowledge about what is being used in our environment.

I have created a simple PowerBI report for this. Download it here. The report will find which devices are used within your organization. The report uses the CQD connector for PowerBI and you can publish it and add it as a tab in Teams.

The report connects directly to the CQD database which is the only supported way. Because of this, the user who accesses the report in Teams needs one of the following admin roles assigned.

  • Global Administrator
  • Global Reader
  • Skype for Business Administrator
  • Teams Service Administrator
  • Teams Communications Administrator
  • Teams Communications Support Engineer
  • Teams Communications Support Specialist
  • Reports Reader

To just see the devices used without getting the UPNs of the users, you can use the Reports Reader or Teams Communications Support Specialist roles.

The report

By specifying the Second UPN you can see what kind of devices individuals in your organization are using. You will find that there are multiple entries of the same devices because Second Capture Dev name is different. There is currently no way of using regex to mitigate this. Second Capture Dev is the microphone used in the audio conversations and is an indication of device used regardless of PSTN, Teams call, or conference.

Default input device, Audio and Realtek High Definition Audio are typically indications of using jack based or laptop speakers as the mic. In the picture below you see that CloudWay are mostly using certified devices👍

The report is based on Audio Call Count and Second Capture Dev from the CQD database


  • Download the CQD PowerBI reports created by Microsoft
    • Read more about them and get the reports here
  • Download and install PowerBI desktop
  • Download the GetDeviceReport from GitHub
  • Assign PowerBI PRO license, to be able to publish the report online
  • Assign at least Teams Communications Support Specialist admin role to be able to connect and read the CQD database

Setting up the report, publish it to PowerBI and adding it as a tab in Teams

  • Make sure you have or create the folder
    • [Documents]\Power BI Desktop\Custom Connectors
  • Copy the MicrosoftCallQuality.pqx to the above folder
    • This file is in the zip package you downloaded called
    • This gives you the Microsoft Call Quality (Beta) connector in the PowerBI desktop app
  • To build a report and run queries, you will first need to connect to the CQD data source.
  • Follow the steps below to connect:
    • In the Home tab of Power BI Desktop, click on Get Data.
    • The Get Data window should appear at this point. Navigate to Online Services, then select Microsoft Call Quality (Beta) and hit Connect.
    • You will be prompted to log in
    • The next prompt will give you the option between two Data Connectivity modes.
      • Select DirectQuery, which is the only supported way to connect to CQD, and hit OK
    • Finally, you will be given a final prompt showing you the entire data model for CQD.
      • No data will be visible at this point, only the data model for CQD.
      • Select Load to complete the setup process.
    • At this point, Power BI will load the data model onto the right side of the window.
      • The page will remain otherwise blank, and no queries will be loaded by default.
      • Proceed to Building Queries below to build a query and return data.
    • Now you are ready to open the PowerBI report you downloaded from GitHub
      • Open GetDevice.pbix, see it load in PowerBI desktop
      • Next, we need to publish the report by clicking Publish in the top menu to the left
      • In the Publish to PowerBI window, you should see the Teams you are an owner of as workspaces
      • Choose one and click Select
    • When it is finished publishing you can go the Team, find a channel and add PowerBI report as a tab
      • In the workspace, you have published to, find the report and click Save
    • You have now imported one of the CQD PowerBI reports
    • Everyone that wants to see the report in Teams needs to have one of the admin roles mentioned previously
    • The report may take some time to load and this is because it is getting the data in real time. There is no supported way to pre-load the data at the moment

Need more Microsoft Teams insights like this? Check out the monthly updated book Office 365 for IT Pros where I write the calling and meetings chapter.

Updated my #Pomodoro #PowerShell timer

Ever been so busy you can’t get anything done? What do I do during those times? Spend time optimizing my productivity routine of course. June 2020 was super busy period for me and I found that my PowerShell Pomodoro timer needed some tuning to be easier to use. Download the updated script from GitHub. I have done the following changes

  • Hide Badges on taskbar buttons
  • Create a shortcut to start it in a fast and simple way
  • Fixed so that presentationsettings.exe works in 64bit PowerShell
  • Read my original post about this script
  • Pomodoro is a technique to induce flow in a busy workday through single tasking. Read more at the end of this blogpost

Hide badges on taskbar buttons

Instead of stopping Microsoft Teams, I hide the badges on taskbar buttons such as Outlook, Teams and Microsoft To Do. You must have access to changing the registry for this to work which was the best approach I could find.

#Hide badge or stop Teams
if ($Teamsmode -notmatch "HideBadge"){
    #Stop Microsoft Teams
    Write-Host "Closing Microsoft Teams" -ForegroundColor Green
    Get-Process -Name Teams -ErrorAction SilentlyContinue | Stop-Process -ErrorAction SilentlyContinue
    #Hiding badges on taskbar buttons such as Outlook, Teams and ToDo
    Write-Host "Hiding badges on taskbar buttons" -ForegroundColor Green
    Set-Itemproperty -path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'TaskbarBadges' -value '0'
    Stop-Process -ProcessName explorer

During hide badge you will not see status in the taskbar icons, which helps you keep focus during the Pomodoro sprint.

When the Pomodoro sprint is finished, it will show badges again

Showing badge on taskbar app is new in Microsoft To Do and can be turned on or off under settings, I prefer to turn it off

Create a shortcut to start it in a fast and simple way

In order to start the script in an fast and simple way, you can create a shortcut to the script.

  1. On you desktop, right click and select new shortcut
  2. In the shortcut target box, type the following:
    • powershell.exe -noexit -ExecutionPolicy Bypass -File
  3. File is the path where you stored the Start-SimplePomodoro.ps1
    • “C:\Users\UserName\OneDrive – CloudWay\Dokumenter\GitHub\MyScripts\Start-SimplePomodoro\Start-MySimplePomodoro.ps1”
  4. I have crated an Icon you can use for the shortcut which you can find on GitHub
  5. If you pin it to you taskbar, you can easily start your Pomodoro sprint

Fixed so that presentationsettings.exe works in 64bit PowerShell

I use presentationsettings.exe to put the computer in presentation mode which supresses popups from all you applications and Windows 10. This is an 32bit application. I found that 64bit PowerShell could not find this due to the feature, File System Redirector. I found a workaround and incorporated it in the script so that it works wherever you are running it

Write-Host "Starting presentation mode" -ForegroundColor Green
if (Test-Path "C:\Windows\sysnative\PresentationSettings.exe"){Start-Process "C:\Windows\sysnative\PresentationSettings.exe" /start -NoNewWindow}
else {presentationsettings /start}

By pointing 64bit PowerShell to the path C:\Windows\sysnative\ I was able to run 32bit apps like PresentationSettings.

The result

Download the script from GitHub

The goal is to induce the flow state in a busy workday

Multitasking is a myth. The goal is to reach the flow state by focusing on one task at a time. Have you ever started writing an email, thought you sent it and eagerly waiting for a response, only to find it incomplete and unsent at the end of the day? This is one of the perils of multitasking.

The Pomodoro Technique is a great methodology to induce flow in a busy workday. It is all about avoiding distractions for 15-25 minutes and focus on one task at a time. This is a short enough period in the day that you can squeeze it in before a meeting. It is incredible what you can get done 15-25 minutes. The goal is to not get distracted and it takes about 7 minutes of focus before you reach your flow state.

If you want to succeed with Pomodoro, you need to make yourself unavailable. Equally important, you need to make yourself available again when those 25 minutes have passed. That is why we created the Pomodoro PowerShell tool, and why I love the simplicity of this approach.

Watch an outtake from my session at Microsoft Ignite 2017 on single-tasking

Learn more on my thinking around single-tasking and tools available to succeed with the flow state, from this outtake of my OneNote LifeHacks talk at Microsoft Ignite 2017

Happy deep work!

Why certified for #MicrosoftTeams devices are important

Part of succeeding with Microsoft Teams in the organization is to use certified for Microsoft Teams devices. There is a difference between consumer devices and business headsets. The major difference for headsets is noise cancelling in the microphone and cameras support the Teams video codec.

A consumer headset is prone to amplify the sounds around you, business headsets focus on your voice and work better in noisy environments. Most importantly, headsets certified for Microsoft Teams support wideband audio with the SILK codec used in all Teams clients, which means you sound better for your audience than with a consumer headset. All certified for Teams devices will be updated to support the new SATIN codec coming in Q2 2020.

Devices certified for Microsoft Teams are all listed and updated at Some of the advantages for the end-users are:

For an administrator the advantages are:

What about certified for Skype for Business devices?

They support the SILK codec too, so all good, but they may not have newer functionality like the Teams button found on certified for Teams devices. You can even use certified for Lync 2013 devices. Everything older than that is not OK, like Lync 2010 and OCS 2007 certified devices. Reason? No support for wideband SILK codec. Keep this in mind if you have upgraded from OCS and Lync to Skype for Business to Microsoft Teams.

It is common to find consumer devices in business environments, because the awareness of the the above features are low. But this is important, because if we have done all the network optimization and made sure users are adopting Teams, the last mile with a proper device is where we fail too often. Use my CQD PowerBI report to identify devices used in your environment and correlate the findings with devices listed at

Want a PRO headset for focus while working and travelling that is certified? Check out this video where I run 5 stress tests on two high end focus headset which are certified for Microsoft Teams

Need more Microsoft Teams insights like this? Check out the monthly updated book Office 365 for IT Pros where I write the calling and meetings chapter.

Staying up to date with #Microsoft365 using #MicrosoftTeams

As a consultant, technician or system owner, staying up to date with Microsoft 365 is a daunting task. With changes seemingly happening daily, how do you keep up?

The Challenge

There are multiple sources for information on what happening with Microsoft 365

  • Service Health tells you about the current status of each service in your tenant
  • Message Center tells you about new features and breaking changes to your specific tenant
  • Microsoft 365 Roadmap tells you about what is planned and rolling out for each service
  • Office Pro Plus what’s new tells you about new features and capabilities of Word, Excel, PowerPoint, etc.

Some of the information requires that you have admin privileges in your tenant. The introduction of the Global Reader role helps in some capacity. Still, there are a lot of different places where you can find this information. A good example is the information about your tenant being migrated from Skype for Business to Teams, this is informed about through the message center, if you are not checking it you may miss the windows to postpone the upgrade.

The Solution

Use Graph and PowerShell to get this information, run it in Azure Automation and publish it to a dedicated team with channels per feature and source. From there your team can leverage the per channel notification in Teams where you can get notified of all new posts that arrives in a specific channel. In this way, you can easily get information about news that interest you and your focus area. Some may be interested in Teams, others may be interested in Intune.


Here you can set how you want to be notified from this channel, I chose to get a notification in my activity feed whenever a new item arrives

How to get there

Einar Asting, who I have worked with for the past two years at a customer site, has created and published all this on his blog and GitHub with how to get started and how to run it though Azure Automation. Check out his articles

How I use the scripts

The above routines work great, but they post to the same channel. I want to sort the information in the separate channels to make sure I do not get information overload. I have therefore a script that creates the team and all the channels which you can find in my public GitHub. I have also added the If Else routine to change the URI based on the category of the roadmap, health status, and message center items. I did not want to do this via a pull request to the original scripts as it requires much more work to get working and is more like an optional feature.

TeamsNotification script.PNG


The script post message cards using webhooks. There may be other methods to do this, but it works. The caveat is that you must manually create the webhook for each channel and there are 23 channels. It is a onetime job, so I guess you survive. I checked with Microsoft, there is no way to create a webhook today programmatically.

How to post categories to different channels

#Teams webhooks for Microsoft 365 Roadmap add to top of script
$M365RInfra = "Your Webhook URI"
$M365RExchange = "Your Webhook URI"
$M365RTeamsSkype = "Your Webhook URI"
$M365RSPOOF = "Your Webhook URI"
$M365RYammer = "Your Webhook URI"
$M365RIntune = "Your Webhook URI"
$M365RSecurity = "Your Webhook URI"
$M365RNextGenApps = "Your Webhook URI"
$M365ROffice = "Your Webhook URI"
$M365RCompliance = "Your Webhook URI"

#Determine which channel the post belongs to, place before the final invoke-restmethod
if ($category -match "exchange"){$uri=$M365RExchange}
elseif ($category -match "Lync" -or $category -match "Skype" -or $category -match "teams"){$uri=$M365RTeamsSkype}
elseif ($category -match "sharepoint" -or $category -match "onedrive"){$uri=$M365RSPOOF}
elseif ($category -match "Intune"){$uri=$M365RIntune}
elseif ($category -match "Yammer"){$uri=$M365RYammer}
elseif ($category -match "ATP" -or $category -match "Cloud App Secruity"){$uri=$M365RSecurity}
elseif ($category -match "Planner" -or $category -match "Stream" -or $category -match "Forms" -or $category -match "Bookings" -or $category -match "Whiteboard"){$uri=$M365RNextGenApps}
elseif ($category -match "Office" -or $category -match "Outlook" -or $category -match "PowerPoint" -or $category -match "To-Do" -or $category -match "Visio" -or $category -match "OneNote" -or $category -match "Excel" -or $category -match "Project" -or $category -match "Access" -or $category -match "Word"){$uri=$M365ROffice}
elseif ($category -match "Compliance" -or $category -match "Information Protection" ){$uri=$M365RCompliance}
else {$uri=$M365RInfra}

#Teams webhooks for Health Status add to top of script
$HCInfra = "Your Webhook URI"
$HCExchange = "Your Webhook URI"
$HCTeamsSkype = "Your Webhook URI"
$HCSPOOF = "Your Webhook URI"
$HCYammer = "Your Webhook URI"
$HCIntune = "Your Webhook URI"

#Determine which channel the post belongs to, place before the final invoke-restmethod
if ($inc.Workload -match "exchange"){$uri=$HCExchange}
elseif ($inc.Workload -match "Lync" -or $inc.Workload -match "Skype" -or $inc.Workload -match "teams"){$uri=$HCTeamsSkype}
elseif ($inc.Workload -match "sharepoint" -or $inc.Workload -match "onedrive"){$uri=$HCSPOOF}
elseif ($inc.Workload -match "Intune"){$uri=$HCIntune}
elseif ($inc.Workload -match "Yammer"){$uri=$HCYammer}
else {$uri=$HCInfra}

#Teams webhooks for Message Center add to top of script
$MCInfra = "Your Webhook URI"
$MCExchange = "Your Webhook URI"
$MCTeamsSkype = "Your Webhook URI"
$MCSPOOFB = "Your Webhook URI"
$MCYammer = "Your Webhook URI"
$MCIntune = "Your Webhook URI"

#Determine which channel the post belongs to, place before the final invoke-restmethod
if ($inc.AffectedWorkloadDisplayNames -match "exchange"){$uri=$MCExchange}
elseif ($inc.AffectedWorkloadDisplayNames -match "Skype" -or $inc.AffectedWorkloadDisplayNames -match "teams"){$uri=$MCTeamsSkype}
elseif ($inc.AffectedWorkloadDisplayNames -match "sharepoint" -or $inc.AffectedWorkloadDisplayNames -match "onedrive"){$uri=$MCSPOOFB}
elseif ($inc.AffectedWorkloadDisplayNames -match "Intune"){$uri=$MCIntune}
elseif ($inc.AffectedWorkloadDisplayNames -match "Yammer"){$uri=$MCYammer}
else {$uri=$MCInfra}



Microsoft Teams Private Channels introduction

Today at Microsoft Ignite 2019 one of the most requested features was announced as GA. Private Channels is a highly requested feature and enables users to create channels that only a subset of users can see.

Why did Microsoft introduce private channels?

The requested scenario is that a subset of users in a Microsoft Team needs to discuss and collaborate without everyone having access and seeing the discussions. Keep in mind that members of a private channel need to be members of the Team.

The scenario where I see this being very useful is in projects where the steering group wants to have their own closed channel and file location to discuss the progress of the project, share meeting notes and make decisions for the project. Another scenario could be the sales department wanting to store signed contracts that only a subset of users have access to.

This is a new feature and I urge you to use private channels with moderation in the beginning and try to design teams around the notion that users should have access to all the content in a team. Use private channels as the exception, not the rule.

How to create private channels

To create a private channel, you need to be a member with the ability to create private channels. When you create the channel, you get the option to make it private, you are asked to add members from the team you are creating the channel in. Here you see how you can make a private channel.


When the channel is created you will see who the members are, and the channel is marked with a padlock icon.  Here you see how you can differentiate between regular channels and private channels you are a member of


The creation of channels can be controlled on a Team setting level. Some facts about channel management:

  • Owners see private channels that they are not a part of under Manage Team and channel list.
  • Owners can control if members are able to create private channels in the Team under settings for the team
  • Owners of the team can delete or see the owner list, to reach out if cleanup is needed.


  • Owners of a private channel get to add member and control @mentions and Member permissions, under manage channel and settings.


What are the features available today?

  • Chat and files are available from the GA date and are rolling out in November 2019
  • All members of the private channel need to be part of the original team
  • There are some limitations on apps available today, such as Planner and Stream connected to the channels, these are on the roadmapPrivateChannels4.PNG
  • When you create a private channel, it creates a new SharePoint TeamSite for that channel. This is to make sure control of who can access the files.
  • Administrators can find private channels in the Teams admin center


  • Administrators can also find the SharePoint sites using the SharePoint PowerShell module using the template property
    • Get-SPOSite -Template TEAMCHANNEL#0
    • you can see that the site name includes the original team name, which means you can find out how many private channels are set up per team
    • The ability to see all private channel team sites in SharePoint admin portal will come later


My post-migration from Skype to Teams toolbox

When migrating from Skype for Business Server to Microsoft Teams you may find that users are not migrated with the correct features as intended. If the migration also includes moving Enterprise Voice workloads and switching to a Direct Routing or Calling Plan setup, you may find it difficult to get a full overview of what state the user is in and if all settings are correct.

I found that this Skype for Business Online PowerShell oneliner gave me the overview I needed to see if there were configuration issues or wrong settings. Hope this helps you in your post-migration cleanup process

 Get-CsOnlineUser | Format-List UserPrincipalName, DisplayName, SipAddress, Enabled, TeamsUpgradeEffectiveMode, ` EnterpriseVoiceEnabled, HostedVoiceMail, City, UsageLocation, DialPlan, TenantDialPlan, OnlineVoiceRoutingPolicy, ` LineURI, OnPremLineURI, OnlineDialinConferencingPolicy, TeamsVideoInteropServicePolicy, TeamsCallingPolicy, HostingProvider, ` InterpretedUserType, VoicePolicy, CountryOrRegionDisplayName  <br />


Some explanation

  • TeamsUpgradeEffectiveMode – Should be set to TeamsOnly, if not, try to change it again and look at the error message
  • UsageLocation, DialPlan, and TenantDialPlan – When using enterprise voice together with Microsoft Teams, UsageLocation is important. It decides the number you get as part of AudioConferencing and your DialPlan. The default DialPlan just adds a plus and country code to whatever you type in Teams and is rarely good enough. You should supplement with TenantDialplans, don’t crate them yourself, use by MVP Ken Lasko. UsageLocation is set using the MSol PowerShell module.
  • LineURI, OnPremLineURI, and VoicePolicy – if your VoicePolicy is set to BusinessVoice you have a Calling Plan assigned, if it is set to HybridVoice, you are using Direct Routing. This is good to know if you are troubleshooting why LineURI is not updated by OnPremLineURI for Direct Routing. You should also know that if you are not able to set OnPremLineURI using Set-CsUser using online PowerShell, then you have msRTCSIP-LineURI populated in local Active Directory. If you clear this attribute, you get write access to the OnPremLineURI online.
  • InterpretedUserType – is a great source of information. It tells you the status of the user. If you have any attributes in local Active Directory it will be set to HybridOnpremSfBUser. If for some reason the user is disabled it will show in this attribute as something with disabled such as DirSyncDisabledSfBUser. Read this useful blog article that goes into this in more detail

On-Premises attributes cleanup

If InterpretedUserType has the value of HybridOnpremSfBUser, then you need to clean up on-premises attributes if you are fully moving to Microsoft Teams and are decommissioning your on-premises deployment. The best way is to use Disable-CsUser to remove all Skype for Business related attributes on a user. More often than not, we see that this command is not run before decommissioning the deployment, so you need to remove the properties manually, here is a routine to detect all msRTCSIP attributes and then to clear them in Active Directory. Based on the type of configuration the user had before servers were removed, the properties with a value may be different per user so using ‘msRTCSIP*’ is a good way to catch the attributes for that specific user.

#Get all msRTCSIP properties for a user that has a value
$Properties = Get-ADUser -Filter {UserPrincipalName -eq ""} -Properties * | Select-Object -Property 'msRTCSIP*'

#Clear all properties for a user
Get-ADUser -Filter {UserPrincipalName -eq ""} -Properties * | Set-ADUser -clear ($Properties | Get-Member -MemberType "NoteProperty " | % { $_.Name })

To learn more about InterpretedUserType and the values it can be set to, read this useful blog article that goes into this in more detail

Get a more in-depth explanation and read more about tips like this in the highly recommended Office 365 for IT Pros eBook, the only constantly-updated book covering Office 365 and associated technologies. You can buy a copy of the book at ( – EPUB/PDF version) or (Amazon – Kindle).

Did you know that you can control notifications from #MicrosoftTeams channel @mentions? 

Yep, it’s true, here is the scenario

  1. You are joined to a lot of teams with high activity and people are @mentioning the Teams and channels because internal emails are moved to Teams, which they should!
  2. Every day you get back to work, you have a huge amount of notifications to go through in your activity feed because people are @mentioning everything all the time to get attention
  3. You are starting to wonder if Teams is a fad and are longing back the thousands of unread internal email messages in Outlook instead

Here is the solution

  1. To avoid getting a notification when someone is @mentioning a channel
    • Go and unfavorite itUnfavorite
    • You still get a notification when someone @mentions your name
    • You cannot unfavorite the General channel, this is why it should be only used for off-topic discussions, wins or general announcements
    • Want to go the other way and get notified whenever someone is talking in a channel? Go and follow the channelFollow
  2. To avoid getting a notification when someone is @mentioning a team
    • There is no way to avoid getting a notification
    • This is why you should refrain from mentioning a team unless it is at the utmost importance
    • You can actually turn off that people can mention either a team or a channel as owner under Manage Team -> Settingsmentions

That’s it really. Now you know it is a huge difference in @mentioning a Team vs channel. #LifeHack