Hide Modern Team Sites From the Global Address List During Provisioning

Microsoft announced an addition to the Graph API beta endpoint for Groups that allows administrators and developers to hide Microsoft 365 Groups from the Exchange Online Address Book at any time, including provisioning of Groups via SharePoint Online Team site creation. This extends to any service that creates a Team site, such as provisioning a Microsoft Team.

This script is designed for Azure Automation, which I would encourage all IT Pros to look at when Site Designs and Power Automate don’t cover a particular provisioning scenario. You can attach a Site Design to a site template, including the default Team site template, to call a Power Automate flow which in turn calls Azure Automation to apply any settings you wish.

This does require a registered App in Azure AD with the Group.ReadWrite.All API permission. The script has a couple of variables that need to be created in the Azure Automation account Variables section. The script input requires the Power Automate flow to send the Group ID as a variable.

I will have a step-by-step guide for this coming in the near future that covers this script.

Here’s the script you would use, in Azure Automation, to hide the Microsoft 365 Groups from the Global Address List in Exchange Online.

Param
(
  [Parameter (Mandatory=$true)]
  [String] $groupId
)

$connectionName = "AzureRunAsConnection"

#Get the connection "AzureRunAsConnection"
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName

try
{
    "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
}
catch {
    if (!$servicePrincipalConnection)
    {
        $ErrorMessage = "Connection $connectionName not found."
        throw $ErrorMessage
    } else{
        Write-Error -Message $_.Exception
        throw $_.Exception
    }
}

try {
    ### Microsoft 365 Group Hide from GAL
    $ClientSecret = Get-AutomationVariable -Name 'ClientSecret' #from Azure AD registered App
    $loginURL = "https://login.microsoftonline.com"
    $tenantName = Get-AutomationVariable -Name 'TenantName' #contoso.onmicrosoft.com
    $scope = "https://graph.microsoft.com/.default"

    $body = @{grant_type="client_credentials";scope=$scope;client_id=$servicePrincipalConnection.ApplicationId;client_secret=$ClientSecret}
    $oauth = Invoke-RestMethod -Method Post -Uri $("$loginURL/$tenantName/oauth2/v2.0/token") -Body $body
    $token = $oauth.access_token

    # Note we're using a _beta_ endpoint! Update to 1.0 when this API is updated.
    $Uri = "https://graph.microsoft.com/beta/groups/$($groupId)?`$select=hideFromOutlookClients"
    $Header = @{"Authorization" = "Bearer $token"}
    $Body = @{hideFromOutlookClients = 'true'}
    $ApiBody = ConvertTo-Json -InputObject $Body

    Invoke-RestMethod -Uri $Uri -Method PATCH -Headers $Header -Body $ApiBody -ContentType "application/json"
}
catch {
    Write-Output "Error occurred: $PSItem"
}

I’ve waited for years for this property, so I’m glad Microsoft has finally released this capability. It will make your Exchange Online administrators very happy!

Fix Import-SPWeb Errors on Modern Lists and Libraries

One of the features of the Modern List and Library view in SharePoint Server 2019 is the custom column width – these column width changes can be saved to the default All Items view or a new view for the List/Library. If a user makes the change and saves the view, if an administrator exports the Web or List/Library using Export-SPWeb, when performing an Import-SPWeb an error will be generated, similar to the below.

Import-SPWeb : The element 'WebPart' in namespace 'urn:deployment-manifest-schema' has invalid child element
'ColumnWidth' in namespace 'urn:deployment-manifest-schema'. List of possible elements expected: 'Script, PagedRowset,
PagedClientCallbackRowset, PagedRecurrenceRowset, ViewFields, ViewData, Query, RowLimit, RowLimitExceeded, Toolbar,
Formats, Aggregations, List, MetaData, View, ViewStyle, ViewBody, ViewEmpty, ViewFooter, ViewHeader, ViewBidiHeader,
GroupByFooter, GroupByHeader, CalendarViewStyles, CalendarSettings, ListFormBody, Xsl, XslLink, JS, JSLink,
ParameterBindings, OpenApplicationExtension, Mobile, MobileItemLimit, Method, WebParts, InlineEdit, Joins,
ProjectedFields, SpotlightInfo, Visualization' in namespace 'urn:deployment-manifest-schema'.
At line:1 char:1
+ Import-SPWeb https://devsp02.cobaltatom.com/sites/teams2 -Path C:\exp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Share...CmdletImportWeb:SPCmdletImportWeb) [Import-SPWeb], XmlSc
   hemaValidationException
    + FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletImportWeb

Based on this error, it is clear that the XML schema defined by SharePoint Server does not match the XML schema in the binary file containing the List in our saved export. Obviously, this is a bug, but one that is easy to work around until the SharePoint Product Group can implement a fix.

As always, what we’re going to do is unsupported because we are modifying a file in the 16 hive. Make a copy of this file prior to making the modification. We are going to edit the file %CommonProgramFiles%\microsoft shared\Web Server Extensions\16\TEMPLATE\XML\DeploymentManifest.xsd. Open this file in Notepad or your favorite XML/text editor.

Find the line that reads <!-- SPView definition -->. Within that section is a line <xs:element name="CustomFormatter" minOccurs="0" maxOccurs="1" />. We are going to add the new line immediately below the CustomFormatter line item.

<xs:element name="ColumnWidth" minOccurs="0" maxOccurs="1" />

The section of the file will look like the below.

        <xs:element name="Visualization" minOccurs="0" maxOccurs="unbounded" />
        <xs:element name="CustomFormatter" minOccurs="0" maxOccurs="1" />
        <xs:element name="ColumnWidth" minOccurs="0" maxOccurs="1" />
      </xs:choice>
    </xs:sequence>

Notice how we are adding the line containing ColumnWidth. This will tell SharePoint to accept that element as part of the valid XML schema to import the List/Library view. With your modified file, overwrite %CommonProgramFiles%\microsoft shared\Web Server Extensions\16\TEMPLATE\XML\DeploymentManifest.xsd. Re-try your import, it should not require restarting any processes or even PowerShell.

If you still encounter the error after making this change, please let me know on Twitter.

SharePoint 2019 June 2020 Updates

The SharePoint 2019 June 2020 Updates have been released.

Product KB Article
SharePoint Server 2019 (sts-x-none) https://support.microsoft.com/help/4484400
SharePoint Server 2019 (wssmui) https://support.microsoft.com/help/4484404
Office Online Server https://support.microsoft.com/help/4484330
Office Updates https://support.microsoft.com/help/4559448

For all SharePoint updates, visit SharePoint Updates.

SharePoint 2016 June 2020 Updates

The SharePoint 2016 June 2020 Updates have been released.

Product KB Article
SharePoint Server 2016 (sts-x-none) https://support.microsoft.com/help/4484402
SharePoint Server 2016 (wssmui) https://support.microsoft.com/help/4484344
Office Online Server https://support.microsoft.com/help/4484330/
Office Updates https://support.microsoft.com/help/4559448/

For all SharePoint updates, visit SharePoint Updates.

Disable Engyte Cloud Storage Prior to Feature Rollout for Microsoft Teams

Microsoft is continuing to add 3rd party storage providers to Microsoft Teams, with the next one being Egnyte which will rollout to all customers in mid-June as part of 63706. Microsoft is enabling this storage provider by default. If your organization implements data policies which allow for only certain storage providers to be leveraged in your environment, this is problematic – since features rollout gradually, there is no specific date in which an administrator can turn this off from the Teams Admin Center.

There is a workaround, however. You can disable it via PowerShell today using the SkypeOnlineConnector module. Download and install the SfB Online module, then run the following PowerShell cmdlets.

Accounts without MFA enabled:

Import-Module SkypeOnlineConnector
$cred = Get-Credential
$sess = New-CsOnlineSession -Credential $cred
Import-PSSession $sess
Set-CsTeamsClientConfiguration -AllowEgnyte $false

Accounts with MFA enabled:

Import-Module SkypeOnlineConnector
$sess = New-CsOnlineSession -UserName admin@contoso.com
Import-PSSession $sess
Set-CsTeamsClientConfiguration -AllowEgnyte $false

Once set, Engyte will be disabled by default when the feature rolls out to your tenant.