Archive for July, 2011

Script: New-LoopbackAdapter.ps1 – Using PowerShell to Create and Configure a Loopback Adapter for Use with Direct Server Return Load Balancing in Exchange 2010 and Lync 2010

July 29th, 2011 1 comment

Using a hardware load balancer is very common to spread workload across multiple servers, as well as direct traffic to surviving servers when one goes down or is being patched. When using an HLB, there are several methods that can be used. The more conventional SNAT is quite popular, but another method, Direct Server Return, or DSR, provides for substantially increased performance. This can be key in environments where a lot of traffic from Exchange and/or Lync is going through the HLBs, or where the same HLBs are being used for many apps. Update: Tom Pacyk and John Cook pointed out that I neglected to mention that DSR based HLB is not supported on Lync Edge servers (and it won’t even work based on my testing). See Microsoft’s support statement at the bottom of Sorry about the omission, guys!

The difference from a server side perspective, is that to use the DSR method, extra configuration is required when building the server. To configure a server for DSR based load balancing a loopback adapter is added and configured with the IP address of the load balancer VIP. This allows the server to accept packets targeted for the VIP address. Without it, the server would ignore them.

  • Add the Microsoft Loopback adapter
  • Unbind all services and protocols except IPv4
  • Rename the loopback adapter to “loopback” and rename the regular NIC to “net”
  • Assign an IP address and subnet mask (but no gateway)
  • Configure the adapter to not register its address in DNS
  • Set the adapter’s metric to 254
  • Adjust the adapter bindings so that it is lower than the normal NIC in the server
  • Set WeakHostSend and WeakHostReceive settings on both adapters

While adding and configuring the loopback adapter is simple enough, it’s a list of steps that is ideally suited for PowerShell – especially if you build a fair number of servers. Unfortunately, there is no straightforward methods to accomplish all of the required tasks. In order to configure the adapter bindings, a separate file must be downloaded. In order to even add the loopback adapter, yet another file needs to be downloaded. It’s almost more grief to try it through PowerShell than to just manually do it, right? Not so fast!

PowerShell is quite powerful. We can download the required files, unzip them if needed, and then use them as required to fulfill our needs. Of course, this assumes that the server has Internet connectivity.

Run the script one of two ways. Run just the script itself by typing


and the script will prompt you for the VIP IP and subnet mask.

Or, type

.\New-LoopbackAdapter.ps1 -vipip [ip address] -vipsm [subnet mask]

for example

.\New-LoopbackAdapter.ps1 -vipip -vipsm

As with most of my scripts, tab completion for the parameters works, and there is a full help section by typing:

Get-Help .\New-LoopbackAdapter.ps1

Once the script completes, Explorer will open to the network adapters section so that you can verify the various steps have completed:

No services or protocols other than IPv4 bound to the loopback adapter:

IP address and subnet mask configured:

Metric set to 254:

DNS registration unchecked:

Loopback adapter at the bottom of the adapter bindings:

The script also creates a full transcript in the same folder as the script.


Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.


Script: Set-Lync2010Features.ps1 – Automated Prereq PowerShell Script for Lync Server 2010

July 25th, 2011 14 comments

If you’ve followed this blog for a while, you may remember one of the more popular posts, Automated prerequisite installation via PowerShell for Exchange Server 2010 on Windows Server 2008 R2. In that script, I used some simple techniques to help take some of the boring tasks out of installing Exchange 2010 servers. It was updated several times, and a new update is coming soon.

Well, Lync Server MVP Stale Hansen took that script and adapted it to installing the prerequisites for Lync Server 2010 and posted the results online. He did some neat things like installing the Best Practice Analyzer and the Resource Kit.

I took the script and added a bunch of functionality, including prerequisites for all Lync related roles, some added third-party tools such as the cool “Find Lync Versions” tool from Stephen Olsen, aka “Stumper”, was added as an option. Note: This automatically installs the .Net 4 framework.

I also added the ability to download some files that are needed – essentially automating some routine tasks. See the changelog file linked below for features added in each version.

For those of you doing Lync voice work, I haven’t done any deployments yet, so if there are tasks you’d like me to automate, please let me know and I can get them added when I have time.


Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.







See the changelog for this script for all version information

Exchange 2010 and Lync 2010 PowerShell Syntax Highlighting File for UltraEdit

July 20th, 2011 No comments

If you write a lot of PowerShell code, you probably have a favorite text editor. Maybe you use Notepad, Notepad+, PowerShell ISE, etc. Mine is IDM Computer Solutions’ UltraEdit. I’ve been using UltraEdit for many years, including while doing web dev work. It’s feature packed and well worth the few dollars that it costs.

One of UltraEdit’s great features is the ability to do syntax highlighting, with support for many different languages. By default, UltraEdit doesn’t ship with a wordfile for PowerShell. There is a community that helps develop new syntax highlighting wordfiles, and lo and behold, someone created a PowerShell wordfile.

I’ve taken that file and added the Exchange 2010 and Lync 2010 cmdlets so that they are properly highlighted. The file can be downloaded from Grab it and toss it into your %appdata%\IDMComp\UltraEdit\wordfiles folder. Enjoy!

Categories: PowerShell Tags:

Function: New-Share – Creating File Shares Via PowerShell

July 13th, 2011 4 comments

Often we need to create file shares, and this is generally fairly boring. PowerShell can help streamline this process. This function will create the share, but does not set sharing permissions. We’ll cover that later.

This is based partly on How to Use PowerShell to create shared folders in Windows 7. I resolved some minor issues and added the pipeline parameters and some minor error checking, and the description. The script will create the folder if it doesn’t exist, and then share it.

function New-Share {
 param (
  [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No folder name specified")]
    [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true, HelpMessage="No share name specified")]
    [parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$false, HelpMessage="No description specified")]
 # Check for folder; Create it if it doesn't exist
 If (!(Test-Path $FolderName)) {
  New-Item $FolderName -type Directory | Out-Null
 # Check for share; Create it if it doesn't exist
 if (!(Get-WMIObject Win32_share -filter "name='$ShareName'")){
  $Shares.Create($FolderName,$ShareName,0,65535,$Description) | Out-Null
  if (!($error)){
   # the share was created
   return $true
  } else {
   # there was an error
   return $false
 } else {
  # the share already exists
  return $false
} # end function New-Share

And we can then call the function with something like:

New-Share -FolderName "c:\LyncShare" -ShareName "LyncShare" -Description "Used by Lync server to store Address Book files, phone updates, and other important files."

As you can see, it’s pretty straight forward. We’ll cover setting both NTFS and Share permissions soon.

Categories: PowerShell Tags: ,

Function: Remove-ScriptVariables – Cleaning Up Script Variables in PowerShell

July 8th, 2011 No comments

PowerShell-logo-128x84When writing scripts that use variables, especially those that contain a fair amount of data, it’s best practice to clean up the environment when exiting. This frees up memory for other purposes, and allows you to leave the environment as clean as possible. This is accomplished using the Remove-Variable cmdlet.

As scripts become more complex and evolve over time, it can be tough to keep track of all variables in order to remove them at the end. I created this function to help deal with this. The function takes the path of the script file, inspects the file, compiles a list of variables in the script, and runs them through the Remove-Variable cmdlet. It builds on some of the code from Auto-Documenting Script Variables.

function Remove-ScriptVariables($path) { 
 $result = Get-Content $path | 
 ForEach { if ( $_ -match '(\$.*?)\s*=') {     
   $matches[1]  | ? { $_ -notlike '*.*' -and $_ -notmatch 'result' -and $_ -notmatch 'env:'}  
 ForEach ($v in ($result | Sort-Object | Get-Unique)){ 
  Write-Host "Removing" $v.replace("$","")
  Remove-Variable ($v.replace("$","")) -ErrorAction SilentlyContinue
} # end function Get-ScriptVariables

We then call the function, passing the built-in $MyInvocation.MyCommand.Name value, which automatically contains the path and name of the currently running script. Essentially, we tell the function to run against it’s own script file:

Categories: PowerShell Tags: ,

Changelog: Get-CsConnections.ps1

July 1st, 2011 8 comments

This is the changelog page for Get-CsConnections.ps1. You will find a complete list of released versions, their dates, and the features and issues addressed in each. Please refer to the script’s main page for more information including download links, installation details, and more.

v3.1 – 04-07-2016

  1. added -SkipUpdateCheck to skip update check

v3.0 – 09-09-2015

  1. clarified some examples in the help section
  2. added detection for Skype for Business Server 2015

v2.9 – 10-28-2014

  1. Fixed an issue where PowerShell v2.0 machines would choke on one line. Thanks to Thierry for pointing it out.
  2. New code-signing certificate to replace expired cert

v2.8 – 06-10-2014

  1. Clarified ShowTotal output per Nate’s comment
  2. Fixed an issue where LRS clients would show a leading space for the agent string
  3. changed FE server info to be lower case to that it’s consistent
  4. the -pool parameter is now -PoolFqdn to align with other scripts and cmdlets
  5. fine tuned some of the code used when specifying -SipAddress

v2.7 – 05-24-2014

  1. fixed check for updates dialog border
  2. defined OverallRecords as an array to avoid an issue. Thanks to Tristan for that info.
  3. fixed verbose output not showing server names. Thanks to Greig for pointing it out.

v2.6 – 02-08-2014

  1. tweaked the MaxEndpointsPerUser section to always use the global configuration. This only matters in environments where multiple configurations exist (Get-CsRegistrarConfiguration). Thanks to Matt for pointing this out.
  2. swaped in new version of Set-ModuleStatus function
  3. cleanup of param block per best practices
  4. cleanup of comment help per best practices
  5. swaped in new verion of Test-ScriptUpdates

v2.5 – 11-26-2013

  1. tweaked SQL query for case insensitivity per Jean-Luc
  2. comment help updated to include info on Windows firewall config
  3. tweaked code when getting info for a single user to fix missing data for pool connection order

v2.4 – 09-13-2013

  1. Fixed output for unique users/clients
  2. Now validates if UserHighConnectionFlag is specified, and does not exceed MaxEndPointsPerUser

v2.3 – 08-01-2013

  1. intro code for script update check
  2. better pool version detection. When using the -Pool option, you no longer need to specify -Is2013 if it’s a 2013 pool
  3. Added code to restart script in an elevated session if the current session isn’t elevated (previously the script just threw an error and exited)

v2.2 – 05-10-2013

  1. Added support for Lync Server 2013 by using the -Is2013 switch. If I can find a better way of automatically detecting the version, I’ll incorporate that in a later build.
  2. Some code optimization
  3. Bug fix for an issue where the names of servers in a pool wouldn’t display if the script was run in PowerShell v3.

v2.1 – 12-13-2012

  1. Minor formatting tweaks for better handling long client names, such as the Lync RT client.
  2. Minor bug fixes

v2.0 – 10.16.2012

  1. Added -IncludeHighUsers option. Similar to -IncludeUsers, but only shows those users who meet the UserHighConnectionFlag value (shown in white), or exceeds it (shown in red).
  2. Added -ShowTotal option. When finished, shows statistics for the org, including total number of Lync enabled users, the total number of voice enabled users, and the percentage of enabled users that are currently connected.
  3. Updated the code the assembles FQDNs when just a pool or server netbios name are specified.
  4. If -SipAddress option is used, additional information showing the preferred connection order for the user is now also included. This adds the functionality of one liners: Finding out which Lync pool servers a user is associated with, and the preferred connection order.

v1.9 – 09-21-2012

  1. Finally resolved the issue where some front end servers would have a different number for PrimaryRegistrarClusterId in SQL Express than others, causing some servers to not return data (and not throw an error). Special thanks to Dave Howe @ Microsoft for helping me identify a work around, and also to Bart, a SQL Engineer at a client site who helped me tweak the related SQL query.
  2. A little code optimization
  3. -Server option added that now allows you to target a specific server instead of an entire pool.
  4. This version is code signed. You no longer are required to have a PowerShell Execution Policy of unrestricted or RemoteSigned. However, the script cannot be edited at all, or the code signature breaks.
  5. -SipAddr now supports specifying just the left part of the SIP address, but only in organizations with ONE SIP domain. For example, -SipAddr bill.gates instead of -SipAddr
  6. -Server supports specifying the netbios domain. The script will “guess” at the FQDN by using the domain name of the machine the script is running on and appending it to the netbios name.

v1.8 – 09-14-2012

  1. Tons of formatting changes, mostly subtle
    1. Server names in the pool list are sorted
    2. Server names in the ‘Frontend Server’ list are now sorted
    3. Connections are now sorted by client
  2. Added -ShowFullClient switch to show extended client info.
  3. If -pool is not specified, and only one registrar pool exists, the script will automatically use that pool.
  4. Some additional verbose output added for troubleshooting

v1.7 – 09-07-2012

  1. Minor display sorting cleanup
  2. Streamlined some code
  3. Removed -IncludeUsers from automatically being set when using -ClientVersion

v1.6 – 07-02-2012

  1. Added feature to show just specific client versions and the connected users with that client

v1.4 – 04-19-2012

  1. cleaned up some of the param() block and added some validation
  2. streamlined some of the code
  3. tweaked the displayed results a little to better handle longer agent strings

v1.3 – 12-27-2011

  1. tweaked the formatting a little to account for longer agent strings due to mobile clients
  2. ignore the RtcApplication-[guid] account when calculating users and displaying userlist
  3. added error if pool doesn’t have any servers
  4. added UserHighConnectionFlag in parameter block to support pipeline entry

v1.1 – 08-09-2011

  1. added comment based help
  2. added option to display user list
  3. updated formatting
  4. added code so it will run in a normal PowerShell session

v1.0 – 07-01-2011

  1. original version