How to Create Microsoft 365 Groups using Powershell

About the Task

I received a request to create Microsoft 365 groups in bulk using PowerShell. While attempting to use the New-UnifiedGroup command (part of the EXO V2 PowerShell Module), I successfully created the Microsoft 365 group.

However, I encountered an issue as this command did not generate the corresponding SharePoint site. Consequently, I used the ‘New-PnPMicrosoft365Group‘ command, which is a part of the PnP.Powershell PowerShell module.

In this blog post, I provide a detailed explanation of how to use the ‘New-PnPMicrosoft365Group‘ command to create one or more Microsoft 365 groups which also created a Sharepoint site as well.

Please note that New-PnPMicrosoft365Group cmdlet does not work when you use Connect-PnPOnline with -useWeblogin parameter. Therefore, we have to first make a connection with Sharepoint in a non-interactive way.

To observe the effects of using the -useWebLogin switch with the Connect-PnPOnline command, open PowerShell as an Administrator, type the following command, and press Enter.

Make sure the PnP.Powershell module is installed on the system; otherwise, the command below will not work. To Install Pnp.Powershell module use: Install-Module -Name PnP.PowerShell -Force -AllowClobber command.

Connect-PnPOnline -Url https://<yoursitename>.sharepoint.com -UseWebLogin

A small window will pop-up on the screen, Enter your administrator credentials to authenticate to Sharepoint.

Connect-PnPOnline -Url https://<yoursitename>.sharepoint.com -UseWebLogin

After authenticating using the -UseWebLogin parameter, attempt to create a new Microsoft 365 group using the New-PnPMicrosoft365Group cmdlet. It will fail with below error message:

This cmdlet does not work with WebLogin/Cookie based connection towards Sharepoint

cmdlet does not work with a WebLogin/Cookie based connectio

Therefore, We will use a non-interactive way which can be achieved by using Entra ID App registration. Let’s check the steps:

Step 1 – Create an Entra ID App Registration

To Create an App registration on the Entra admin center. Follow the below steps:

  • Login on Entra admin center.
  • Expand Applications > App registrations.
  • Click on New registrations
Azure AD App Registration New Registration
  • Provide the Name of the Application and select “Accounts in this organizational directory only“. Click Register.
Register an Application
  • Once the application is registered, click on the ‘Overview‘ link, and then copy the Client ID. The Client ID will be used when connecting to SharePoint via the Connect-PnPOnline command.
PnP Powershell Application
  • The next step is to grant minimum permissions to this app for our task. To do this, click on ‘API Permissions‘ and then select ‘Add a Permission“.
PnP Powershell Application API Permissions
  • Click on Microsoft Graph.
PnP Powershell Application API Permissions
  • Click on Application Permissions.
PnP Powershell Application API Permissions
  • Search for Group and Provide Group.ReadWrite.All Permission.
PnP Powershell Application API Permissions
  • Search for ‘directory‘ and provide ‘Directory.ReadWrite.All‘ permission.
PnP Powershell Application API Permissions
  • Grant Admin Consent
PnP Powershell Application API Permissions Grant Consent
  • Admin Consent Granted
PnP Powershell Application API Permissions Grant Consent

Step 2 – Create a Self-signed Certificate

The next step is to create a self-signed certificate and upload it to the PnP PowerShell app we registered in Entra ID. Let’s see how we can generate and upload the certificate.

  • Use the following command to generate a self-signed certificate. Please note that the date format is YYYY-MM-dd. Adjust the start date and end date according to your requirements.
.\Create-SelfSignedCertificate.ps1 -CommonName "TechPress" -StartDate 2021-08-13 -EndDate 2022-08-13
.\Create-SelfSignedCertificate.ps1 -CommonName "TechPress" -StartDate 2021-08-13 -EndDate 2022-08-13
  • Self-signed Certificate has been generated
.\Create-SelfSignedCertificate.ps1 -CommonName "TechPress" -StartDate 2021-08-13 -EndDate 2022-08-13

Step 3 – Upload the Self Signed Certificate

  • Click on the ‘Certificates & Secrets‘.
  • Click on Upload certificate
 PnP Powershell Upload Certificate

Select .cer file to upload.

Upload Certificate

Certificate .cer file / Public Key is uploaded.

 PnP Powershell Upload Certificate

Create Microsoft365 Groups

For Creating Microsoft 365 Group(s), We need to gather a few values that will be used to connect to SharePoint using the Connect-PnPonline command. Below are the values required for this command.

Client ID = Copy the Client ID of the App PnP Powershell from Azure Portal.
Certificate Path = Path of Certificate PFX File
CertificatePassword
= PFX File Password
Url =
Sharepoint site URL where you want to connect —- for example: https://jmittechpress.onmicrosoft.com
Tenant
= Azure Active Directory Tenant Name —— for example techpress.onmicrosoft.com

Step 1 – Install PnP.Powershell

To install the PnP.Powershell module on your system, open the PowerShell console as an Administrator and type the following command:

Install-Module -Name PnP.PowerShell -Force -AllowClobber
Install-Module -Name PnP.PowerShell

First, connect to Sharepoint using Connect-PnPOnline command using the command shown below:

Connect-PnPOnline -ClientId <ClientID> -CertificatePath C:\SelfSignedCertificate\TechPress.pfx -CertificatePassword (ConvertTo-SecureString -AsPlainText "Welcome123" -Force) -Url https://<SharepointSite URL> -Tenant <Tenant Name>

Create one Microsoft 365 Group using New-PnPMicrosoft365Group without Team

$displayname = "London Finance"
$nickname = "LondonFinance"
$arrayOfOwners = "[email protected]", "[email protected]"
$arrayOfMembers = "[email protected]"
New-PnPMicrosoft365Group -Displayname $displayName -Description "TechPress Finance Group" -MailNickname $nickname -Owners $arrayOfOwners -Members $arrayOfMembers -IsPrivate
Create Microsoft 365 Group using New-PnPMicrosoft365Group without Team
Create Microsoft 365 Group using New-PnPMicrosoft365Group without Team
  • Owners and Members of the group as we defined in our command.
Create Microsoft 365 Group using New-PnPMicrosoft365Group without Team

Create one Microsoft 365 Group using New-PnPMicrosoft365Group with Team

Create Microsoft 365 Group with Sharepoint site and with connected Team. I am using the same example as above, the only difference is a switch added to the end of New-PnPMicrosoft365Group Command -CreateTeam.

$displayname = "London Finance"
$nickname = "LondonFinance"
$arrayOfOwners = "[email protected]", "[email protected]"
$arrayOfMembers = "[email protected]"
New-PnPMicrosoft365Group -Displayname $displayName -Description "TechPress Finance Group" -MailNickname $nickname -Owners $arrayOfOwners -Members $arrayOfMembers -IsPrivate -CreateTeam

Also Read: Exchange Online / Exchange 2010 useful PowerShell Commands

Create Microsoft 365 Groups in bulk

For creating Microsoft365 groups in bulk, I have created a small script which you can use. You can copy the script from this blog post or download it from TechPress GitHub Page as well. Please find the link of Github page in the next section. Before you can use the script, there are some important points to note as given below:

Script requirements and Important Points
– Make sure to use -verbose switch when running the function (It’s also explained and show in later section with screenshots). If its not run with -verbose switch, script will still run but will not have full information about the progress displayed on the console.

– An CSV File is required as a source data for this script. A Sample CSV File is shown in the later section. Create a CSV File using the same headings and update the data. When this script / function is run, it will prompt for CSV File path, provide the path of the CSV File.

– The Script checks for Powershell module PnP.Powershell and Installs / Imports it for you. There is a confirmation message before it gets installed.

– Script creates Log files everytime its run and its stored at C:\Apps\Logs. You can change the value of the variables $Logfile and $Logfolder as per your requirement.

– After dot sourcing the script, you can check more information about the script using >get-help Create-M365GroupwithSPOSite

Only few variables required to be updated in the script before you can run the script.

Example:

$arrayOfOwners = “[email protected]”, “[email protected]
$arrayOfMembers = “[email protected]

$ClientID = “<clientID>”
$CertPath = “<Path of the Certificate File>”
$SiteUrl = “<Sharepoint Site URL>”
$tenant = “<Azure AD tenant name>”
Sample M365Groups.csv File
If Teams Column is set to Y –> Microsoft 365 group + SPO Site + Team will be created
If Teams Column is set to N –> Microsoft 365 group + SPO Site will be created without Teams

Once you have a sample csv file created and variables populated in the powershell script. Lets run it to see how it goes. This is how my folder looks like:

Script Folder contains Powershell script and CSV File
Copy these two files in any folder and on powershell console dot source it like >. .\<script>.ps1
GitHub Script Download link
https://github.com/Techpress-net/Powershell-Scripts.git

– After dot sourcing the script, you can check more information about the script using get-help Create-M365GroupwithSPOSite

get-help Create-M365GroupwithSPOSite
Create Microsoft 365 Groups in bulk
Create Microsoft 365 Groups in bulk
After the groups are created, it will not be shown on the PS Console. The script is updated as per comment: https://techpress.net/how-to-create-microsoft-365-groups-in-bulk-with-sharepoint-site-and-teams-using-powershell/#comment-79
C:\Apps\Logs\M365GroupLog-08-13-2021_06-54-59.csv File
TipUse Excel -> Data -> Text to Colums and use the Delimeter as * to separate data it in two columns
Disclaimer
I have created below script and used it in the test enviornment as well as Production Envionments. Its recommeded to use this script to create couple of groups first or to use it in test enviornment first to see if you are successful before creating 100’s of groups using this script in Production.

This script/function is provided AS IS without warranty of any kind. Author(s) disclaim all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall author(s) be held liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the script or documentation. Neither this script/function, nor any part of it other than those parts that are explicitly copied from others, may be republished without author(s) express written permission. Author(s) retain the right to alter this disclaimer at any time.
Function Create-M365GroupwithSPOSite { 
<# 
.SYNOPSIS 
Create Microsoft 365 Groups in bulk along with Sharepoint Sites.If Teams Column value is Y
Teams Site will also be linked to the group else Teams Site will not be linked/created. 
 
.DESCRIPTION 
This is Create-M365GroupwithSPOSite Function which can be used to Create Microsoft 365 Groups
with Sharepoint Sites (with or without Teams Site). 
 
.NOTES     
        Name       : Create-M365GroupwithSPOSite  
        Author     : Jatin Makhija  
        Version    : 1.0.1  
        DateCreated: 13-08-2021 
        DateUpdated: 24-08-2021
        Blog       : https://techpress.net
         
.LINK 
https://techpress.net
 
.EXAMPLE 
PS> Create-M365GroupwithSPOSite -verbose
 
For Example 
 
Create-M365GroupwithSPOSite -verbose 
#> [cmdletBinding()] 
    param( 
    [parameter(mandatory = $true, Position =0, HelpMessage="Please Enter the Path to CSV File")] 
    [string]${CSVFilePath} 
         ) 
 
Try { 
 
        #Check for PNP Powershell module 
        $Module=Get-Module -Name pnp.powershell -ListAvailable  
        if($Module.count -eq 0) 
        { 
        Write-Host PNP Powershell module is not available  -ForegroundColor yellow  
        $Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No 
        if($Confirm -match "[yY]") 
        { 
        Write-Host "Installing PnP.Powershell Module"
        Install-Module -Name PnP.PowerShell -Confirm:$False -Force
        Write-Host "Importing PnP.Powershell Module"
        Import-Module -Name PnP.PowerShell -Verbose:$false
        } 
        else 
        { 
        Write-Host PNP Powershell module is required for this script to work. 
        Exit
        }
        }         
 
    } 
 
Catch { 
Write-Warning "PNP Powershell module is required for this script to work." 
Write-Warning $_ 
break 
} 
$arrayOfOwners = "[email protected]", "[email protected]"
$arrayOfMembers = "[email protected]"
$ClientID =  "<clientID>"
$CertPath =  "<PFX Certificate File Location>"
$CertPass =   Read-Host -Prompt 'Enter Password of the PFX File' -AsSecureString
$SiteUrl  =  "<Sharepoint Site URL>"
$tenant   =  "<Azure AD Tenant Name>"
$Params = @{
    ClientId            = $ClientID
    CertificatePath     = $CertPath
    CertificatePassword = $CertPass
    Url                 = $SiteUrl
    Tenant              = $tenant
}
Write-host "Connecting to PNPOnline" -ForegroundColor Blue -BackgroundColor White
Connect-PnPOnline @Params
$LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
$Logfile = "C:\Apps\Logs\M365GroupLog-$LogTime.csv"
$logfolder ="C:\Apps\Logs"
if(!(Test-Path -path $LogFolder)){
New-Item -ItemType Directory -path $logfolder
}
Else 
{
Write-Host "Great! log folder already exists, Please check C:\Apps\Log\ Folder for Log Files generated by this script"
}
Function LogWrite
{
    Param ([string]$logstring)
     Add-content $Logfile -value $logstring
}
Import-Csv ${CSVFilePath} -Header displayname, nickname, description, Teams | Select-Object -Skip 1 | ForEach-Object{ 
                                                    $displayname = $_.displayname 
                                                    $nickname = $_.nickname
                                                    $description = $_.description
                                                    $Teams = $_.Teams
if (Get-PnPMicrosoft365Group -identity $displayname) {
       Write-verbose "M365 Group $displayname already exists" 
       LogWrite "$displayname * Already Exists"
}
Elseif ($Teams -eq 'N') {
         Write-verbose "Teams Column Value set to $Teams for $displayname" 
         Write-verbose "Creating M365 Group + SPO Site without connected Teams for $displayname"
         try { 
         New-PnPMicrosoft365Group -DisplayName $displayname -Description $description -MailNickname $nickname -Owners $arrayOfOwners -Members $arrayOfMembers -IsPrivate | out-null
         } catch {
         LogWrite "$displayname *  could not be created"
         }
         LogWrite "$displayname *  created without Teams Site"
}
else {
    Write-verbose "Teams Column Value set to $Teams for $displayname"
    Write-verbose "Creating M365 Group + SPO Site with connected Teams for $displayname" 
    try{
    New-PnPMicrosoft365Group -DisplayName $displayname -Description $description -MailNickname $nickname -Owners $arrayOfOwners -Members $arrayOfMembers -IsPrivate -CreateTeam | out-null 
    } catch {
    LogWrite "$displayname *  could not be created"
    }
    LogWrite "$displayname * created with Teams Site"
     }
  }
}  

6 thoughts on “How to Create Microsoft 365 Groups using Powershell”

  1. Love this guide! Having an issue at the very end however. It seems like the script will create one group from the csv file and then hang. After a bit i get the below error. The group does actually get created in O365 but no group after that one will be created. If i run the script again it does see the first group was created and moves on to the next, then i get the same issue where it hangs and the below message appears

    New-PnPMicrosoft365Group : Access denied
    At C:\Scripts\M365Group.ps1:115 char:10
    +         New-PnPMicrosoft365Group -DisplayName $displayname -Descript …
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       + CategoryInfo         : InvalidOperation: (:) [New-PnPMicrosoft365Group], PSInvalidOperationException
       + FullyQualifiedErrorId : InvalidOperation,PnP.PowerShell.Commands.Microsoft365Groups.NewPnPMicrosoft365Group

    Reply
    • Hi Jestoner, Thanks for the feedback. Make sure Directory.ReadWriteAll and Groups.ReadWriteAll Permissions are granted to the App in Azure AD. As it says Access Denied, I suspect this could be due to permissions issue. I understand you manage to create one group which is a bit strange. I had tested and used this scripts on different tenants but didn’t face any issues. I will test it again to replicate the issue, update the changes and release the updated version of the script.

      Update: Just tested this script again by using the csv file and adding a test group and it seems to be working fine.

      VERBOSE: M365 Group PMO Office already exists
      VERBOSE: M365 Group Accounting already exists
      VERBOSE: M365 Group Financial Services already exists
      VERBOSE: M365 Group InformationTech already exists
      VERBOSE: M365 Group ClientProjects already exists
      VERBOSE: M365 Group Team xyz already exists
      VERBOSE: M365 Group InternalMeeting already exists
      VERBOSE: Teams Column Value set to N for Jatin
      VERBOSE: Creating M365 Group + SPO Site without connected Teams for Jatin
      
      DisplayName               Id                                                     HasTeam                   SiteUrl        
      ----------- --                  -------                                                  -------        
      Jatin                    15e94953-da1d-8-fabe9cddd9d81af              False                           https://jmit...
      
      Reply
      • Thanks for the quick reply. I checked the permissions and they are both granted for Directory.ReadWriteAll and Groups.ReadWriteAll and to make things even more odd, i thought the script was failing after creating the first group however that is not actually the case. It just hangs for about 5 minutes before moving on to the next group while spitting out that error each time. So this works exactly as intended, just slowly and with “errors”. I’ve attached a screenshot of my powershell screen. While it might be annoying that it doesn’t do this quickly, I am happy that i can at least queue it up and let it do it’s thing.

        Reply
        • Hey Jestoner, No Problem.Thanks for the screenshot. I have seen this error while working on the script. The script creates groups as intended and then displays the created groups on the console as you would be able to see it in the screenshot i shared in the blog post. Only the part where it displays the groups on the console is failing. This error is caused by Azure AD app registration API permissions.Make sure Powershell is run as admin, Grant Consent is approved for both Directory.ReadWriteAll and Group.ReadWriteAll in azure app.

          Permissions Required by New-PnPMicrosoft365Group
          One of Directory.ReadWrite.All, Group.Create, Group.ReadWrite.All

          I can try to hide this in the next version of the script so that it does not display the groups on the console as log file will have the information about the groups creation status. However, with required permissions provided, this error should not appear.

          UPDATE: Script has been updated now (To version 1.0.1) to not produce the console output for created group and also a bit of error handling has been added. This should fix the error message you are getting on Powershell console. You can download the updated copy from GitHub link: https://github.com/Techpress-net/Powershell-Scripts/tree/master/CreateM365GroupswithSPOSite
          or copy it from this blog post as well.

          Reply
          • Thank you so much! It was the group.create that i didn’t have permissions granted for.

            On a side note, is it possible to disable the automated email that gets sent out to the members when the group is created?

          • You’r Welcome Jestoner. I thought so that it could be a permission issue. I am glad that you finally found the root cause of the error. However as the script has been updated, there is not need to provide Groups.ReadWriteAll.

            Disable Welcome Message to users in Microsoft 365 Groups:

            Connect to EXO PS Module and run below command to disable the Welcome message. Let me know if it works fine.

            Set-UnifiedGroup <groupname> -UnifiedGroupWelcomeMessageEnabled:$false
            

Leave a Comment

Discover more from TechPress

Subscribe now to keep reading and get access to the full archive.

Continue reading