Alan's sysadmin Blog

Working smarter not harder

Posts Tagged ‘PowerShell’

PS Script: Auto Generating New Extensions in Lync

Posted by Alan McBurney on August 29, 2014

This a script I’ve been meaning to put together for a while in order to find free extensions within a given extension range in Lync.

Within Lync I assign all enterprise voice users with a phone number and extension.
Some users have a DDI assigned whilst others use the base office number with an extension.

Each office has its own extensions range

100 – 109 HQ response Groups
110 – 299 HQ Users
300 – 399 Branch Office 1
400 – 499 Branch Office 2

Over time and depending on who activates new staff members the extensions tend to get out of sequence, so finding the next available extension within a range can be tedious.

The Get-FreeExtensions.ps1 script makes finding available extensions a lot easier.

The script has 4 parameters:

BaseNumber is the base number to search against without the +, ExtensionsRequired is the number of extensions that are needed within a given range, where ExtRangeStart and ExtRangeEnd define the range.

The script is run as the example below in order to generate 5 free extensions within the range 110 to 299

Get-FreeExtensions.ps1 -BaseNumber 442890454433 -ExtensionsRequired 5 -ExtRangeStart 110 -ExtRangeEnd 299

The script will always find the free extensions in ascending numerical order

  Finds free extensions within a given range
  Version 1.0, August 28th, 2014
  Version 1.1, December 16th, 2014
  This script will find the next available extension(s) within a given extension range.
  The script searches for extensions across:
    Unified Messaging
  The script will also throw a warning if the number of required extensions are not
  available within the given range.
  .PARAMETER -BaseNumber
  This the base number to search for a free extension within
  .Parameter -ExtensionsRequired
  This is the number of free extensions that are required
  .Parameter -ExtRangeStart
  This is the start of the range to query
  .Parameter -ExtRangeEnd
  This is the end of the Range to query
  Get-FreeExtensions.ps1 -BaseNumber 442890454433 -ExtensionsRequired 5 -ExtRangeStart 100 -ExtRangeEnd 199
  [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$false,HelpMessage='Base Number without +')][long]$BaseNumber,
  [parameter(Position=2,Mandatory=$true,ValueFromPipeline=$false,HelpMessage='Number of Extensions Required')][int]$ExtensionsRequired,
  [parameter(Position=3,Mandatory=$true,ValueFromPipeline=$false,HelpMessage='Extension Range Start')][int]$ExtRangeStart,
  [parameter(Position=4,Mandatory=$true,ValueFromPipeline=$false,HelpMessage='Extension Range End')][int]$ExtRangeEnd
#Check to Ensure Lync Module is loaded or can be loaded
Function Get-MyModule
  if (-not(Get-Module -name $Name))
    if(Get-Module -ListAvailable | Where-Object {$_.Name -eq $Name})
      Import-Module -Name $Name
      Write-Host $Name PowerShell Module Not Available -ForegroundColor Red
Get-MyModule -Name Lync
Function Get-LyncExtensions
  $Extensions = @()
  $Extensions += (Get-CsUser).LineURI | Where-Object {$_ -match "$BaseNumber;ext="}
  $Extensions += (Get-CsUser).PrivateNumber | Where-Object {$_ -match "$BaseNumber;ext="}
  $Extensions += (Get-CsRgsWorkflow).LineURI | Where-Object {$_ -match "$BaseNumber;ext="}
  $Extensions += (Get-CsAnalogDevice).LineURI | Where-Object {$_ -match "$BaseNumber;ext="}
  $Extensions += (Get-CsCommonAreaPhone).LineURI | Where-Object {$_ -match "$BaseNumber;ext="}
  $Extensions += (Get-CsExUMContact).LineURI | Where-Object {$_ -match "$BaseNumber;ext="}
  $Extensions += (Get-CsMeetingRoom).LineURI | Where-Object {$_ -match "$BaseNumber;ext="}
  if (($Extensions).Count -gt "0")
      $Extensions -replace "tel:\+$BaseNumber;ext=" | Sort

If ((Get-LyncExtensions).Count -eq "0")
  Write-Host "Invalid Base Number detected, please ensure the base number is valid" -ForegroundColor Red
$UnUsedCount = 0
$ExtRange = ($ExtRangeStart..$ExtRangeEnd)
$FreeExt = @()
$UsedExt = Get-LyncExtensions
$CompareUsed = Compare-Object $UsedExt $ExtRange
foreach ($ext in $CompareUsed)
  if($ext.sideIndicator -eq "=>") {$FreeExt+=$ext.inputobject;$UnUsedCount++}
if ($ExtRangeStart -gt $ExtRangeEnd)
  Write-Host "Extension End Range must be equal or greater to Extension Start Range" -ForegroundColor Yellow
  } elseif ($ExtensionsRequired -gt $ExtRange.Count) {
    Write-Host "Extensions Required is greater than Specifed Extensions Range. Please ammend the Extension Range End parameter" -ForegroundColor Yellow
  } elseif ($ExtensionsRequired -gt $UnUsedCount) {
    Write-Host "Not enough free extensions within the specified range $ExtRangeStart-$ExtRangeEnd Maximum is $UnUsedCount" -ForegroundColor Yellow
  } else {
    $FreeExt | Select -First $ExtensionsRequired

Posted in Lync, Lync 2013, PowerShell | Tagged: , , , , | Leave a Comment »

Automating PowerShell Connection to Office 365

Posted by Alan McBurney on August 18, 2014

Connecting to Office 365 manually can be a bit of a chore especially if you need to do it on a regular basis, so why not automate the task.

Be sure the following components have been installed on your system before attempting this.

    • Azure Active Directory Module for Windows PowerShell
    • Microsoft Online Services Sign-In Assistant

In order to automate the task, credentials are exported to an XML file.

Get-Credential | Export-Clixml $env:USERPROFILE\Documents\MyO365Creds.xml

The cool thing about exporting the credentials used to connect to 365 using the Export-Clixml command is that the credentials are automatically encrypted within the file using DPAPI and can only by decrypted by the person who originally saved it.


The final piece of the automation process is adding this into your PowerShell profile
First test to see if a profile exists

Test-Path $Profile

Running the above command will return either a True or False value.
True being that the profile exists, false that it doesn’t

If the return value is false then in order to create the profile run the code below

New-Item -Type File -Path $Profile


Once the profile exists, to open the Profile type

Notepad $Profile

Finally enter the following into your PowerShell profile. This will run every time you launch PowerShell

Import-Module MSOnline
$Cred = Import-Clixml $env:USERPROFILE\Documents\MyO365Creds.xml
Connect-MsolService -Credential $Cred

If you work with multiple office 365 accounts each one of these credentials can be represented by a variable within your PowerShell profile.

$Cust1Cred = Import-Clixml $env:USERPROFILE\Documents\Cust1O365Creds.xml
$Cust2Cred = Import-Clixml $env:USERPROFILE\Documents\Cust2O365Creds.xml
$Cust3Cred = Import-Clixml $env:USERPROFILE\Documents\Cust3O365Creds.xml

Typically I will omit the final line from the Profile to connect to the service.
Then its really simple to connect to a customers tenancy using

Connect-MSOLService –Credential $Cust1Cred

Posted in Office 365, PowerShell | Tagged: , , | Leave a Comment »

Windows Server Core 2012 R2 Remote Management

Posted by Alan McBurney on October 8, 2013

In my last blog post I added certificate services to a server core installation.

Well as it turns out after some more hands on with server core I did it the hard way as Server 2012 brings with it a new level of remote or headlesss management.

When I first got this up and running I was pretty blown away by the experience.

What I’m going to walk though in this blog post are the configuration steps that are required in order to get remote management of the server core installation up and running via a dedicated management server.

In this lab I have 2 Windows 2012 R2 Servers

  • 1 Server Core
  • 1 GUI

I’m not going to include the steps that are required in order to get the VM’s installed.
I’m going to pick this up from the point that the installation is complete.

Once Server Core has been installed and you have created your admin password and logged in. The first thing to do is fire up SConfig in order to set:

  • Server Name
  • IP Address\Subnet Mask
  • DNS Servers
  • Remote Desktop


Running sconfig from the command prompt brings up the screen as below and allows basic server setup options to be configured


Select Option 2 and enter a computer name for the server. This requires a reboot once complete

Once the server comes backup and your logged back in run sconfig again and this time choose option 8 in order to set the IP Adresss, Subnet mask, Default Gateway and DNS Servers

Once complete that’s about all that needs done on the server core installation.

We can now switch over to the Management Server.

Configure this server up in the normal way, setting:

  • IP Address\Subnet Mask
  • Default Gateway
  • DNS Server
  • Server Name

Reboot the server and get logged back in.

As we are still to configure a domain we are effectively in a workgroup.
And as there is no domain there is no DNS for name resolution.

To work around these issues there are few steps that need to be taken.

  1. Add a host file entry for the DC on th emanagement server
  2. Add the would be Domain Controller to the trusted hosts file on the management server

Lets go ahead and take care of the easy task of assining the Domain Controller ServerName to the management servers host file

Open Notepad as administrator and then open:


Add an entry for the domain controller similar to that below


Close the file and test name resolution via ping.
We won’t get a ping response due to the Firewall on Quarkalbs-DC01 but thats not the point. The point here is to test name resolution.


Now that name resolution is functional for QuarkLabs-DC01 the next step is to add the server to the trusted hosts file on the management server

Open PowerShell and run the following command

Set-Item WSMAN:\localhost\Client\TrustedHosts quarklabs-dc01 -force


All items are now set and we can go back to the Server Manager Dashboard on the management server and add our remote server

From Server Manager choose Add other server to manage


Select DNS and add the remote server


Click OK and wait for a moment while the remote server is added.

The server count should have increased from the dashboard


Open All Servers and be sure that the recently added server is now present


The server can now be managed via the management server like any normal server.

That wraps it up for this post. In the next post I’ll configure and promote the server to be a domain controller all via the management server.


Posted in Active Directory, Server 2012 R2, Server Core, Windows Servers | Tagged: , , , | Leave a Comment »

Creating File Shares with PowerShell

Posted by Alan McBurney on July 23, 2013

I’m gradually moving more and more to PowerShell only for server administration.

Today I needed to create a new file share for a Lync 2013 Std Edition installation on Server 2012 and once again I looked to achieve this though the Shell.

As it turns out that this is a very simple task so with no further ado here is the syntax

New-SmbShare –Name LyncShare -Path C:\LyncShare –Description “Lync 2013 File Share” –FullAccess Administrators

Posted in Active Directory, Lync, Lync 2013, PowerShell | Tagged: , | Leave a Comment »

Unable to Connect to Exchange Management Shell after SP2 installation

Posted by Alan McBurney on September 12, 2012

After patching a number DAG nodes with SP2 I was unable to open the EMC from any of the mailbox servers.

The follow error was displayed


To resolve this issue I downloaded the Exchange Management Console Troubleshooter Tool EMTShooter

After running the tool it found an error and displayed the following


After reading through the possible solutions I discounted options 2 & 3 as these had already been investigated and the settings were correct.

So with that I settled on option 1.

After examining the GlobalModules of C:\Windows\System32\Inetsrv\config\ApplicationHost.config I could see that the entry for WSMan was indeed missing


I added the entry and closed the file


Refresh the EMC and viola, good as new.


Posted in EMC, Exchange 2010, PowerShell | Tagged: , , , , , | Leave a Comment »

Change default gateway on clients with static IP’s using PowerShell

Posted by Alan McBurney on July 29, 2010

Recently when working on a project I need to change the gateway on a bunch of clients that had static IPs.

This PowerShell Script did the job

——-Begin Script———-

function Set-Gateway  {

#Get NICS via WMI

$NICs = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $_ -Filter “IPEnabled=TRUE”

foreach($NIC in $NICs) {$Gateway = “”




function Get-FileName {

$computer = Read-Host “Please specify the location of the file containing the computer names”

return $computer


$f = Get-FileName

Get-Content $f | foreach {Set-Gateway}

——-End Script———-

Posted in PowerShell, Windows Servers | Tagged: | 2 Comments »

Granting multiple users access to specific computers using RWW in SBS 2008

Posted by Alan McBurney on August 14, 2009

While working on an SBS 2008 migration I was faced with having to grant 60 users access to only Terminal Servers in the corporate network when using Remote Web Workplace

Powershell and Quest Active Roles to the rescue again.

The following script sets the msSBSComputerUserAccessOverride attribute to the desired computer

[PS] C:\> Get-QADUser | Where {$_.ParentContainerDN -eq “OU=MyOU,DC=Domain,DC=Local”} | Set-QADUser –ObjectAttributes @{msSBSComputerUserAccessOverride = ”S:1:3:CN=MyTerminalServer, OU=SBSServers, OU=Computers, OU=MyBusiness, DC=Domain, DC=Local”}

Posted in PowerShell, SBS | Tagged: , , | Leave a Comment »