Sunday, 10 May 2020

TechNet Gallery to GitHub Migration Tool

As you may or may not be aware Microsoft are making a move to close down the TechNet Gallery web site. This website is the location where I had previously posted all of my tools over the past few years and is also jam packed full of other great community tools as well. In the first stage of the shutdown, Microsoft has put the TechNet Gallery pages into a Read-Only mode where you can still edit existing posts but cannot create new posts. This first step is to give people time to download their posts and move them to another location before the final shutdown of the site.

I find this news to be quite concerning because I know that I still find useful resources on TechNet Gallery all the time. So I've decided to try and do something to help people move their content off TechNet gallery to a safe harbor before it's too late. To do this, I decided to put together a PowerShell tool that will both download content from TechNet Gallery and prepare it for upload directly onto GitHub. This post also describes the steps to uploading the files onto GitHub to make the process as easy as possible.

How does the tool work? Well, you feed it one or many TechNet Gallery URL(s) and it will download the posted file and all the text and images from the site into a folder for you. In addition to this, it will convert all of the text into a Markdown based README.MD file (and refactoring image URLs to move to GitHub) so it can be directly uploaded to GitHub to display the exact text that you had on your TechNet Gallery post (minus any code snippets). All you need to do after this is follow a simple process of creating a new GitHub repository and upload these files to it. You will then end up with your TechNet Gallery content re-hosted in a very similar format on GitHub.

The Differences Between TechNet Gallery and GitHub

TechNet Gallery was designed to be a relatively simple CMS style system that allowed you to upload a file (of any type) and put some blog post style text and images with the file to explain whatever you wanted about the file. This concept is fairly easy to understand and didn’t offer too many bells and whistles. GitHub on the other hand was designed to be a source code repository with versioning features and functionality built in. As a result, GitHub has a much bigger capability set and complexity level than TechNet Gallery.

What does that mean when moving files and content over from TechNet Gallery to GitHub? It means that you have more options for how you can post and manage your files. For example, you could simply use it as a location to put your files or you could potentially start using the Git application workflow to manage the versioning of your files. Using these more complex components of GitHub is out of scope for this blog post. You could quite easily “git init” the folder that the tool creates and then link this up to a remote GitHub repository as a way to upload the content. I will assume if you know how to use Git then you’ll be more than capable of doing this yourself, and if not, then you don't have to use these features or you can read up on them as you see fit.

Backup / Migration Procedure

For the purposes of this blog post I am going to make this the simplest procedure possible which does not require that you install and use Git. Instead the process will use the GitHub web interface to upload your files for storage on GitHub in a similar way to how you would have used TechNet Gallery.

Firstly you need to go and get the URL of your TechNet post. This will look something like this one for one of my posts:

Once you have this you will need to sign up for a GitHub account. This is free and offers you a heap of functionality without asking you any of your hard earned dollars (thank you Microsoft!). I’m not going to show you how you do this because it’s pretty straight forward. When you sign up you will be asked to create a GitHub account name. You will require this account name if you are migrating your images over to GitHub using the tool.

Head over to my GitHub repository and grab of a copy of the script I wrote for downloading the files and generating a file for use on GitHub. Click the link below to go to the repository:


When you run the tool you can either use PowerShell flags to input your information into the tool or not use any flags and the script will ask you to input the information that's required. The flags that the tool uses are as follows:

-MoveImagesToGitHub (Default TRUE) - When set to $false you can retain the original location of the images from the TechNet post in the GitHub file. If these originally pointed to an external location then you can keep them there but if you uploaded them to TechNet Gallery you will want to move them as they will disappear when the site is taken down.

-TechNetURLs - This flag is where you can input a comma separated list of all the TechNet URLs that you want to download. If you don't use this flag the tool will ask you for a URL when it runs.

-GitHubAccount -  This flag is used for updating image URLs with the GitHub account location where it's going to be stored. This will be the account name that you sign into GitHub with. If you don't use this flag and the script determines that it's required it will ask you for it.

-GitHubRepo (Default TechNet Post Title) - This is the Repo name that the files will be uploaded to. If you don't enter this then the TechNet title will be used. If you have a specific name you want to use then use this flag to set it.

To run the script with flags you will use the following format:
.\TechNet-Gallery-to-GitHub-Migrator.ps1 -TechNetURLs "", "" -GitHubAccount "<your account name>"

After you have run the script it will generate a new folder for each TechNet Gallery post in the root folder that you ran the script from. These folders will be named using the title of your TechNet post with dashes replacing spaces. This is a common naming convention for GitHub repositories (not the only way, but a common one). The script is designed based on the assumption that the repository that you create in GitHub will have this same name (and same format).

Sign into GitHub with your account. Within GitHub go to your Repositories page. In here you will see a green button marked “New”. Click this button to create a new repository:

To name the repository, copy and paste the name of the folder that the tool created (this is the same as the TechNet Gallery post title). I recommend you use this same name for your GitHub repository when you create it (unless of course you wrote weird or super verbose things in your title to try and up your SEO). Below I have copied the name of the folder:

The New Repository page on GitHub asks for the following information:

Fill in the repository name and description with the folder name that the tool created. Select “Public” repository type if you want others to be able to see it on the Internet. Once you have done this click the “Create repository” button.

You will now be taken to a page that tells you how you can connect to this repository using Git methods. However, we are just going to use an entirely web based creation process for simplicity. Click the “Uploading an existing file” link as highlighted below:

You will now be taken to a page for uploading your files. Drag and drop all the files from the folder (the script created) on the web browser window in the location shown below:

You should now see a list of your files in the page as seen below. Click the “Commit changes” button to upload the files:

You will see your newly created repository with all your files in it. The contents of the file will be displayed in all its glory below this as GitHub uses this as your repository’s information text by default. It should also render all the Markdown in the file nicely with headings, bolding, dot point and images being displayed. This should make the page look similar to what you would have seen on the TechNet Gallery page for your content!

 Tweaking or Changing the Text

Minor tweaking may be required on the document to perfect the layout. The good news is you can do any corrections you need to do in the GitHub web editor. Simply click on the file and then click the Edit button. This will take you to a text based editor in the web page where you can make your changes. In this example the Protocol Documentation heading is not quite rendering properly as being bold because there is a return carriage between the second set of asterisks. So I just need to simply move them up to the line that they heading is on and click the Commit Changes button at the bottom of the page.

Note: Code snippets in the TechNet Gallery text will not be carried over to the file (lots of people include their entire scripts in the body text which doesn't translate well to markdown). If you have put smaller lines of code examples in your text you will have to add them manually to the file.

And you’re done!

What Next?

The good news is that you have a publicly available backup of your TechNet Gallery content. It's up to you on how you would like to administer this moving forward on GitHub. As I mentioned earlier, you may choose to start using the Git workflow and downloading and managing your repo(s) with Git commands (commit, push, etc). You may also choose to use the Releases page in your repo to generate tagged and versioned releases. It will depend on the type of project that you are migrating as to how you may choose to do this. For a project that is not getting changed much you may just choose to put up and leave it. However, for a project that you are actively doing a lot of updates on you may choose to start using Git. There are many resources on the web that will explain Git and how it works. Git will be a lot to digest when you first start using it and it's something that you really need to start using in practice to get your head around. As they say; there's no better time to start something than right now, so hop to it!

The Wrap Up

I have migrated 14 of my tools that were up on TechNet Gallery using this process so the process has been trialed and worked successfully for me. As I mentioned earlier in the post; TechNet Gallery has loads of great content on it which I really hope does not disappear into the abyss when the site is closed down because people put the migration in the too hard basket. I really hope that this tool and blog post do something to make the process a bit simpler and give you a framework by which to migrate your tools as well. If you have any issues with the script, let me know.

Read more →

Tuesday, 21 January 2020

Portals for Office 365

Office 365 is amazing: it has tonnes of great applications and tools for getting your work done. However, it can be quite overwhelming at times, getting access to all the applications and administrative portals it offers. It can be especially hard when you have multiple accounts and/or different tenants, whether that be full accounts or guest account access in Microsoft Teams. I wanted to make this easier, so over many months I developed an application that was designed to give you a simple workflow for accessing the various administrative and user tools within Office 365. This application I call Portals.


For more information on releases, check out the change log over at GitHub:

Known issues:

The app has the following known issues:
  • Screen sharing does not work within meetings (although sharing of PowerPoint presentations does). This is due to an issue with Electron using a closed display capture methodology. Currently there doesn't seem to be the impetus for them to change this at this stage (
  • When in edit mode and moving accounts up and down, the open or closed state of the accordion item for the account will not move with the account. The open or closed state of the items prior the move will be retained after the item has been moved. This is weird but usable 😊
  • Portals currently references the normal Enterprise Office 365 portal URLs to connect to services. This means it will not be able to connect to any different URLs that may be used by the other specialised Office 365 cloud variants (eg. 21Vianet, DOD or GCC versions).
  • In Power BI if you try to update a dataset's authentication with OAuth the Power BI site will launch a new window and do a redirection which fails. The window will open and then disappear without you being able to authenticate.
  • Exchange ECP has some pop up dialog windows such as the user selection pop up in the Shared Mailbox configuration section that uses a method of passing information between windows that doesn't work with Portals. This currently is a limitation. 

If you have specific feedback about the app you can send it to myteamslab(at)

(Simply download and install the "PortalsInstall-win32-x64.exe" installer file from the GitHub releases page. All future updates should automatically get pushed to you without you needing to manually download them)

Portals Walkthrough Video

Rather than write many thousands of words that you may not have the time or energy to read, I opted to make a walk-through video of the application. This should give you a quick and hopefully painless overview of the main capabilities of the app.

Adding Accounts

When you add an account, you can add either a regular account which has access to all the applications within Office 365 (this might depend on the account licence level, e.g. E1, E3, or E5 licenced account for example) or a Teams Guest account. The purpose of the Teams Guest account type is to allow you to create a separate account session that can log into a Guest Account tenant in a separate window from your home account. This allows you to have both Guest Accounts and your regular account Teams sites open at the same time (woot!).

Tenant Name for Regular Accounts:
To add an account click the Add Account button:

You will then be presented with the Add Account Dialog. You enter the Email Address of the user for which you want to add an account:

After this, you have a fill in the Tenant Name. When you’re adding a regular account, the Tenant Name is used within SharePoint and OneDrive URLs. The easiest way to find out what the Tenant Name needs to be is to log into the website in a browser and then click on the SharePoint item:

This will open the SharePoint home page for your tenant, which will have the tenant name at the beginning of the URL -  as shown below:

When you click on the SharePoint portal, the URL will use the tenant name you enter in Portals as shown below:

Below is an example of the format of the working OneDrive URL:

If you get the tenant name wrong, then the SharePoint and OneDrive Portals will not load properly.

Tenant Name for Teams Guest Accounts (when you’ve ticked the Guest Account checkbox):
When adding a Guest account, the Tenant Name should be the name of the organization for which you are a Guest. In this example, John Woods is a guest account for a partner organization called “mylynclab”.

This name does not matter as much as the regular account tenant name, as it’s not used in any of the URLs. Instead, it gets added as a designator in brackets next to the account name to signify to you which tenant the guest account is accessing. This is an example of what the account looks like once added (in this case mylynclab is the tenant for which John Woods is a guest):

Password Security

Portals does not save any of your Office 365 passwords. It behaves in the same way as a browser does, when you sign into Office 365 using Portals the application is given a temporary access token by Office 365. This token and all other cookies presented to Portals are encrypted with AES 256 encryption and a long random password when they're written to disk. So your passwords are never saved and any temporary access tokens are fully encrypted.  

It's recommended when you sign into Office 365 in the Portals that you select to stay signed in. This way you don't have to keep putting in your password. Example:

Edit Mode

In edit mode you are able to edit the layout and setup of the Launcher window. When you click the edit button you will see all the portal icons start to wiggle. This lets you know that you can move them around. Crosses will also appear on the right hand side of portal buttons so you can delete them. There will also be a few extra buttons that appear at the bottom of each account section, which allow you to add portals, edit the account preferences for each account, and delete accounts. Finally you will also see an up and down arrow next to each account appear which allows your to reorder the accounts up and down in the accordion view. Using these tools, you should be able to craft a layout that suits your specific needs.

Toast Notifications

When using Microsoft Teams it's important the when people are trying to call or message you that you are aware of it. This is especially the case when you are logged into various Teams accounts at the same time.  As a result, I have designed the app to have a Toast based notification system that will pop toasts when you receive an inbound call, direct message, or team based notification. When you click on the toast the app will bring the window that the notification came from to the front so you can quickly and easily answer the call or respond to the notification.

Below is an example of a Calling toast (in this case Bob Kelly is getting called by a John Woods):

Below is an example of a Notification message (in this case Bob is getting a message from John Woods):

Each account has been given its own settings for turning off notifications for calling and messaging within Portals. These can be accessed by clicking the preferences button under an account when in edit mode. The two checkboxes can be seen below:

If you would like to have more granular control over which message notifications will pop toast windows you can go into the Teams app settings (Click on your user profile in the top right of Teams > Select Settings > Notifications). In here you have full control over the type of notifications that you will receive a toast message for (just like in the Teams app).

An example of this is that if you have "Banner and feed" set for "Like and reactions" then you will receive a toast like this one:

If you were to set "likes and reactions" notifications to "Off" then you wouldn't get any toasts when people react to your posts. This gives very fine control over how many toasts you will receive in Portals.


I have not previously accepted any donations for any scripts or apps that I’ve released. However, in this case I spent a huge amount of time working on this application and I feel that I’ve built something that will help with some major pain points that many people have with Office 365. As a result, I added a Paypal Donate button into the Preferences dialog which you can use to make a donation representative of the value you feel you get from it. I have also built the application to support automatic updates and I would like to continue to develop and improve the app where possible, so donations will certainly help to keep encouraging me to put further time into it. If you choose to donate, then I thank you very much. link:

The Wrap Up

It’s safe to say that this is the largest and most complex application I have made and released to the public. It’s essentially a completely customized web browser, built for a specific purpose and workflow of my design. When I started the project many many months ago I hadn’t developed anything in Electron or even written anything serious in Javascript before. As you might imagine the learning curve has been large but I’m happy with the way the application has turned out so far and have high hopes for its future. Thanks for reading and downloading, enjoy!

Read more →

Tuesday, 8 October 2019

Microsoft Teams Bandwidth Usage Deep Dive

I was recently reading this Microsoft Docs article called “Prepare your organization's network for Microsoft Teams” which says the following:

“The actual bandwidth consumption in each audio/video call or meeting will vary based on several factors, such as video layout, video resolution, and video frames per second. When more bandwidth is available, quality and usage will increase to deliver the best experience.”

I found the comment about bandwidth availability to be interesting and wondered how this actually functioned in practice. So I did (what turned out to be) a lot of testing to see exactly how the client behaves under various network and policy constraints and I thought the outcomes were interesting enough to write an article about. So steel yourself and lie back and think of Redmond as they say in the classics…

Note: The testing in this article is a point-in-time sample of how the product worked when the testing was done (Late September 2019). Office 365 is constantly being updated and things may change over time. If you have seen things operate differently or Microsoft provide information contrary to that documented here let me know.


The Teams service, at the time of writing this article, does not support individual Call Admission Control features. However, in the Teams Portal Meeting Policy there is a setting called “Media bit rate (KBs)”. This setting is shown below:

A bugbear I have with the naming of this setting is that it includes “KBs“, which to my eyes means Kilo Bytes per Second (ie. a capital ”B” means Bytes and a lower case “b” means bits). However, this is not the case - this setting is actually configured in Kilo bits per second (ie. Kbps). I have lobbied Microsoft to change this. We’ll see how that works out.

As you will see the default value for this setting is 50000 which seems kind of crazy because this is 50Mbps. In my opinion, this probably would have been better being represented as “Max” or “Unlimited” or anything else rather than this very high number. I can imagine the poor consultant that goes into the meeting with the networking team and says that the Teams client is currently configured to use 50MBs worth of bandwidth per user… Oh, to be a fly on the wall in that meeting… The truth is that this setting is basically telling the system to place no restraint on the maximum bit rate used by the Teams client or service (as 50Mbps will never be reached). So in practice, a Media Bit Rate setting of 50000 means that the Teams client and Teams service will function without any networking constraints. This means that Teams will try and use the maximum audio codec and video codec resolution and frame rate that it can. Read on to see how the client behaves under network constraints.

The example below shows what a setting of 800Kbps looks like:

Testing for this Article

During the writing of this article I did a great deal of testing using the Media Bit Rate settings within the Meeting Policy and by using networking tools to artificially limit network traffic to test the effects on the Teams client. During the testing the bit rate in and out of the PC running teams was monitored using Wireshark’s IO Graph feature which essentially counts the number of bits in each packet captured by a specific Wireshark filter. In this case the filter was capturing traffic based on Microsoft’s Teams media IP Address range 52.114.x.x to see exactly how much traffic was being transferred up and down from the cloud in each scenario.

During the tests the Teams Meeting Policy Media Bit Rate setting was used in conjunction with limiting bandwidth using a network emulator tool to see how the client behaved under different circumstances. In most cases a scheduled meeting was used with two parties joining from two clients running on PCs with typical i7 Intel CPUs you would expect to see in a business laptop. For consistency, each test meeting had the same 1080p video being sent via VBSS screen sharing from a PC that did not have any bandwidth constraints applied to it. All bandwidth limiting was only done on the PCs that was receiving the screen sharing traffic in order to avoid any compounding quality issues caused by limiting both client streams. The bandwidth limited client was viewing the screen shared video over the constrained link so the changes in quality could be monitored. Both of the clients also had their video cameras enabled which was displayed as thumbnails down the bottom right of the screen, however, this was covered up by the bandwidth graph. Be aware that this bandwidth was also there in the test calls.

During the testing and in the test videos Wireshark’s IO Graph is displayed in the bottom right hand side of the screen. For most of the testing this graph displayed with an SMA (Simple Moving Average) of 10 in order to smooth the graphs to see the average bit rate making it easier to compare with the Media Bit Rate value set in the Meeting Policy.

The videos supplied in this article are directly screen captured using OBS software running at 1080p and with 44khz audio. It offers a reasonable representation of the quality actually seen on the laptop screen, with perhaps only a small bit of additional compression distortion. When watching these videos on YouTube ensure that you have the quality set to 1080p in the video settings so you’re seeing an accurate representation of the video and are not adding additional artifacts when watching the YouTube stream.

For future reference the software versions used during testing for this article were:
  • Microsoft Teams Version (64-bit). It was last updated on 9/12/19
  • Microsoft Edge version 41.16299.1004.0
  • Google Chrome version 77.0.3865.90
  • iOS Mobile Client version 1.0.85

Network Based Bandwidth Limiting

The cloud has now ushered in a new world where applications can connect to O365 from basically anywhere that has Internet access. This means that administrators don’t have the luxury of knowing that their perfectly manicured and QoS enriched networks are always being used by applications anymore, so it is important to understand how applications will behave under various non-perfect network conditions. With that framing in mind, I wanted to see exactly what the Teams client does when you limit its bandwidth to O365.

When left at default settings (Media Bit Rate of 50,000 Kbps) the Teams client, practically speaking, does not have a fixed ceiling on the bandwidth that it can use for a call/meeting. The limits are simply based around whatever the maximum data rate of the audio and video codecs running at their maximum resolution and frame rate will allow. In reality, the client will only reach the maximum data rate of the codec whilst keeping under a certain packet loss rate (and potentially other media quality thresholds that I can’t easily test). In order to show the way this works in practice the following test case shows a meeting where the bandwidth available to the Teams client starts off at an unlimited amount followed by the network being limited all of a sudden to 500Kbps:

Bandwidth conditions change (22 secs into the video) during a meeting change from unlimited bandwidth to 500Kbps:

Note: Set the YouTube video quality to 1080p when watching the videos.

The bandwidth limit is applied at 22 seconds into the video right when the man waves after joining the meeting. The video freezes at this point for about 8 seconds as the Teams client recognises that the loss rate has increased to a point where it ramps down the video resolution and frame rate to try and stem the losses. When a suitable new bit rate has been found the Teams client will then use this new bit rate until more bandwidth becomes available. In a scenario where the client software doesn’t have this capability to ramp down the data rate, and the the original stream resolution/data rate was maintained, the video playback would not have recovered. In addition to this, the already saturated network would have continued to deliver a high data rate stream that would further choke the existing bottleneck in the network. If you consider the scenario when you might have tens or hundreds of Teams clients in a meeting that crosses the same network bottlenecks to get to O365, this ability to ramp down the bandwidth and find a safe balancing point for all users allows for meetings to continue where they might otherwise have failed due to overwhelmed network infrastructure.

What you might see in the field is that users are complaining that the video or screen sharing quality is not very good (ie. low resolution and low frame rate video). In this case it is highly likely that the client has been forced to decrease the stream quality to deal with limited data network bandwidth. So you should confirm that the network links that the Teams clients are using to get to O365 are not saturating and reporting data loss on them. You could potentially get a user (or someone capable of testing the network) to use a tool like the Skype for Business Network Assessment Tool or my Network Assessor Tool to check the link quality to O365. In the case where links are maxing out you might start to see results going over the recommended thresholds, like in this example:

What happens when bandwidth becomes available again?

Now that we know that the client can reduce its bandwidth usage when the network is congested, what happens when the network bandwidth becomes available again? To test this case I started the meeting with a 200Kbps bandwidth limit and then released the limit back to unlimited bandwidth to see how long it took to ramp the data rate back up again:

Bandwidth conditions change during a call from constrained 200Kbps to unlimited bandwidth (at 10 seconds into the video):

Note: Set the YouTube video quality to 1080p when watching the videos.

This case operates slightly differently to the previous test. In the previous test it was obvious to the client that the bandwidth was dramatically reduced because it would have almost instantly seen the packet loss rate go through the roof. As a result, the client could swiftly ramp down the data rate until the packet loss stopped. However, in the case of bandwidth becoming available again, the client needs to slowly ramp up the data rate and monitor the packet loss rate to see that it hasn’t put too much traffic on the link. If this is done too fast then the flooding of the network with more traffic could be very detrimental and lead to data link queuing and dropping traffic again. In the video above you will see after removing the bandwidth constraints at 10 seconds it takes the client about one minute to ramp the data rate back up. In practice this could be seen as being a bit problematic if there are data links that frequently get congested as the client will take much longer to increase the bandwidth than reduce it.    

How does the client determine when to ramp down the bandwidth?

In the testing above it appears that the client uses packet loss to determine when the client will reduce its data rate. In the following test a random packet loss algorithm was put on the network link to test this theory. There may actually be more thresholds like jitter that are also taken into account here,
however, packet loss is easiest to use for testing purposes. The following cases show how adding 40% of random packet loss will cause the Teams client to ramp down its data rate:   

Note: Set the YouTube video quality to 1080p when watching the videos.

It’s difficult to know exactly what the thresholds are that the client uses here, however, you can see in the video if you increase the packet loss enough the Teams client will start lowering the data rate to try and reduce load on the network and hopefully stop the packet drops from happening. Note: Please ignore the quality of the video in this case as there is a constant random drop of 40% that continues for the whole video. The point here is just to see what the Teams client and service will try and do in this circumstance. 

Policy Base Bandwidth Limiting

By default the Teams client will use as much bandwidth as the Meeting Policy allows for its meetings and peer to peer calling. The setting in the Meeting Policy that controls this limit is called “Media bit rate (KBs)”. As mentioned earlier, I take a bit of issue with the way this setting is labelled currently with KBs. This nomenclature indicates to me that it’s a value in Kilo Bytes per second, however, this setting is actually interpreted by the system as kilo-bits per second (Kbps). I have raised this typo with Microsoft so it may get fixed at some point but for now don’t misinterpret this to mean Bytes as it is in fact bits. By default this setting is set to 50,000 which means that 50Mbps is allowed for media streams. This value is the equivalent of saying that unlimited bandwidth is available because 50Mbps is not going to be reached in any practical scenario.

When the Media Bit Rate setting is used then the client and O365 meeting service are told to enforce some average bit rate values when generating video and audio streams. This value is enforced in both directions, so for example if you set a value of 800Kbps then it would allow a stream of 800kbps from the client up to O365 and an 800Kbps stream down from O365 to the client. This is a combined total of 1600Kbps for both up and down streams. When you’re talking to networking folks they will usually talk about uni-directional values on full duplex links in describing bandwidth used, so from that perspective it’s described as an 800Kbps stream. The Media Bit Rate basically becomes the new average bit rate ceiling for all calls made from a client with the Teams Meeting Policy assigned to them. If the client experiences packet loss it will still ramp down to a lower resolution and frame rate in the same way as it does when there is no Media Bit Rate policy assigned.

The video below shows a call with an 800Kbps Media Bit Rate set. You will see in this video that the average bit rate (graph is displaying an SMA averaged value) will never go over 800Kbps as a result of the 800Kbps setting being made:

Note: Set the YouTube video quality to 1080p when watching the videos.

You will have noticed I used the term average bit rate here rather than peak bit rate. These two concepts are quite different: average means that over some period of time the bit rate when averaged will turn out to be under a specific value, however peak bit rate means that at any point in time the rate must always be under the bit rate. To show the difference the video below has both an averaged SMA graph and a non-SMA (ie peak style graph) displayed. In the meeting the client had an 800Kbps Media Bit Rate set and at 50 seconds in the network is limited with no queuing (ie. anything over 800Kbps is dropped). For this video the graph is showing an SMA graph of the averaged data rate (Blue) and a non-averaged data rate (Red) to show the true peaks of the data usage:

Note: Set the YouTube video quality to 1080p when watching the videos.

What this shows is that the data rate described by the Data Bit Rate value is actually an average bit rate instead of a peak bit rate. This can be seen by the blue average line never crossing the 800,000 bit (800Kbps) line but the red peak bit rate line spiked significantly above this value. At the 50 second mark the network was strictly limited to 800Kbps and as a result packets from the media stream that went over 800Kbps were dropped. You will see that the video freezes for a couple of seconds at the 50 second point due to this change and the quality of the video dropped slightly. This bandwidth constraint caused the media stream to suffer losses and have to decrease the video quality (resolution/frame rate) to keep the peak rate under 800Kbps which made the average (blue SMA line) drop to about 500Kbps. In practical circumstances the network will likely queue the media stream packets and still deliver them to the other end avoiding the packet loss which led to the resolution/data rate decrease. However, if there are any network devices that are not queuing traffic but instead dropping it then your 800Kbps stream might suffer and be forced to ramp down the bit rate itself to keep the stream at an acceptable level.

What about peer-to-peer calls that go directly between clients - do they also follow this Meeting Policy?

The answer here is - yes they do. The video below shows a peer to peer call between two Teams clients with the Media Bit Rate set at 800Kbps. You will see that the average bit rate never goes over 800Kbps for this call:

Note: Set the YouTube video quality to 1080p when watching the videos.

Do the Browser based or Mobile clients follow the Media Bit Rate setting?

From my testing of the Google Chrome and Edge (classic) browser, they do not follow this setting. This can have a profound effect on your network if you think that you’ve limited all clients to a specific bit rate only to find out that there are some clients on the network still running with unlimited bandwidth ceiling. Below is the Chrome and Edge browsers tests I ran to prove this:

Meeting using Chrome Browser with 800Kbps policy limit set:

Note: Set the YouTube video quality to 1080p when watching the videos.

Meeting using Edge (Classic) Browser with 800Kbps policy limit set:
Note: Set the YouTube video quality to 1080p when watching the videos.

In addition to this, I tried the iOS Teams client to see if it would have its Bit Rate limited by the Media Bit Rate policy setting. It turns out that it also doesn't appear to follow this setting. Note: In this video i'm doing a screen mirror from the iPhone to my PC and getting a Wireshark capture (of the traffic to O365 from the phone) of the traffic off a monitor port of a network switch the traffic was travelling through. The quality of the video being displayed is not as good as was actually displayed on the phone due to it being streamed over the screen mirroring protocol, but the bit rate usage displayed should be accurate.

Meeting using iOS (iPhone 7) mobile client with 800Kbps policy limit set:

Note: Set the YouTube video quality to 1080p when watching the videos.

The Wrap Up

If you have taken the time to read this entire 3000 words article and watch the videos, congratulations! I hope that you’ve learnt a thing or two about how the Teams client and Teams service will behave under different network conditions. Doing all this testing has definitely given me some insights on how the client and service actually use bandwidth as opposed to how the maximum and average codec bandwidth tables in the Microsoft documentation describe the usage. As far as the Media Bit Rate setting goes, there's not a huge number of cases where I can see this being useful over the automatic bandwidth management provided by Teams. If there was a case where you had constrained links and you really didn't want Teams taking bandwidth over a specific ceiling bit rate then you could use this setting. However, it's a pretty restrictive and will set a quality ceiling for all calls for users with the Policy applied to them. Not to mention, if the user moves to another location they will have this limit following them everywhere, which is not ideal. With the setting available, my recommendation is to let Teams do it's thing. If you're getting complaints about video quality on calls then you need to look into where there are bandwidth bottlenecks on your network and see if bandwidth can be increased to meet the needs of users. Optionally if the bottleneck is on an internal network then Diffserv DSCP values could potentially be used to tune the queues for the Teams media traffic (however, this is perhaps a completely different topic for another time). Till next time, au revoir!

Read more →

Thursday, 5 September 2019

Teams Tenant Dial Plan Tool

I recently released a tool for configuring Direct Routing within an Office 365 tenant. Its name is the imaginative Microsoft Teams Direct Routing Tool. This tool, whilst allowing you to configure all your PSTN Gateways and Routing, did not allow you to configure the normalisation of numbers that users dial prior to being routed. This step in the process is very important because nearly all users are not going to dial phone numbers in E.164 format. As a result, prior to getting to the E.164 based routing rules we need to do some work to ensure that the numbers dialed have been converted into the right format. The number normalisation in O365 is done by the Tenant Dial Plan policies, which contain normalisation rules. The configuration of these are done using the Skype for Business Online module and bunch of pretty complicated PowerShell that really shouldn’t be inflicted on a regular human being. So to try and avoid this pain, I decided to make a sister tool to my Direct Routing Tool that will allow for simple configuration and editing of these Tenant Dial Plans. This time, in order to ensure that I came up with the most imaginative name possible for the tool, I trekked into the deepest jungles of Peru on a vision quest where after drinking several litres of Ayahuasca came up with the name “Teams Tenant Dial Plan Tool”. Enjoy…

Teams Tenant Dial Plan Tool

The Tenant Dial Plan Tool is a PowerShell based tool that allows you to configure and edit Tenant Dial Plans within Office 365 for use with Microsoft Teams Direct Routing and Calling Plans. This tool is a sister tool to my Microsoft Teams Direct Routing Tool that allows you to configure all the routing for Direct Routing within Office 365. To use the tool, simply open it with PowerShell (with the Skype for Business Online Module installed) and you will be presented with the following GUI and features:

Tool Features
  • Log into O365 using the Connect SfBO button in the top left of the tool. Note: the Skype for Business Online PowerShell module needs to be installed on the PC that you are connecting from. You can get the module from here:
  • Create/Edit and Remove Tenant Dial Plan policies using the New.., Edit.. and Remove buttons.
  • Copy existing Tenant Dial Plans and all their Normalisation rules to a new Tenant Dial Plan.
  • Add/Edit Tenant Dial Plan normalisation rules. If the rule you are setting has a name that matches an existing rule, then the existing rule will be edited. If the rule’s name does not match an existing rule then it will be added as a new rule to the list.
  • Delete one or all normalisation rules from a Tenant Dial Plan policy.
  • Easily change the priority of normalisation rules with the UP and DOWN buttons.
  • Test the normalisation rules! Teams currently (at the time of writing this) doesn’t have any normalisation rule testing capabilities. So I wrote a custom testing engine into the tool providing this feature. By entering a number into the Test textbox and pressing the Test Number button, the tool will highlight all of the rules in the Dial Plan that match in blue. The rule that has the highest priority and matches the tested number will be highlighted in green. The pattern and translation of the highest priority match (the one highlighted in green) will be used to do the translation on the Test Number and the resultant translated number will be displayed in the Test Result.

  • Initial Release 1.00

Note: the Skype for Business Online PowerShell module needs to be installed on the PC that you are connecting from. You can get the module from here:

Download from TechNet Gallery:

Frequently Asked Questions

1. What is the deal with the OptimizeDeviceDialing setting - I can't edit it? 

In order to use the Access Prefix value that you can enter when creating a policy in the tool, a setting in the background called OptimizeDeviceDialing must also be turned on (for more details about what an Access Prefix is, refer to Ken Lasko's post about how they work in Lync). In addition to this, there is some weirdness in the PowerShell commands, which means that after you have set an Access Prefix for a policy you cannot then delete this value. You can only overwrite an existing Access Prefix with another number. When you delete the Access Prefix in the Edit dialog of the tool it will set the OptimizeDeviceDialing setting to FALSE (and leave the existing Access Prefix because it can't delete it). For example, if you already have an Access Prefix configured (as say "0") on a policy and then open the Edit dialog and remove the Access Prefix value like shown in the image below:

... then the result will show as the Access Prefix still being "0" in the main window (due to it not being able to be deleted by PowerShell) but it will update the OptimizedDeviceDialing setting to FALSE so the Access Policy is not used:

The Wrap Up

Well that was one hell of a ride. I think the Ayahuasca has nearly worn off and it's time for me to lie down. Enjoy the tool and remember, kids, don’t drink weird potions in the jungle…

Read more →

Sunday, 18 August 2019

Skype for Business 2019 Call Forward Tool

In the July 2019 update of Skype for Business Server 2019 (a release that might also be called CU1 or CU2 depending on if you include a Hotfix release that came about a month earlier) now includes some new PowerShell commands that allow you to centrally control users' call forwarding settings. This functionality used to be available via a tool called SEFAUTIL.exe in the Skype for Business resource kits in previous versions of the server releases. This is obviously great news because this is the functionality that was used all the time in practice by most organisations that I have seen.

The first question is what do we actually get with these new commands? We basically get the ability to do all the things a user can do from the Call Forward settings dialog within the Skype for Business client. This includes adding users to their Team Call Group and Delegate lists as well as setting call forward immediate, unanswered and simultaneous ring.

For more details on using the commands directly, Greig Sheridan has done a nice write up here:

Whilst it’s great to have these commands at our disposal, I still find that there is a learning curve to figuring out which settings and flags to use to achieve the call forward type that you might want in practice. So I thought it would be good to build a GUI for the PowerShell commands that looked exactly the same as the call forward settings screen from the Skype for Business client that we have all been using for many years and understand already. So that’s what I did… Introducing the Skype for Business 2019 Call Forwarding Tool:

Skype for Business 2019 Call Forwarding Tool

Tool Features:
  • No learning curve - it works the same as the call forward configuration on the Skype for Business client!
  • Get the call forwarding settings for any user on the system.
  • Edit team-call groups members.
  • Edit delegate members
  • Forward calls immediately to another number, delegates or contact.
  • Set simultaneous ring to team-call members, delegates, number or contact.
  • Control when the settings will apply ("all of the time" or "during work hours in Outlook")
  • Set the call forward settings on one or a number of users by selecting them from the user list on the right hand side of the tool.


1.00 Initial Release

Download from TechNet Gallery:


The PowerShell commands that have been supplied by Microsoft have the following limitations when compared to what can be set in the Skype for Business Client:

  • In Delegate and Team-call settings the "ring after" timer can only be set to 0, 5, 10 or 15 seconds, whereas in the Client you can set it from zero to 55 seconds (the maximum value is actually is whatever the unanswered call timer is, minus 5 seconds, which is a maximum of 55 seconds). 
  • There is no ability to select which delegates will be able to receive calls. This is represented in the client as a checkbox next to the delegate in the "Call Forwarding - Delegates" dialog. This capability is not available in the PowerShell commands at the moment.

Known Issues

Known Issue 1: Call Forward Unanswered to a Phone Number Issue

There is a bug in Skype for Business Server 2019 July 2019 update when Call Forward Immediate is disabled but Call Forward Unanswered is set to point to a number. This scenario looks like this in the Client:

From PowerShell it looks like this:

Set-CsUserCallForwardingSettings -Identity "" -DisableForwarding -UnansweredToOther "+61395554444" -UnansweredWaitTime 10

Whilst this command will be accepted by the system and look like the data has set correctly within the client the actual Call Forward will not work when you call the Client (ie. instead of the call going to the number it forwards to the user's Voicemail). This is due to a bug in the Set-CsUserCallForwardingSettings command which will hopefully be fixed in the next CU.

Known Issue 2: Call Forward Immediate to Voice Mail Issue

In Skype for Business Server 2019 July 2019 the PowerShell commands do not tell you if the user has Call Forward Immediate to Voice Mail configured. If you run the Get command it will show:

User                             :
CallForwardingEnabled            : False
ForwardDestination               :
ForwardImmediateEnabled          : False
SimultaneousRingEnabled          : False
SimultaneousRingDestination      :
ForwardToDelegates               : False
SimultaneousRingDelegates        : False
TeamRingEnabled                  : False
Team                             : {}
Delegates                        : {}
DelegateRingWaitTime             : 0
TeamDelegateRingWaitTime         : 0
SettingsActiveWorkhours          : False
UnansweredToVoicemail            : True
UnansweredCallForwardDestination :
UnansweredWaitTime               : 30

... which looks exactly the same as if there is no Call Forward set at all.

The commands also do not have a flag to allow you to set Call Forward Immediate to "Voice Mail". As a work-around for this, I have implemented the setting of Call Forward Immediate using a special SIP Address format. The SIP Address of a user's Voice Mail can be represented as their SIP Address with the following parameters after it ";opaque=app:voicemail". So, in order to forward to Voice Mail, the tool currently uses this method which the Client also respects and displays correctly as a Forward to Voice Mail. When this issue is fixed I will update the tool accordingly.

The Wrap Up

Forward away my friends! Forward away!

Read more →

Popular Posts