SCRIPT: List-UnusedNumbers.ps1
Script Name: List-UnusedNumbers.ps1
Script Author: Lync MVP Ståle Hansen
Original Post: http://msunified.net/2011/01/17/script-to-find-available-telephone-numbers-in-lync-server-2010/
Featured: The official Lync Server 2010 PowerShell Blog, look under Voice Application
Log:
- V10 21.04.2011
- After some great feedback I have updated the script to be much more dynamic by supporting different country codes in the same deployment
- The only customization (in theory) you have to do in the script is changing the length of your country code
- This can be done in line 019
- Added check if Unassigned Numbers are in E.164 format, if its not, continue to the next number serie
- V06 12.04.2011
- Added finding common area phones with line uri, thanks to colleague Jarle Utne
- v05 01.04.2011
- Added finding numbers for users enabled with private lines, thanks again to Paul-Christiaan Diks
- Added line $used=$used | ForEach-Object {$_.ToLower()} to convert the $used array to all lower case letters, because the {$_.Replace(“tel:+47″, “”) would not work on uppercase letters
- Added finding numbers for analog devices, thanks to Marjus Sirvinsks for the tip
- v04 24.03.2011
- Added finding numbers for Response Groups, thanks to Paul-Christiaan Diks
- v03 22.02.2011
- Added supression of error messages when removing “tel:+47″ from arrays. Got errors if they where empty
- v02 09.02.2011
- Added TrustedApplicationEndpoint filter as well
- v01 17.01.2011
- Initial Script
- Gets numbers from users, Exchange UM Contacts and Dial In Conferencing
- Lists total available numbers, total numbers, and what numbers are available
- Fixed country code to +47
####################################################################################################
# List-UnusedNumbers.ps1
#
# v10 April 2011 by Ståle Hansen, Lync MVP (http://msunified.net)
#
# Thanks to Marjus Sirvinsks (http://marjuss.wordpress.com) for pointing me in the right direction
#
####################################################################################################
[System.Console]::ForegroundColor = [System.ConsoleColor]::White
clear-host
Write-Host "Script for finding unused numbers in Lync Server 2010, by Ståle Hansen"
Write-Host
foreach ($Serie in (Get-CsUnassignedNumber)) {
#The CountryCodeLength is the length of you countrycode. For Norway this is 47 so the length is 2.
#If you want to remove more than 2 digits, change the $CountryCodeLength
$CountryCodeLength=2
#The "tel:+" string is the +5 lenght that is added in the next line
$CountryCodeLength=$CountryCodeLength+5
#Now we get the replace string so that all numbers can be converted to an int
#In the norwegian case this value becomes tel:+47
$ReplaceValue=($Serie.NumberRangeStart).Substring(0,$CountryCodeLength)
#Check to see if Unassigned Numbers are in E.164 format, if its not, continue to the next number serie
if (($ReplaceValue.Substring(0,5)) -ne "tel:+"){
Write-Host "The script requires that Unassigned Numbers are populated in E.164 format" -Foregroundcolor Yellow
Write-Host "It appears that the number range " -nonewline
Write-Host $Serie.Identity -nonewline -Foregroundcolor Green
Write-Host " is not in this format"
Write-Host
Continue
}
#To see what your $ReplaceValue is, untag the next line
#Write-Host Value to be replaced is $ReplaceValue
$NumberStart=$Serie.NumberRangeStart | ForEach-Object {$_.Replace($ReplaceValue, "")}
$NumberEnd=$Serie.NumberRangeEnd | ForEach-Object {$_.Replace($ReplaceValue, "")}
$Ser=$NumberStart..$NumberEnd
$ErrorActionPreference = 'SilentlyContinue'
$Used=Get-CsUser -Filter {LineURI -ne $Null} | Select-Object LineURI | out-string -stream
$Used+=Get-CsUser -Filter {PrivateLine -ne $Null} | Select-Object PrivateLine | out-string -stream
$Used+=Get-CsAnalogDevice -Filter {LineURI -ne $Null} | Select-Object LineURI | out-string -stream
$Used+=Get-CsCommonAreaPhone -Filter {LineURI -ne $Null} | Select-Object LineURI | out-string -stream
$Used+=Get-CsExUmContact -Filter {LineURI -ne $Null} | Select-Object LineURI | out-string -stream
$Used+=Get-CsDialInConferencingAccessNumber -Filter {LineURI -ne $Null} | Select-Object LineURI | out-string -stream
$Used+=Get-CsTrustedApplicationEndpoint -Filter {LineURI -ne $Null} | Select-Object LineURI | out-string -stream
$Used+=Get-CsRgsWorkflow | Select-Object LineURI | out-string -stream
$Used=$Used | ForEach-Object {$_.ToLower()}
$Used=$Used | ForEach-Object {$_.Replace($ReplaceValue, "")}
$Used=$Used | ForEach-Object {$_.split(';')[0]}
$ErrorActionPreference = 'Continue'
$AllUsed=@()
foreach($Series in $Ser){foreach($UsedNumber in $Used){
if($Series -eq $UsedNumber){$AllUsed+=$UsedNumber}
}
}
$ListUnUsed=@()
$ComparisonResult=compare-object $Ser $AllUsed
foreach($UnUsed in $ComparisonResult){
if($UnUsed.SideIndicator -eq '<='){$ListUnUsed+=$UnUsed.InputObject;$FreeSize++}
}
$RangeSize=($NumberEnd-$NumberStart)+1
$TotalUsed = $RangeSize-$FreeSize
$TotalFree = $RangeSize-$TotalUsed
Write-Host "Total free numbers in number range " -nonewline
Write-Host $Serie.Identity -NoNewLine -Foregroundcolor Green
Write-Host ", " -NoNewLine
Write-Host $TotalFree -NoNewLine
Write-Host " of"$RangeSize
Write-Host "This range start with " -NoNewLine
Write-Host $NumberStart -NoNewLine -Foregroundcolor Green
Write-Host " and ends with " -NoNewLine
Write-Host $NumberEnd -Foregroundcolor Green
Write-Host "To list available numbers, press "-NoNewLine
Write-Host "L" -NoNewLine -Foregroundcolor Green
$opt = Read-Host " else press Enter"
if($opt -eq "L"){$ListUnUsed}
Write-Host
$FreeSize=0
$ListUnUsed=$NULL
$UsedNumbers=$NULL
}
[System.Console]::ForegroundColor = [System.ConsoleColor]::Gray


Alex Lewis said
Hmmm, this doesn’t seem to work when using the ;ext=1234 format…
Ståle Hansen said
Hi Alex, thanks for trying my script :)
It should work and works in my lab. The line number 31 removes everything after ; “$used=$used | ForEach-Object {$_.split(‘;’)[0]}”
Are you sure you changed all the +47 prefixes?
Alex Lewis said
I did change all the +47s but I had to do this – $_.Replace(“tel:+14085551234;ext=”, “”) where +14085551234 was the DID. Pretty simple and I can’t believe it took me that long to figure out :)
GREAT script BTW!
Ståle Hansen said
Thanks :) What is your output now? only the extensions? or is your extensions part of the full number?
Alex Lewis said
Only the extensions, but I could have changed that the in write-output field to add it back in. I also added a function to write to a log file.
Ståle Hansen said
Sounds great, I am looking into makin the script more generic regarding countrycode and so forth. All tips are appreciated.
Other areas I see this script can develop is being even more generic, and be part of a script enabling users for Enterprise Voice.
Alex Lewis said
I found a fix. Where you eliminated “tel:+47″ I changed that to be the full DID and ext part so “+14085551234;ext=” Now it returns all the “open” extensions.
Paul-Christiaan Diks said
One additional item you should add is the new Private Line feature. With this it should be complete I guess :)
Get-CsUser -Filter {PrivateLine -ne $Null}
Ståle Hansen said
Thanks! Will look into it :)
Ståle Hansen said
New updates to the script:
After some great feedback I have updated the script to be much more dynamic by supporting different country codes in the same deployment
Added check if Unassigned Numbers are in E.164 format, if its not, continue to the next number serie
PowerShell Scripts - Unified Communication, Lync 2010 said
[...] List Unused Numbers (external link) [...]
Staggerlee said
Great script but it has an issue when using typical 10 digit dialing in the U.S.. The Range Operator code on line 43 ($Ser=$NumberStart..$NumberEnd) is limited to only 32-bit values (-2,147,483,648 and 2,147,483,647). In the instance of 10 digit dialing where the area code begins with say 412 (4125551212), the script will fail with the following error – “Cannot convert value “4125551212″ to type “System.Int32″. Error: “Value was either too large or too small for an Int32.”
Editing the $CountryCodeLength variable to “4″ to strip out the area code will work but is really only useful if you only have a single area code in the DID range. I some US cities, you can have multiple area codes (i.e. 412, 325, 514) so if you used this method, you would not know what area code prefix goes with the unassigned number that was listed.
I’m new to powershell and have been looking for a way to update the script to work. Will probably have to do it with an array of some sort but I’m not that good yet. Would appreciate any assistance.
Interview with a Lync Pro: Ståle Hansen - NextHop - Site Home - TechNet Blogs said
[...] I created this script in January 2011 during a long weekend and have been using it ever since. It even got published as the only external script at the Lync PowerShell blog, which I am very proud of. You can find the script here: List-UnusedNumbers.ps1. [...]
Interview with a Lync Pro: Ståle Hansen said
[...] I created this script in January 2011 during a long weekend and have been using it ever since. It even got published as the only external script at the Lync PowerShell blog, which I am very proud of. You can find the script here: List-UnusedNumbers.ps1. [...]
James Botham said
Brilliant script, only issue I have found is that it doesn’t take in to account numbers used by response groups. Not sure if this can be fixed but other than that it is great!!
Ståle Hansen said
Hi, thanks for commenting.
This line should find numbers used by response groups, let me know it that is not the case: $Used+=Get-CsRgsWorkflow | Select-Object LineURI | out-string -stream
James Botham said
How odd, if I run the command on its own it brings up the response group numbers without an issue and lists 9. The only reason I know for sure it isn’t working is that we have a number range with 20 numbers dedicated to response groups and it lists all 20 of them as free when 9 are in use.
Very strange!
Ståle Hansen said
Yes, strange, its tested ok in other deployments, could you send me the number series configuration offline? So I can have a quick look at it and maybe test it in lab.
/Ståle