Public/Support/VoiceConfig/Enable-TeamsUserForEnterpriseVoice.ps1
# Module: TeamsFunctions # Function: Teams User Voice Configuration # Author: David Eberhardt # Updated: 01-DEC-2020 # Status: Live function Enable-TeamsUserForEnterpriseVoice { <# .SYNOPSIS Enables a User for Enterprise Voice .DESCRIPTION Enables a User for Enterprise Voice and verifies its status .PARAMETER UserPrincipalName Required for Parameterset UserPrincipalName. UserPrincipalName of the User to be enabled. .PARAMETER Object Required for Parameterset Object. CsOnlineUser Object passed to the function to reduce query time. .PARAMETER Force Suppresses confirmation prompt unless -Confirm is used explicitly .EXAMPLE Enable-TeamsUserForEnterpriseVoice John@domain.com Enables John for Enterprise Voice .INPUTS System.String .OUTPUTS System.Void - If called directly Boolean - If called by another CmdLet .NOTES Simple helper function to enable and verify a User is enabled for Enterprise Voice Returns boolean result and less communication if called by another function Can be used providing either the UserPrincipalName or the already queried CsOnlineUser Object .COMPONENT VoiceConfiguration .FUNCTIONALITY Enables a User for Enterprise Voice in order to apply a valid Voice Configuration .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Enable-TeamsUserForEnterpriseVoice.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_VoiceConfiguration.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_UserManagement.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_Supporting_Functions.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/ #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'UserPrincipalName')] [Alias('Enable-Ev')] [OutputType([Boolean])] param( [Parameter(Mandatory, Position = 0, ParameterSetName = 'Object', HelpMessage = 'CsOnlineUser Object')] [Object]$UserObject, [Parameter(ParameterSetName = 'Object', HelpMessage = 'AzureAdUserLicense Object')] [Object]$LicenseObject, [Parameter(Mandatory, Position = 0, ParameterSetName = 'UserPrincipalName', ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('ObjectId', 'Identity')] [ValidateScript( { If ($_ -match '@' -or $_ -match $script:TFMatchGuid) { $True } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid UPN or ObjectId' } })] [string[]]$UserPrincipalName, [Parameter(HelpMessage = 'Suppresses confirmation prompt unless -Confirm is used explicitly')] [switch]$Force ) #param begin { Show-FunctionStatus -Level Live Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" # Asserting MicrosoftTeams Connection if ( -not (Assert-MicrosoftTeamsConnection) ) { break } # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { $DebugPreference = 'Continue' } if ( $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { $InformationPreference = 'Continue' } $Stack = Get-PSCallStack $Called = ($stack.length -ge 3) # Preparing Splatting Object $parameters = $null $Parameters = @{ 'Called' = $Called 'Force' = $Force } #region Worker Function function EnableEV ($UserObject, $LicenseObject, $Called, $Force) { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" #TEST Id - may need to use SipAddress for better compatibility (users only) #$Id = $($UserObject.SipAddress) $Id = $($UserObject.UserPrincipalName) Write-Verbose -Message "[PROCESS] Enabling User '$Id' for Enterprise Voice" if ( $UserObject.InterpretedUserType -notmatch 'User' ) { $Message = "Object '$Id' is not a User!" if ($Called) { Write-Warning -Message $Message return $false } else { throw [System.InvalidOperationException]::New("$Message") } } elseif ( -not $LicenseObject.PhoneSystem ) { $Message = "'$Id' Enterprise Voice Status: User is not licensed correctly (PhoneSystem required)!" if ($Called) { Write-Warning -Message $Message return $false } else { throw [System.InvalidOperationException]::New("$Message") } return $(if ($Called) { $false }) } elseif ( -not [string]$LicenseObject.PhoneSystemStatus.contains('Success') ) { $Message = "'$Id' Enterprise Voice Status: User is not licensed correctly (PhoneSystem required to be enabled)!" if ($Called) { Write-Warning -Message $Message return $false } else { throw [System.InvalidOperationException]::New("$Message") } } elseif ( $UserObject.EnterpriseVoiceEnabled -and -not $Force ) { if ($Called) { return $true } else { Write-Verbose -Message "'$Id' Enterprise Voice Status: User is already enabled!" -Verbose Set-CsPhoneNumberAssignment -Identity $Id -EnterpriseVoiceEnabled $TRUE -ErrorAction SilentlyContinue } } else { if ( $UserObject.EnterpriseVoiceEnabled ) { Write-Information "TRYING: '$Id' - Enterprise Voice Status: Enabled, trying to re-enable with FORCE" } else { Write-Information "TRYING: '$Id' - Enterprise Voice Status: Not enabled, trying to enable" } try { if ($Force -or $PSCmdlet.ShouldProcess("$Id", 'Enabling User for EnterpriseVoice')) { try { Set-CsPhoneNumberAssignment -Identity $Id -EnterpriseVoiceEnabled $TRUE -ErrorAction STOP } catch { #TEST whether to remove this method? returns cmdlet is deprecated error now. #Writing error of Set-CsPhoneNumberAssignment to debug stream Write-Warning -Message "Enablement with 'Set-CsPhoneNumberAssignment' did not work, trying legacy method!" " Function: $($MyInvocation.MyCommand.Name) - Set-CsPhoneNumberAssignment threw exception:", ($($_.Exception.Message) | Out-String).Trim() | Write-Debug Set-CsUser -Identity $Id -EnterpriseVoiceEnabled $TRUE -HostedVoiceMail $TRUE -ErrorAction STOP } $i = 0 $iMax = 20 $Activity = 'Enable User For Enterprise Voice' $Status = 'Azure Active Directory is propagating Object. Please wait' $Operation = 'Waiting for Get-CsOnlineUser to return a Result' Write-Verbose -Message "$Status - $Operation" do { if ($i -gt $iMax) { Write-Error -Message "'$Id' - Enterprise Voice Status: FAILED (User status has not changed in the last $iMax Seconds" -Category LimitsExceeded -RecommendedAction 'Please verify Object has been enabled (EnterpriseVoiceEnabled)' return $false } Write-Progress -Id 0 -Activity $Activity -Status $Status -CurrentOperation $Operation -SecondsRemaining $($iMax - $i) -PercentComplete (($i * 100) / $iMax) Start-Sleep -Milliseconds 1000 $i++ } while ( -not $(Get-CsOnlineUser -Identity "$($UserObject.UserPrincipalName)" -WarningAction SilentlyContinue).EnterpriseVoiceEnabled ) Write-Progress -Id 0 -Activity $Activity -Completed if ($Called) { return $true } else { Write-Verbose -Message "'$Id' - Enterprise Voice Status: SUCCESS" -Verbose } } } catch { $Message = "'$Id' - Error enabling user for Enterprise Voice: $($_.Exception.Message)" if ($Called) { Write-Warning -Message $Message return $false } else { throw $_ } } } } #endregion } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" switch ($PSCmdlet.ParameterSetName) { 'UserprincipalName' { foreach ($User in $UserPrincipalName) { Write-Verbose -Message "[PROCESS] Processing provided UserPrincipalName '$User'" try { $CsUser = Get-CsOnlineUser -Identity "$User" -WarningAction SilentlyContinue -ErrorAction Stop $LicenseObject = Get-AzureAdUserLicense "$User" } catch { Write-Error "'$User' not found" -Category ObjectNotFound continue } EnableEV -UserObject $CsUser -LicenseObject $LicenseObject @Parameters } } 'Object' { Write-Verbose -Message "[PROCESS] Processing provided CsOnlineUser Object for '$($UserObject.UserPrincipalName)'" if ( -not $LicenseObject.IsPresent ) { $LicenseObject = Get-AzureAdUserLicense "$($UserObject.UserPrincipalName)" } EnableEV -UserObject $UserObject -LicenseObject $LicenseObject @Parameters } } } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } #end } #Enable-TeamsUserForEnterpriseVoice |