Over the past few months I have worked on multiple projects and training courses for Microsoft Teams. A common task is creating policies and applying them to either users or groups. Creating them, can be as simple is going into the Teams Admin Center, or you can use PowerShell. As I have worked in multiple Microsoft 365 Tenants, I am a big advocate of scripting when I know I need to repeat the same task many times.

The PowerShell commands are pretty well defined and the documentation is okay, although needs little updating and a few more examples. To read about the basic policy PowerShell commands you can navigate to the following:

The “Teams Calling Policy” option, used to be available within the documentation but seems to have disappeared. However the PowerShell command is still valid.

To help me in repeating the same process multiple times, my thought was to define the properties for all the commands within a JSON file. I would then read the JSON file for the property values making it easy to adjust to what is needed each time. However, after looking at this, I also thought how nice it would be to be able to simply add new parameters and values to the JSON if the PowerShell command got updated. This made the idea a little more complicated, as it meant the JSON needed to store the property name and values and dynamically generate what was needed. An example of the JSON I created is this:

   "Calling": {
        "Identity": "Calling Policy",
        "AllowPrivateCalling": "$false",
        "AllowCallForwardingToUser": "$false",
        "AllowCallForwardingToPhone": "$false",
        "AllowVoicemail": "AlwaysDisabled",
        "AllowCallGroups": "$false",
        "AllowDelegation": "$false",
        "PreventTollBypass": "$false",
        "BusyOnBusyEnabledType": "Disabled",
        "AllowWebPSTNCalling": "$false"
   "Events": {
        "Identity": "Events Policy",
        "AllowBroadcastScheduling": "$false",
        "AllowBroadcastTranscription": "$true",
        "BroadcastRecordingMode": "UserOverride",
        "BroadcastAttendeeVisibilityMode": "EveryoneInCompany"

The basic structure is the type of policy e.g. Events, followed by the property and value. This format allows new properties to be added within the policy type as needed, or removed if needed.

The PowerShell itself performs a few tasks. The first is to import the JSON file.

$Path = "C:\Deployment\Policies.json"
$json = Get-Content $Path | ConvertFrom-Json

The next task actually generates the code needed for executing.


$PolicyPrefix = "Demo"
[string]$command = $null

switch ($PolicyType) {
    "Meeting" {  
        $object = $json.Policies.Policy.Meeting
        $command += "New-CsTeamsMeetingPolicy"
        foreach($property in $object.psobject.properties)
            if($property.name -eq "Identity")
                $command += " -$($property.name) '$($PolicyPrefix) $($property.value)'"
                $command += " -$($property.name) $($property.value)"
    "Messaging" {  
        $object = $json.Policies.Policy.Messaging
        $command += "New-CsTeamsMessagingPolicy"
        foreach($property in $object.psobject.properties)
            if($property.name -eq "Identity")
                $command += " -$($property.name) '$($PolicyPrefix) $($property.value)'"
                $command += " -$($property.name) $($property.value)"
return $command

When executed this code will generate the actual command. For example, if you specify “Messaging” as the choice, it will generate the following:

New-CsTeamsMessagingPolicy -Identity 'Demo Messaging Policy' `
    -AllowUrlPreviews $true `
    -AllowOwnerDeleteMessage $false `
    -AllowUserEditMessage $true `
    -AllowUserDeleteMessage $false `
    -AllowUserChat $false `
    -AllowGiphy $false `
    -GiphyRatingType STRICT `
    -AllowMemes $false `
    -AllowStickers $true `
    -AllowUserTranslation $true `
    -AllowImmersiveReader $true `
    -AllowRemoveUser $false `
    -AllowPriorityMessages $false `
    -AllowSmartReply $false `
    -ReadReceiptsEnabledType Everyone `
    -AudioMessageEnabledType Disabled `
    -ChannelsInChatListEnabledType DisabledUserOverride

The generated command, can then be passed into an “Invoke-Expression” method, which will then generate the actual Teams Policies.

Invoke-Expression -Command $command

When it is all put together, it allows multiple types of policies to be created easily. It allows for parameters and values to be added or removed from the JSON, as well as auto generating the actual command to execute. I am still in testing of it, but so far it has worked well. I am a great advocate of PowerShell and Automation for tasks like this.

Once done, the plan is to add it to my github and then make it available, we shall see how it goes 🙂