Assegnare licenze di Workplace Analytics con PowerShellAssign Workplace Analytics licenses with PowerShell

Utilizzare la procedura seguente per assegnare licenze di Workplace Analytics con PowerShell in Azure Active Directory (Azure AD).Use the following steps to assign Workplace Analytics licenses with PowerShell in Azure Active Directory (Azure AD).

Prerequisiti di installazioneInstallation prerequisites

  1. Installare il modulo Azure AD PowerShell seguendo questi passaggi:Install the Azure AD PowerShell module by following these steps:

    1. Aprire un prompt di Windows PowerShell con privilegi elevati.Open an elevated Windows PowerShell command prompt.

    2. Immettere il comando seguente:Enter the following command:

      Install-Module *AzureAD*
      
  2. Eseguire il modulo Azure AD PowerShell:Run the Azure AD PowerShell module:

    1. Avviare PowerShell.Start PowerShell.

    2. Immettere il comando seguente:Enter the following command:

      Import-Module *AzureAD*
      

Assegnazione di licenzeAssigning licenses

Workplace Analytics può estrarre i dati solo dagli account degli utenti che dispongono di licenze di Workplace Analytics valide.Workplace Analytics can only extract data from the accounts of users who have valid Workplace Analytics licenses.

  1. Per assegnare una licenza di Workplace Analytics a un utente:To assign a Workplace Analytics license to a user:

    Con PowerShell aperto, avviare il modulo di importazione e accedere ad Azure AD eseguendo i comandi seguenti:With PowerShell open, start the Import Module, and sign in to Azure AD by running the following commands:

    Import-Module *AzureAD*
    
    Connect-AzureAD
    

    Per accedere, sono necessarie credenziali con privilegi di amministratore.To sign in, you need credentials with admin privileges.

    Accesso ad Azure Active Directory

  2. Copiare e incollare i dati delle variabili seguenti nella riga di comando di PowerShell e quindi eseguirli:Copy and paste the following variable data into the PowerShell command line, and then run it:

     $UserToLicense = Get-AzureADUser -SearchString '<usertolicense@domain.com>'
     $LicenseSku = Get-AzureADSubscribedSku | Where {$_.SkuPartNumber -eq 'WorkPlace_Analytics'}
     $License = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicense
     $License.SkuId = $LicenseSku.SkuId
     $AssignedLicenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses
    
  3. Per assegnare una licenza, copiare e incollare il codice seguente nella riga di comando di PowerShell ed eseguirlo:To assign a license, copy and paste the following code into the PowerShell command line, and then run it:

     $AssignedLicenses.AddLicenses = $License
     Set-AzureADUserLicense -ObjectId $UserToLicense.ObjectId -AssignedLicenses $AssignedLicenses
    
  4. Per verificare che la licenza sia assegnata, copiare e incollare il codice seguente nella riga di comando di PowerShell ed eseguirla:To verify that the license is assigned, copy and paste the following code into the PowerShell command line, and then run it:

     Get-AzureADUserLicenseDetail -ObjectId $UserToLicense.ObjectId | Select -Expand ServicePlans | Where {$_.ServicePlanName -eq "Workplace_Analytics"}
    

    Dopo l'esecuzione dell'ultimo comando, verrà visualizzata una voce nella riga di comando.After this last command runs, you'll see an entry on the command line. In caso contrario o se viene visualizzato un messaggio di errore, la licenza non è stata assegnata correttamente.If not, or if an error message shows, the license was not successfully assigned.

Visualizzare le licenze disponibili nel tenantView Available licenses on your tenant

Per visualizzare le licenze disponibili per il tenant e l'utilizzo corrente, eseguire le operazioni seguenti in PowerShell:To view available licenses for your tenant and current usage run the following in PowerShell:

Connect-MsolService

Dopo aver eseguito la connessione al tenant di Microsoft 365, eseguire le operazioni seguenti:Now that you're connected to the Microsoft 365 tenant, run the following next:

Get-MsolAccountSku

Aggiungere licenze di Workplace Analytics in blocco tramite PowerShell di Microsoft 365Add Workplace Analytics licenses in bulk through Microsoft 365 PowerShell

Se è necessario assegnare licenze di Workplace Analytics a un numero elevato di utenti, è possibile usare lo script di licenza in blocco per Microsoft 365 PowerShell fornito in questa sezione.If you need to assign Workplace Analytics licenses to a large number of users, you can use the bulk license script for Microsoft 365 PowerShell provided in this section.

Requisiti softwareSoftware Requirements

Lo script di licenza in blocco di Workplace Analytics usa il modulo Azure Active Directory PowerShell per apportare le modifiche necessarie alle licenze alle identità del tenant.The Workplace Analytics bulk license script uses the Azure Active Directory PowerShell module to make the necessary licensing changes to your tenant identities. Per verificare che il modulo Azure Active Directory PowerShell sia installato:To ensure that the Azure Active Directory PowerShell module is installed:

  1. Aprire Windows PowerShell come amministratore ed eseguire il comando seguente:Open Windows PowerShell as an administrator and run the following command:

    Set-ExecutionPolicy RemoteSigned
    
  2. Quando viene visualizzato un messaggio di conferma, accettare la modifica per consentire l'esecuzione degli script di PowerShell locali.When a confirmation message appears, accept the change in order to allow local PowerShell scripts to run.

  3. Dopo aver impostato correttamente il criterio di esecuzione nel computer, eseguire il cmdlet seguente:After the execution policy is set correctly on the machine, run the following cmdlet:

     Install-Module -Name MSOnline -Repository PSGallery
    

Note

Se l'esecuzione del cmdlet non riesce, è possibile che sia in esecuzione una versione precedente di Windows Management Framework (WMF).If the cmdlet fails to execute, you might be running an older version of Windows Management Framework (WMF). In tal caso, scaricare e installare l'assistente per l'accesso necessario e il modulo Azure Active Directory PowerShell tramite MSI.In that case, download and install the required sign-in assistant and the Azure Active Directory PowerShell module through MSI. Per istruzioni su come installare questi pacchetti necessari, vedere Connettersi a Microsoft 365 PowerShell.For instructions to install these required packages, see Connect to Microsoft 365 PowerShell.

Requisiti di inputInput Requirements

Lo script di licenza in blocco di Workplace Analytics usa un file di riferimento CSV come input.The Workplace Analytics bulk license script uses a .csv reference file as input. Lo script fa riferimento a ogni indirizzo elencato nel file CSV e tenta di assegnare la licenza di Workplace Analytics a tutti gli utenti.The script references each address listed in the .csv file and attempts to assign Workplace Analytics license to all users.

Ogni utente a cui è già assegnata una licenza mantiene tutte le licenze correnti.Each user who is already assigned a license retains all current licensing. I nuovi utenti riceveranno una licenza di Workplace Analytics.New users will receive a Workplace Analytics license. L'input .csv deve avere una singola colonna con l'intestazione "Email" che contiene tutti gli indirizzi di posta elettronica.The .csv input must have a single column with the header "Email" that contains all email addresses.

Per altri dettagli sulla formattazione del file CSV di input, vedi file di esportazione CSV di esempio.For more details on formatting the input .csv file, see example .csv export file.

Descrizione scriptScript description

Lo script Add-WpALicense.ps1 è progettato per assegnare licenze di Workplace Analytics alle identità di Microsoft 365 in base all'input dell'indirizzo di posta elettronica CSV.The Add-WpALicense.ps1 script is designed to assign Workplace Analytics licenses to Microsoft 365 identities based on .csv email address input. L'input dell'indirizzo di posta elettronica viene usato per identificare l'identità corretta di Microsoft 365 in base agli attributi UserPrincipalName e ProxyAddresses dell'oggetto MSOL (Microsoft Online) e quindi tenta di assegnare una licenza all'identità di Microsoft 365.The email address input is used to identify the correct Microsoft 365 identity based on the UserPrincipalName and ProxyAddresses attributes of the MSOL (Microsoft Online) object, and then tries to assign a license to the Microsoft 365 identity.

Esecuzione scriptScript Execution

  1. Crea una cartella C:\Scripts se non esiste già.Create a C:\Scripts folder if it does not already exist.

  2. Copiare lo script seguente e incollarlo in un editor di testo e quindi salvarlo comeC:\Scripts\Add-WpALicense.ps1.Copy the following script and paste it into a text editor, and then save the script as C:\Scripts\Add-WpALicense.ps1.

    <#
    .NOTES
     Title:    Add-WpALicense.ps1
     Date:     February 25th, 2020
     Version:  1.0.4
    .SYNOPSIS
     This script is designed to add Workplace Analytics licenses to a .csv list of email addresses that correlate to Microsoft 365 identities.
    .DESCRIPTION
     Add-WpALicense is designed to assign Workplace Analytics licenses to Microsoft 365 identities based on .csv e-mail address input. The e-mail address input will be used to identify the correct Office365 identity based on the UserPrincipalName and ProxyAddresses attributes of the MSOL object and try to assign a license to the identity.
    .PARAMETER CSV
     The .csv input file contains all of the email addresses that are given a license. Use Email as the header and when save the file with the UTF-8 encoded format.
    .PARAMETER LicenseSKU
     The WORKPLACE_ANALYTICS LicenseSKU will be applied to a user that's found. The script tries to automatically apply a license SKU. If a license SKU is provided, the script tries to match it with the domain. An example SKU is CONTOSO:WORKPLACE_ANALYTICS.
     .EXAMPLE
     .\Add-WpALicense.ps1 -CSV c:\users\user123\desktop\inputCSV -LicenseSku CONTOSO:WORKPLACE_ANALYTICS
    
     The script would ingest the .csv file from the specified location in this example and try to apply the MSOL license SKU of CONTOSO:WORKPLACE_ANALYTICS to all users that are found in the MSOL structure of the tenant.
        #>
        param
        (
        [parameter(Mandatory=$true,Position=0,HelpMessage="Please provide a CSV file that has the Email column header.")]
        [ValidateNotNullorEmpty()]
        [string]$CSV,
        [parameter(Mandatory=$true,Position=1,HelpMessage="Please provide the exact name of the Workplace Analytics MSOL Account SKU license for the applicable tenant.")]
        [ValidateNotNullorEmpty()]
        [string]$LicenseSKU
        )
        #Simple function to connect to Microsoft 365 MSOL PowerShell.
        Function Connect-O365PowerShell {
            try {
                Import-Module MSOnline -ErrorAction Stop
                Write-Output "Successfully imported the Azure Active Directory PowerShell module, proceeding..."
            }
            catch {
                Write-Error -Message "Windows Azure Active Directory PowerShell module could not be found, please install the module and run this script again!"
                break
            }
            if(Get-Module -Name MSOnline) {
                try {
                    Connect-MsolService -ErrorAction Stop
                    Write-Output "Successfully connected to Microsoft 365 MSOL, proceeding..."
                }
                catch {
                    Write-Error "Could not connect to Microsoft 365 MSOL due to the following exception.`r`n$($_.Exception.Message)"
                    break
                }
            }
        }
        #Simple function to get to MSOL SKU information.
        Function Get-WorkplaceAnalyticsSku {
            param ($searchString)
            $O365MsolSKUs = Get-MsolAccountSku
            try {
                $wpaSku = $O365MsolSKUs | Where-Object { $_.AccountSkuId -like $searchString }
                if ($wpaSku) {
                    Write-Host "Office365 tenant possesses the correct WorkplaceAnalytics license, proceeding..."
                    [int]$availableLicenses = $wpaSku.ActiveUnits - $wpaSku.ConsumedUnits
                    Write-Host "Using Sku: $($wpaSku.AccountSkuId), Total Licenses: $($wpaSku.ActiveUnits), Used Licenses: $($wpaSku.ConsumedUnits), Available Licenses: $($availableLicenses)"
                    return $wpaSku
                }
                else {
                    Write-Error "Script could not find matching WorkplaceAnalytics license using $searchString on Office365 tenant. Here are the available SKU's for this tenant:"
                    Write-warning ($O365MsolSKUs | out-string)
                    write-warning "Please Rerun script and specify a SKU above with parameter -LicenseSKU {sku} including the appropriate WORKPLACE_ANALYTICS SKU"  
                    exit 1
                }
            }
            catch {
                 Write-Error "Failed to determine the Office365 tenant licenses, script cannot proceed!`n$_."
                 exit 1
            }
        }
        #Start-Transcript to keep a simple log of all stream output of the successes and failures of the execution and to set StrictMode.
        Start-Transcript
        Set-StrictMode -version 2
        #Simple if block to test the CSV parameter input and confirm the path is valid and contains a file.
        if (!(Test-Path $CSV)) {
          Write-Error "CSV file could not be found, please ensure that the location is correct and you have the proper permissions to read the file then try again.`r`n$($_.Exception.Message)"
        break
        }
        Write-Output "CSV file was found, proceeding..."
        try {
           #If the CSV is valid, this tries to import the contents into a user's CSV array that's used for processing.
           [array]$users = @(Import-Csv $CSV -ErrorAction Stop)
            Write-Output "CSV file was imported to process successfully, proceeding..."
         }
         catch {
            Write-Error "Failed to import CSV for processing due to the following exception.`r`n$($_.Exception.Message)"
            break
         }
        #After CSV formatting is verified, check for Email values in the file.
        if(($users.count) -le 0) {
           Write-Error "The CSV provided did not contain any valid SMTP data. Please check the CSV file and try again."
           break
        }
        Write-Host "Found $($users.count) items in the CSV to process"
        #Check the CSV contains the proper Email header.
        if ($users | Get-Member Email) {
           Write-Host "CSV file is valid, proceeding..."
        }
        else {
           Write-Warning "CSV is missing Email header. Please check the CSV file specified and update the CSV to include the header: Email"
           break
         }
         #Calling Connect-O365PowerShell function to establish connection.
         try {
             Connect-O365PowerShell -ErrorAction Stop
         }
         catch {
            Write-Error "Failed to successfully connect to Azure Active Directory PowerShell due to the following exception.`r`n$($_.Exception.Message)"
            break
         }
         #Try to pull MSOL SKUs.
         if ([string]::isnullorempty($LicenseSku)) {
            $wpaSearch = "*:WORKPLACE_ANALYTICS"
         }
         else {
            $wpaSearch = "*$LicenseSku*"
         }
         $LicenseSku = Get-WorkplaceAnalyticsSku -searchString $wpaSearch
         $NumofSuccessfullyLicensed = 0
         $NumofErrorLicensed = 0
         $NumOfAlreadyLicensed = 0
         $NumOfUsersNotFound = 0
         [System.Collections.ArrayList]$UsersNotFound =@()
         [System.Collections.ArrayList]$UsersFailedtoLicense =@()
         #If the user's array contains the Email member who is created by importing a CSV and the object count of the user's array is greater than zero (0), the processing block is entered and a foreach loop is used to process the array contents.
         Foreach($user in $users) {
            #An attempt is made to find the user through the UserPrincipalName parameter. If an error occurs, the catch block will try to find the user through a ProxyAddresses attribute regex comparison. An absolute match after the colon of the address in the array is required to increase the accuracy of the find.
            $userIndex = $users.Indexof($user)
            Write-Progress -Activity "Assigning Workplace Analytics Licenses, currently on $($userIndex + 1) of $($users.Count) Currently searching for user $($user.Email)" -PercentComplete ($userIndex / $users.Count * 100) -Id 1
            try {
                $msolUser = Get-MsolUser -UserPrincipalName $user.Email -ErrorAction Stop
             }
             catch {
                Write-Warning "Failed to find user $($user.Email) through UPN lookup, attempting ProxyAddress attribute...`n$_"
                $msolUser = Get-MsolUser -All | Where-Object {$_.ProxyAddresses -match "\:$($user.Email)"}
             }
             if($msolUser) {
                 #If the msolUser variable is not null, the following block will be entered where an attempt is made to add the LicenseSKU parameter to the MSOL user.
                 if ($msolUser.Licenses.AccountSkuId -contains $LicenseSKU.AccountSkuId) {
                    Write-Warning "User $($msolUser.UserPrincipalName) was found but is already licensed for WorkplaceAnalytics, skipping licensing."
                    $NumOfAlreadyLicensed++
                 }
                 else {
                    Write-Output "User $($user.Email) found, attempting to license..."
                    try {
                       Set-MsolUserLicense -UserPrincipalName $msolUser.UserPrincipalName -AddLicenses $LicenseSKU.AccountSkuId -ErrorAction Stop | Out-Null
                       Write-Output "Successfully licensed user $($msolUser.UserPrincipalName) with $($LicenseSKU.AccountSkuId) license."
                       $NumofSuccessfullyLicensed++
                     }
                     catch {
                        Write-Error "Failed to license user $($msolUser.UserPrincipalName) due to the following exception.`r`n$($_.Exception.Message)"
                        $NumofErrorLicensed++
                        $UsersFailedtoLicense.Add($user.Email) | Out-Null
                     }
                 }
             }
             else {
                $NumOfUsersNotFound++
                $NumofErrorLicensed++
                $UsersNotFound.Add($user.Email) | Out-Null
                Write-Error "Could not find user $($user.Email), skipping!"
                continue
             }
         }
         if ($UsersFailedtoLicense.count -ne 0) {
             Write-Output "`nThe following $($UsersFailedtoLicense.count) failed to License:`n"
             Write-Output $UsersFailedtoLicense
         }
         if ($UsersNotFound.Count -ne 0) {
             Write-Output "`nThe following $($UsersNotFound.count) users were not found:`n"
             Write-Output $UsersNotFound
         }
         $finaloutput = "`nScript completed, Total number of users licensed:$NumofSuccessfullyLicensed"
         $finaloutput += "`nTotal number of users that were already licensed:$NumOfAlreadyLicensed"
         $finaloutput += "`nErrors encountered:$NumofErrorLicensed"
         $finaloutput += "`nTotal users not found:$NumOfUsersNotFound"
    
         Write-Output $finaloutput
       Stop-Transcript
    

    Dopo aver preparato l'ambiente PowerShell e creato il file di input, verificare che il file utente CSV si trova nella stessa directory dello script e quindi eseguire lo script.After the PowerShell environment is prepared and the input file constructed, confirm that the CSV user file is in the same directory as the script, and then you can execute the script.

  3. Avviare Windows PowerShell ed eseguire il comando seguente:Start Windows PowerShell and run the following command:

     C:\Scripts\Add-WpALicense.ps1 -CSV <CSVLocation>
    

    Note

    Deve <CSVLocation> contenere il percorso completo del file di input CSV, ad esempio C:\Scripts\InputFile.csv.That the <CSVLocation> should contain the full path to the CSV input file, such as C:\Scripts\InputFile.csv.

  4. Quando richiesto, immettere le credenziali di amministratore globale di Microsoft 365 per il tenant in cui devono essere aggiunte le licenze.When prompted, enter the Microsoft 365 global administrator credentials for the tenant where the licenses are to be added.

    Se tutti gli input necessari sono soddisfatti, lo script viene eseguito ora nell'elenco CSV e quindi le licenze vengono assegnate agli utenti.If all the required inputs are satisfied, the script executes now against the CSV list, and then licenses are assigned to users. Durante l'esecuzione dello script, tutti gli errori e gli errori vengono visualizzati nella riga di comando e una trascrizione viene salvata nella cartella Documenti.During the script execution, all successes and failures are shown on the command line and a transcript is saved in the Documents folder.

Domande frequentiFAQ

Si è verificato un problema durante l'esecuzione dello script. Esiste un registro delle azioni script?Something went wrong during the script execution. Is there a log of the script actions?

Sì, è possibile trovare una trascrizione di script per ogni esecuzione nella cartella Documenti della persona che ha eseguito lo script.Yes, you can find a script transcript for each execution in the Documents folder for the person who executed the script.

L'input di un indirizzo di posta elettronica funzionerà se non è UserPrincipalName di un'identità MSOL?Will an email address input work if it is not the UserPrincipalName of any MSOL identity?

La logica dello script tenta innanzitutto di trovare l'identità MSOL tramite UserPrincipalName utilizzando l'indirizzo di posta elettronica del file CSV.The script logic first attempts to find the MSOL identity through the UserPrincipalName by using the email address from the CSV file. Se il tentativo non riesce, lo script tenta di trovare qualsiasi oggetto MSOL contenente l'indirizzo di posta elettronica dal file CSV all'interno della proprietà ProxyAddresses.If this attempt fails, the script tries to find any MSOL object that contains the email address from the CSV file within the ProxyAddresses property. Se non è ancora possibile trovare un utente, il messaggio di posta elettronica viene considerato inesistente e viene ignorato.If a user still cannot be found, the email is deemed not to exist and is skipped.

Funziona con Multi-Factor Authentication (MFA)?Does this work with Multi-Factor Authentication (MFA)?

Questo script funziona con Multi-Factor Authentication perché il cmdlet Connect-MsolService supporta Azure Active Directory Authentication Library (ADAL).This script works with Multi-Factor Authentication because the Connect-MsolService cmdlet supports Azure Active Directory Authentication Library (ADAL).

Risoluzione dei problemiTroubleshooting

Errore: il file CSV fornito non contiene dati SMTP validi. Controllare il file CSV e riprovare.Error: The CSV provided did not contain any valid SMTP data. Please check the CSV file and try again.

Verificare che il file CSV contenga l'intestazione corretta e gli indirizzi di posta elettronica validi da analizzare.Check that the CSV file contains the proper header and valid email addresses to parse.

Errore: Impossibile trovare l'user1@contoso.com, operazione ignorata.Error: Could not find user user1@contoso.com, skipping!

Verificare che il messaggio di posta elettronica venga risolto correttamente.Check that the email properly resolves.

Errore: impossibile trovare la proprietà 'AccountSkuId' nell'oggetto. Verificare che la proprietà esista.Error: The property 'AccountSkuId' cannot be found on this object. Verify that the property exists.

Verificare che l'utente abbia la licenza EXO appropriata.Check that the user has the proper EXO license.

Errore: Impossibile trovare il file CSV...Error: The CSV file could not be found ...

Verificare che il file corretto sia specificato durante la definizione e che l'utente che esegue lo script abbia le -CSV autorizzazioni per leggere il file.Confirm the correct file is specified when defining the -CSV and that the user running the script has permissions to read the file.

Se lo script ha esito positivo ma l'output riporta: Script completato, ma il numero totale di utenti con licenza è zero (0).If the script is successful but the output reports: Script completed, but the total number of users licensed is zero (0).

  1. Verifica che l'utente non sia già concesso in licenza.Confirm the user is not already licensed.
  2. Verificare che l'utente utilizzi il piano di Exchange Online corretto.Confirm the user is using the correct Exchange Online plan.
  3. Verificare che l'UPN o l'indirizzo di posta elettronica proxy degli utenti si risolva nell'ambiente.Confirm the users UPN or proxy email address resolves in the environment.