Public/CallQueue/Get-TeamsCallQueue.ps1
# Module: Orbit # Function: CallQueue # Author: David Eberhardt # Updated: 28-May 2023 # Status: Beta #TODO Add Transcription, SystemPromptSuppression, #TODO Add NoAgent Parameters function Get-TeamsCallQueue { <# .SYNOPSIS Queries Call Queues and displays friendly Names (UPN or Displayname) .DESCRIPTION Same functionality as Get-CsCallQueue, but display reveals friendly Names, like UserPrincipalName or DisplayName for the following connected Objects OverflowActionTarget, TimeoutActionTarget, Agents, DistributionLists and ApplicationInstances (Resource Accounts) .PARAMETER Name Required for ParameterSet Name. Searches all Call Queues for this name (unique results). If not provided, all Call Queues are queried, returning only the name .PARAMETER SearchString Required for ParameterSet Search. Searches all Call Queues for this string (multiple results possible). .PARAMETER Detailed Optional Switch. Displays all Parameters of the CallQueue This also shows parameters relating to Ids and Diagnostic Parameters. .EXAMPLE Get-TeamsCallQueue Same result as Get-CsCallQueue .EXAMPLE Get-TeamsCallQueue -Name "My CallQueue" Returns an Object for every Call Queue found with the exact Name "My CallQueue" .EXAMPLE Get-TeamsCallQueue -Name "My CallQueue" -Detailed Returns an Object for every Call Queue found with the String "My CallQueue" Displays additional Parameters used for Diagnostics & Shared Voicemail. .EXAMPLE Get-TeamsCallQueue -SearchString "My CallQueue" Returns an Object for every Call Queue matching the String "My CallQueue" Synonymous with Get-CsCallQueue -NameFilter "My CallQueue", but output shown differently. .EXAMPLE Get-TeamsCallQueue -Name "My CallQueue" -SearchString "My CallQueue" Returns an Object for every Call Queue found with the exact Name "My CallQueue" and Returns an Object for every Call Queue matching the String "My CallQueue" .INPUTS System.String .OUTPUTS System.Object .NOTES Without any parameters, Get-TeamsCallQueue will show names only Agents, DistributionLists, Targets and Resource Accounts are displayed with friendly name. Main difference to Get-CsCallQueue (apart from the friendly names) is that the Output view more concise .COMPONENT TeamsCallQueue .FUNCTIONALITY Get-CsCallQueue with friendly names instead of GUID-strings for connected objects .LINK https://github.com/DEberhardt/Orbit/tree/main/docs/Orbit.Teams/Get-TeamsCallQueue.md .LINK https://github.com/DEberhardt/Orbit/tree/main/docs/about/about_TeamsCallQueue.md .LINK https://github.com/DEberhardt/Orbit/tree/main/docs/ #> [CmdletBinding(SupportsPaging, DefaultParameterSetName = 'Name')] [Alias('Get-TeamsCQ')] [OutputType([System.Object[]])] param( [Parameter(ParameterSetName = 'Name', Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = 'Full Name of the Call Queue')] [AllowNull()] [string[]]$Name, [Parameter(ParameterSetName = 'Search', HelpMessage = 'Partial or full Name of the Call Queue to search')] [Alias('NameFilter')] [string]$SearchString, [Parameter()] [switch]$Detailed ) #param begin { Show-OrbitFunctionStatus -Level Live Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand)" # Asserting Graph Connection if ( -not (Test-GraphConnection) ) { throw 'Connection to Microsoft Graph not established. Please validate connection' } # Asserting MicrosoftTeams Connection if ( -not (Assert-MicrosoftTeamsConnection) ) { throw 'Connection to Microsoft Teams not established. Please validate connection' } # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters['Verbose']) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters['Confirm']) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters['WhatIf']) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } $DebugPreference = if (-not $PSBoundParameters['Debug']) { $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { 'Continue' } $InformationPreference = if ( $PSBoundParameters['InformationAction']) { $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { 'Continue' } #Initialising Counters $private:StepsID0, $private:StepsID1 = Get-WriteBetterProgressSteps -Code $($MyInvocation.MyCommand.Definition) -MaxId 1 $private:ActivityID0 = $($MyInvocation.MyCommand.Name) [int] $private:CountID0 = [int] $private:CountID1 = 1 #Initialising splatting Object $GetCsCallQueueParameters = @{ WarningAction = 'SilentlyContinue' ErrorAction = 'Continue' } if ( $PSBoundParameters['First'] ) { $GetCsCallQueueParameters.First = $PSCmdlet.PagingParameters.First } if ( $PSBoundParameters['Skip'] ) { $GetCsCallQueueParameters.Skip = $PSCmdlet.PagingParameters.Skip } if ( $PSBoundParameters['IncludeTotalCount'] ) { $GetCsCallQueueParameters.IncludeTotalCount = $PSCmdlet.PagingParameters.IncludeTotalCount } #Worker Function function GetCallQueues { [CmdletBinding()] [OutputType([System.Object])] param( [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = 'Call Queue object')] [AllowNull()] [object]$Q, [Parameter()] [bool]$Detailed ) #param begin { } process { # Initialising counters for Progress bars [int] $private:CountID0 = 1 $ActivityID0 = "'$($Q.Name)'" # Initialising Arrays [System.Collections.Generic.List[object]]$UserObjects = @() [System.Collections.Generic.List[object]]$DLNames = @() [System.Collections.Generic.List[object]]$AIObjects = @() [System.Collections.Generic.List[object]]$OboObjects = @() [System.Collections.Generic.List[object]]$AuthorizedUserObjects = @() if ( $Detailed ) { [System.Collections.Generic.List[object]]$ChannelUserObjects = @() [System.Collections.Generic.List[object]]$AgentObjects = @() } $StatusID0 = 'Parsing Targets' #region Finding OverflowActionTarget $CurrentOperationID0 = 'OverflowActionTarget' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 $OAT = $null if ($Q.OverflowActionTarget) { $OAT = Get-TeamsCallableEntity -Identity "$($Q.OverflowActionTarget.Id)" -WarningAction SilentlyContinue } # Output: $OAT #endregion #region Finding TimeoutActionTarget $CurrentOperationID0 = 'TimeoutActionTarget' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 $TAT = $null if ($Q.TimeoutActionTarget) { $TAT = Get-TeamsCallableEntity -Identity "$($Q.TimeoutActionTarget.Id)" -WarningAction SilentlyContinue } # Output: $TAT #endregion #region Finding NoAgentActionTarget $CurrentOperationID0 = 'NoAgentActionTarget' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 $NAT = $null if ($Q.NoAgentActionTarget) { $NAT = Get-TeamsCallableEntity -Identity "$($Q.NoAgentActionTarget.Id)" -WarningAction SilentlyContinue } # Output: $NAT #endregion #region Endpoints $StatusID0 = 'Parsing Endpoints' # Channel $CurrentOperationID0 = 'Channel' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 if ($Q.ChannelId) { $FullChannelId = $Q.DistributionLists.Guid + '\' + $Q.ChannelId $Team, $Channel = $null $Team, $Channel = Get-TeamsTeamAndChannel -String "$FullChannelId" #$Team, $Channel = Get-TeamAndChannel -String "$FullChannelId" $TeamAndChannelName = "$($Team.DisplayName)" + '\' + "$($Channel.DisplayName)" } # Output: $ChannelObject # Distribution Lists $CurrentOperationID0 = 'DistributionLists' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 foreach ($DL in $Q.DistributionLists) { try { #TEST whether GroupID accepts names - otherwise Filter or Search should help here (but must narrow down to ONE object!) $DLObject = Get-MgGroup -GroupId "$DL" -WarningAction SilentlyContinue if ($DLObject) { [void]$DLNames.Add($DLObject.DisplayName) } } catch { [string]$Message = $_ | Get-ErrorMessageFromErrorString Write-Warning -Message "'$($Q.Name)' - $Operation`: GetUser$($Message.Split(':')[1])" } } # Output: $DLNames # Users $CurrentOperationID0 = 'Users' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 foreach ($User in $Q.Users) { try { $UserObject = Get-MgUser -UserId "$($User.Guid)" -WarningAction SilentlyContinue -ErrorAction Stop | Select-Object UserPrincipalName, DisplayName, JobTitle, CompanyName, Country, UsageLocation, PreferredLanguage [void]$UserObjects.Add($UserObject) } catch { [string]$Message = $_ | Get-ErrorMessageFromErrorString Write-Warning -Message "'$($Q.Name)' - $Operation`: GetUser$($Message.Split(':')[1])" } } # Output: $UserObjects.UserPrincipalName if ( $Detailed ) { $StatusID0 = 'Switch Detailed' # Parsing Channel Users when the detailed Switch is used $CurrentOperationID0 = 'Channel Users' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 foreach ($User in $Q.ChannelUserObjectId) { try { $ChannelUserObject = Get-MgUser -UserId "$($User.Guid)" -WarningAction SilentlyContinue -ErrorAction Stop | Select-Object UserPrincipalName, DisplayName, JobTitle, CompanyName, Country, UsageLocation, PreferredLanguage [void]$ChannelUserObjects.Add($ChannelUserObject) } catch { [string]$Message = $_ | Get-ErrorMessageFromErrorString Write-Warning -Message "'$($Q.Name)' - $Operation`: GetUser$($Message.Split(':')[1])" } } # Output: $UserObjects.UserPrincipalName # Parsing Agents only when the detailed Switch is used $CurrentOperationID0 = 'Agents' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 foreach ($Agent in $Q.Agents) { try { $AgentObject = Get-MgUser -UserId "$($Agent.ObjectId)" -WarningAction SilentlyContinue -ErrorAction Stop | Select-Object UserPrincipalName, DisplayName, JobTitle, CompanyName, Country, UsageLocation, PreferredLanguage [void]$AgentObjects.Add($AgentObject) } catch { [string]$Message = $_ | Get-ErrorMessageFromErrorString Write-Warning -Message "'$($Q.Name)' - $Operation`: GetUser$($Message.Split(':')[1])" } } # Output: $AgentObjects.UserPrincipalName } # Authorized Users $CurrentOperationID0 = 'Authorized Users' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 foreach ($User in $Q.AuthorizedUsers) { $UserObject = $null try { $UserObject = Get-MgUser -UserId "$($User.Guid)" -WarningAction SilentlyContinue -ErrorAction Stop | Select-Object UserPrincipalName, DisplayName, JobTitle, CompanyName, Country, UsageLocation, PreferredLanguage [void]$AuthorizedUserObjects.Add($UserObject) } catch { [string]$Message = $_ | Get-ErrorMessageFromErrorString Write-Warning -Message "'$($Q.Name)' - $Operation`: GetUser$($Message.Split(':')[1])" } } #endregion $StatusID0 = 'Parsing Resource Accounts' #region Application Instance UPNs $CurrentOperationID0 = 'Resource Accounts (Associated)' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 foreach ($AI in $Q.ApplicationInstances) { $AIObject = $null $AIObject = Get-CsOnlineApplicationInstance | Where-Object { $_.ObjectId -eq $AI } | Select-Object UserPrincipalName, DisplayName, PhoneNumber if ($null -ne $AIObject) { [void]$AIObjects.Add($AIObject) } } # Output: $AIObjects.UserPrincipalName #endregion #region Application Instance UPNs $CurrentOperationID0 = 'Resource Accounts (CallerId)' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 foreach ($OboRA in $Q.OboResourceAccountIds) { $OboObject = $null $OboObject = Get-CsOnlineApplicationInstance | Where-Object { $_.ObjectId -eq $OboRA } | Select-Object UserPrincipalName, DisplayName, PhoneNumber if ($null -ne $OboObject) { [void]$OboObjects.Add($OboObject) } } # Output: $OboObjects.UserPrincipalName #endregion #region Creating Output Object # Building custom Object with Friendly Names $StatusID0 = 'Output' $CurrentOperationID0 = 'Constructing Output Object' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 $QueueObject = $null $QueueObject = [PSCustomObject][ordered]@{ PSTypeName = 'PowerShell.TeamsFunctsions.CallQueue' Identity = $Q.Identity Name = $Q.Name LanguageId = $Q.LanguageId UseDefaultMusicOnHold = $Q.UseDefaultMusicOnHold WelcomeMusicAudioFileName = $Q.WelcomeMusicFileName WelcomeTextToSpeechPrompt = $Q.WelcomeTextToSpeechPrompt MusicOnHoldAudioFileName = $Q.MusicOnHoldFileName RoutingMethod = $Q.RoutingMethod PresenceBasedRouting = $Q.PresenceBasedRouting AgentAlertTime = $Q.AgentAlertTime AllowOptOut = $Q.AllowOptOut ConferenceMode = $Q.ConferenceMode } # ForEach-Object parsers $Stages = @('Overflow', 'Timeout', 'NoAgent') $AllNonDefaultActions = @('Disconnect', 'RedirectPerson', 'RedirectVoiceApp', 'RedirectPhoneNumber', 'RedirectVoicemail', 'SharedVoicemail') $Stages | ForEach-Object { if ( $_ -eq 'NoAgent') { $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentApplyTo -Value $Q.NoAgentApplyTo } else { $QueueObject | Add-Member -MemberType NoteProperty -Name "$_`Threshold" -Value $Q.$("$_`Threshold") } $CallTarget = (Get-Variable "$($_.Substring(0, 1))`AT").Value $QueueObject | Add-Member -MemberType NoteProperty -Name "$_`Action" -Value $Q.$("$_`Action") $QueueObject | Add-Member -MemberType NoteProperty -Name "$_`ActionTarget" -Value $CallTarget.Entity $QueueObject | Add-Member -MemberType NoteProperty -Name "$_`ActionTargetType" -Value $CallTarget.Type $Stage = $_ if ( $Detailed ) { $AllNonDefaultActions | ForEach-Object { $Prefix = "$Stage$_" $QueueObject | Add-Member -MemberType NoteProperty -Name "$Prefix`AudioFilePrompt" -Value $Q.$("$Prefix`AudioFilePrompt") $QueueObject | Add-Member -MemberType NoteProperty -Name "$Prefix`AudioFilePromptFileName" -Value $Q.$("$Prefix`AudioFilePromptFileName") $QueueObject | Add-Member -MemberType NoteProperty -Name "$Prefix`TextToSpeechPrompt" -Value $Q.$("$Prefix`TextToSpeechPrompt") } } else { # For Non-detailed output, only the Active Type is returned, deteremined with the below. # Parameter depends on Type of Target provided. Determining correct (single) parameter to apply with CallTarget $PromptTrigger = switch ( $Q.$("$_`Action") ) { 'DisconnectWithBusy' { 'Disconnect' } 'Disconnect' { 'Disconnect' } 'Forward' { switch ( $CallTarget.ObjectType ) { 'User' { 'RedirectPerson' } 'ResourceAccount' { 'RedirectVoiceApp' } 'TelUri' { 'RedirectPhoneNumber' } } } 'Voicemail' { 'Voicemail' } 'SharedVoicemail' { 'SharedVoicemail' } default { $null } } if ( $Q.$("$_$PromptTrigger`AudioFilePrompt") ) { $PromptType = 'AudioFile' $Prompt = $Q.$("$_$PromptTrigger`AudioFilePromptFileName") } elseif ( $Q.$("$_$PromptTrigger`TextToSpeechPrompt") ) { $PromptType = 'TextToSpeech' $Prompt = $Q.$("$_$PromptTrigger`TextToSpeechPrompt") } else { $PromptType = $null # or 'None' - Depending whether we want RedirectPerson or RedirectPersonNone if not defined? $Prompt = 'None' } $QueueObject | Add-Member -MemberType NoteProperty -Name "$_`PromptTrigger" -Value $PromptTrigger $QueueObject | Add-Member -MemberType NoteProperty -Name "$_`PromptType" -Value $PromptType $QueueObject | Add-Member -MemberType NoteProperty -Name "$_`Prompt" -Value $Prompt } if ( $Detailed -or $("$_`ActionTargetType") -eq 'SharedVoiceMail') { # Displays SharedVoiceMail Parameters only if $_`ActionTargetType is set to SharedVoicemail $QueueObject | Add-Member -MemberType NoteProperty -Name "Enable$_`SharedVoicemailTranscription" -Value $Q.$("Enable$_`SharedVoicemailTranscription") $QueueObject | Add-Member -MemberType NoteProperty -Name "Enable$_`SharedVoicemailSystemPromptSuppression" -Value $Q.$("Enable$_`SharedVoicemailSystemPromptSuppression") } } <# Retained for fall-back scenario! # Adding Overflow Parameters $QueueObject | Add-Member -MemberType NoteProperty -Name OverflowThreshold -Value $Q.OverflowThreshold $QueueObject | Add-Member -MemberType NoteProperty -Name OverflowAction -Value $Q.OverflowAction $QueueObject | Add-Member -MemberType NoteProperty -Name OverflowActionTarget -Value $OAT.Entity $QueueObject | Add-Member -MemberType NoteProperty -Name OverflowActionTargetType -Value $OAT.Type if ( $Detailed -or $OverflowActionTargetType -eq 'SharedVoiceMail') { # Displays SharedVoiceMail Parameters only if OverflowActionTargetType is set to SharedVoicemail $QueueObject | Add-Member -MemberType NoteProperty -Name OverflowSharedVoicemailAudioFilePrompt -Value $Q.OverflowSharedVoicemailAudioFilePrompt $QueueObject | Add-Member -MemberType NoteProperty -Name OverflowSharedVoicemailAudioFilePromptFileName -Value $Q.OverflowSharedVoicemailAudioFilePromptFileName $QueueObject | Add-Member -MemberType NoteProperty -Name OverflowSharedVoicemailTextToSpeechPrompt -Value $Q.OverflowSharedVoicemailTextToSpeechPrompt $QueueObject | Add-Member -MemberType NoteProperty -Name EnableOverflowSharedVoicemailTranscription -Value $Q.EnableOverflowSharedVoicemailTranscription $QueueObject | Add-Member -MemberType NoteProperty -Name EnableOverflowSharedVoicemailSystemPromptSuppression -Value $Q.EnableOverflowSharedVoicemailSystemPromptSuppression } # Adding Timeout Parameters $QueueObject | Add-Member -MemberType NoteProperty -Name TimeoutThreshold -Value $Q.TimeoutThreshold $QueueObject | Add-Member -MemberType NoteProperty -Name TimeoutAction -Value $Q.TimeoutAction $QueueObject | Add-Member -MemberType NoteProperty -Name TimeoutActionTarget -Value $TAT.Entity $QueueObject | Add-Member -MemberType NoteProperty -Name TimeoutActionTargetType -Value $TAT.Type if ( $Detailed -or $TimeoutActionTargetType -eq 'SharedVoiceMail') { # Displays SharedVoiceMail Parameters only if TimeoutActionTargetType is set to SharedVoicemail $QueueObject | Add-Member -MemberType NoteProperty -Name TimeoutSharedVoicemailAudioFilePrompt -Value $Q.TimeoutSharedVoicemailAudioFilePrompt $QueueObject | Add-Member -MemberType NoteProperty -Name TimeoutSharedVoicemailAudioFilePromptFileName -Value $Q.TimeoutSharedVoicemailAudioFilePromptFileName $QueueObject | Add-Member -MemberType NoteProperty -Name TimeoutSharedVoicemailTextToSpeechPrompt -Value $Q.TimeoutSharedVoicemailTextToSpeechPrompt $QueueObject | Add-Member -MemberType NoteProperty -Name EnableTimeoutSharedVoicemailTranscription -Value $Q.EnableTimeoutSharedVoicemailTranscription $QueueObject | Add-Member -MemberType NoteProperty -Name EnableTimeoutSharedVoicemailSystemPromptSuppression -Value $Q.EnableTimeoutSharedVoicemailSystemPromptSuppression } # Adding NoAgent Parameters $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentApplyTo -Value $Q.NoAgentApplyTo $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentAction -Value $Q.NoAgentAction $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentActionTarget -Value $NAT.Entity $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentActionTargetType -Value $NAT.Type if ( $Detailed -or $NoAgentActionTargetType -eq 'SharedVoiceMail') { # Displays SharedVoiceMail Parameters only if NoAgentActionTargetType is set to SharedVoicemail $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentSharedVoicemailAudioFilePrompt -Value $Q.NoAgentSharedVoicemailAudioFilePrompt $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentSharedVoicemailAudioFilePromptFileName -Value $Q.NoAgentSharedVoicemailAudioFilePromptFileName $QueueObject | Add-Member -MemberType NoteProperty -Name NoAgentSharedVoicemailTextToSpeechPrompt -Value $Q.NoAgentSharedVoicemailTextToSpeechPrompt $QueueObject | Add-Member -MemberType NoteProperty -Name EnableNoAgentSharedVoicemailTranscription -Value $Q.EnableNoAgentSharedVoicemailTranscription $QueueObject | Add-Member -MemberType NoteProperty -Name EnableNoAgentSharedVoicemailSystemPromptSuppression -Value $Q.EnableNoAgentSharedVoicemailSystemPromptSuppression } #> # Adding Agent Information $QueueObject | Add-Member -MemberType NoteProperty -Name TeamAndChannel -Value $TeamAndChannelName if ( $Detailed ) { $QueueObject | Add-Member -MemberType NoteProperty -Name Users -Value $($UserObjects.UserPrincipalName -join ', ') $QueueObject | Add-Member -MemberType NoteProperty -Name DistributionLists -Value $($DLNames -join ', ') } else { $QueueObject | Add-Member -MemberType NoteProperty -Name Users -Value $UserObjects.UserPrincipalName $QueueObject | Add-Member -MemberType NoteProperty -Name DistributionLists -Value $DLNames } $QueueObject | Add-Member -MemberType NoteProperty -Name DistributionListsLastExpanded -Value $Q.DistributionListsLastExpanded $QueueObject | Add-Member -MemberType NoteProperty -Name AgentsInSyncWithDistributionLists -Value $Q.AgentsInSyncWithDistributionLists if ( $Detailed ) { # Displays Agents $QueueObject | Add-Member -MemberType NoteProperty -Name AgentsCapped -Value $Q.AgentsCapped $QueueObject | Add-Member -MemberType NoteProperty -Name Agents -Value $($AgentObjects.UserPrincipalName -join ', ') $QueueObject | Add-Member -MemberType NoteProperty -Name ChannelUsers -Value $($ChannelUserObjects.UserPrincipalName -join ', ') # Displays all except reserved Parameters (Microsoft Internal) $QueueObject | Add-Member -MemberType NoteProperty -Name MusicOnHoldAudioFileId -Value $Q.MusicOnHoldAudioFileId $QueueObject | Add-Member -MemberType NoteProperty -Name WelcomeMusicAudioFileId -Value $Q.WelcomeMusicAudioFileId $QueueObject | Add-Member -MemberType NoteProperty -Name MusicOnHoldFileDownloadUri -Value $Q.MusicOnHoldFileDownloadUri $QueueObject | Add-Member -MemberType NoteProperty -Name WelcomeMusicFileDownloadUri -Value $Q.WelcomeMusicFileDownloadUri $QueueObject | Add-Member -MemberType NoteProperty -Name Description -Value $Q.Description } if ( $Detailed ) { $QueueObject | Add-Member -MemberType NoteProperty -Name ResourceAccountsAssociated -Value $($AIObjects.Userprincipalname -join ', ') $QueueObject | Add-Member -MemberType NoteProperty -Name ResourceAccountsForCallerId -Value $($OboObjects.Userprincipalname -join ', ') } else { $QueueObject | Add-Member -MemberType NoteProperty -Name ResourceAccountsAssociated -Value $AIObjects.Userprincipalname $QueueObject | Add-Member -MemberType NoteProperty -Name ResourceAccountsForCallerId -Value $OboObjects.Userprincipalname } $QueueObject | Add-Member -MemberType NoteProperty -Name AuthorizedUsers -Value $AuthorizedUserObjects.Userprincipalname if ( $Detailed ) { $QueueObject | Add-Member -MemberType NoteProperty -Name HideAuthorizedUsers -Value $Q.HideAuthorizedUsers } #endregion # Output Write-Progress -Id 0 -Activity $ActivityID0 -Completed Write-Output $QueueObject } end { } } } #begin process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" [int] $private:CountID0 = [int] $private:CountID1 = 1 $StatusID0 = 'Information Gathering' #region Data gathering $CurrentOperationID0 = 'Querying Call Queues' Write-BetterProgress -Id 0 -Activity $ActivityID0 -Status $StatusID0 -CurrentOperation $CurrentOperationID0 -Step ($private:CountID0++) -Of $private:StepsID0 # Capturing no input if (-not $PSBoundParameters['Name'] -and -not $PSBoundParameters['SearchString']) { Write-Information 'INFO: No Parameters - Listing names only. To query individual items, please provide Parameter Name or SearchString' Get-CsCallQueue @GetCsCallQueueParameters | Select-Object Name return } else { $Queues = @() switch ($PSCmdlet.ParameterSetName) { 'Name' { # Lookup Write-Verbose -Message "Parameter 'Name' - Querying unique result for each provided Name" foreach ($DN in $Name) { if ( $script:OrbitRegexGuid.isMatch($DN) ) { #Identity or ObjectId Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand) - ID - '$DN'" $QueuesById = Get-CsCallQueue -Identity "$DN" @GetCsCallQueueParameters $Queues += $QueuesById } else { #Name Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand) - Name - '$DN'" $QueuesByName = Get-CsCallQueue -NameFilter "$DN" @GetCsCallQueueParameters $QueuesByName = $QueuesByName | Where-Object Name -EQ "$DN" $Queues += $QueuesByName } } } 'Search' { # Search Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand) - SearchString - '$SearchString'" $QueuesByString = Get-CsCallQueue -NameFilter "$SearchString" @GetCsCallQueueParameters $Queues += $QueuesByString } } # Parsing found Objects Write-Verbose -Message "[PROCESS] Processing found Queues: $($Queues.Count)" foreach ($Q in $Queues) { Write-Output (GetCallQueues -Q $Q -Detailed ($PSBoundParameters['Detailed']) @Args) } } #endregion } #process end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" if ($PSCmdlet.PagingParameters.IncludeTotalCount) { [double]$Accuracy = 1.0 $PSCmdlet.PagingParameters.NewTotalCount($Queues, $Accuracy) } } #end } #Get-TeamsCallQueue |