Archive

Posts Tagged ‘Deployment’

Script: Set-CsFeatures.ps1 – Easily Install Prerequisites and Tools for Lync Server 2013 and Skype for Business Server 2015

October 24th, 2016 24 comments

skype_for_business_secondary_blue_rgbDescription

Installing Skype for Business and Lync servers is usually boring if you’re a consultant who does it often. Making sure the server specs are right, installing OS features, configuring NICs, etc. It’s even more boring if you’re building a bunch of servers at one time. There’s always a chance for human error, too. So why not automate as much as possible? That’s what I was after when I built the Lync Server 2010 prereq script, then the Lync Server 2013 prereq script. And it’s certainly what I’m after for Skype for Business Server 2015. This time, however, I opted to not have a separate script for Skype for Business. Many of the requirements are the same, or just slightly different, than Lync Server 2013. So I just added the Skype for Business functionality to the 2013 script, and updated everything as a whole.

When calling the script, one only needs to specify the –Skype4b switch to put the script into “Skype for Business mode”. Not specifying that switch cause a pop-up to appear, asking what mode you’d like. The menus don’t change based on what mode the script is in. Options for only one platform are clearly noted. Otherwise, the options automatically adjust for the platform you’ve chosen. The menu starts out with core prerequisite options for common Lync/SfB roles, followed by Microsoft tools and resources, some third-party tools and options, and then some sub-menus. Sub-menus are broken down by Misc server config, Desktop shortcuts, Taskbar shortcuts, Downloads, and Security options. As you can see, there are TONS of options. I’m not going to list every menu and option here, as the nature of the script means I’ll be adding/updating things as people request them, or as vendors update/alter their offerings. Just note that the options from the 2013 script have been moved around a little bit as I try to keep things organized.

This version also uses my new method of checking for updates, as mentioned in Function: Get-UpdateInfo – Making It Easy for Your Users to Get the Latest Version of Your Scripts. When a new version is available, you’ll get a pop-up notifying you.

If you’re aware of a third-party product, or even Microsoft product, that is a good match for Skype for Business servers, let me know. I’m happy to take a look and see if it would make a good addition to the script.

Super big thanks to my beta testers for supplying bug reports, suggestions, and comments.

Syntax

C:\Set-CsFeatures.ps1 [-TargetFolder <String>] [-WindowsSource <String>] [-SQLPath <String>] [-InitialMenuOption <Int32>] [-IncludeSSMS ] [-IncludeTelnet ] [-IncludeFW ] [-IncludeHighPower ] [-IncludeStandard ] [-GetInfoFromRegistry ] [-OWASOveride ] [-DownloadOnly ] [-SkipCoreCheck ] [-Tail ] [-Skype4b ] [-SkipUpdateCheck ] [-DisableAutoUpdates ] [-IncludeLanguagePack ] [-SkipEdgeNicConfig ] [-WhatIf ] [-Confirm ] [-IncludeTotalCount ] [-Skip <UInt64>] [-First <UInt64>] [<CommonParameters>]

C:\Set-CsFeatures.ps1 [-TargetFolder <String>] [-GetInfoFromRegistry ] [-OWASOveride ] [-DownloadAll ] [-SkipCoreCheck ] [-Tail ] [-Skype4b ] [-WhatIf ] [-Confirm ] [-IncludeTotalCount ] [-Skip <UInt64>] [-First <UInt64>] [<CommonParameters>]

C:\Set-CsFeatures.ps1 [-GetInfoFromRegistry ] [-ClearRunningStatus ] [-WhatIf ] [-Confirm ] [-IncludeTotalCount ] [-Skip <UInt64>] [-First <UInt64>] [<CommonParameters>]

C:\Set-CsFeatures.ps1 [-GetInfoFromRegistry ] [-Skype4b ] [-WhatIf ] [-Confirm ] [-IncludeTotalCount ] [-Skip <UInt64>] [-First <UInt64>] [<CommonParameters>]

Examples

.\Set-CsFeatures.ps1 -Skype4b

Runs script in Skype for Business mode. Options chosen while running in this mode are tailored to Skype for Business. Not specifying this option will cause a pop-up prompt when the script starts, allowing a user to choose the desired mode.

.\Set-CsFeatures.ps1

Runs script with default values.

.\Set-CsFeatures.ps1 -WindowsSource "d:"

Runs script with the location defined for the Windows Server 2012/2012 R2 installation files.

.\Set-CsFeatures.ps1 -SQLPath "d:\sqlexpress"

Runs the script and installs any required SQL Express instances in the specified location.

.\Set-CsFeatures.ps1 -TargetFolder "d:\installbits"

Runs the script, and saves any downloaded files and written logs in the specified location instead of the default “c:\_install”.

.\Set-CsFeatures.ps1 -InitialMenuOption 3

Runs the script, and automatically starts option 3 (Front End server). Once it’s finished with that option, the script functions as normal, and displays the menu. NOTE: only options from the main menu can be specified. Options in sub-menus are not available with -InitialMenuOption.

.\Set-CsFeatures.ps1 -tail

Runs script with default values, but also shows an additional PowerShell window showing a live running log file.

Parameters

-TargetFolder

Defines the location for any downloaded files. Defaults to “c:\_install”. Additionally, log files generated by this script are located in a sub-folder of TargetFolder called “logs”. TargetFolder does not support paths with spaces, but does support non-hidden UNC paths.

-WindowsSource

Defines the location of the Windows Server installation files. This is needed to install .Net 3.5 since those files are not installed on the server by default. Defaults to first detected CD-ROM/DVD drive. This can be a local file path, path to an .ISO file, or a non-hidden UNC path.

-SQLPath

Defines the desired installation path for SQL Express. Defaults to “c:\Program Files\Microsoft SQL Server”.

-InitialMenuOption

Allows you to start the script with the option you want, without first displaying the menu.

-IncludeSSMS

If specified, will include SQL Server Management Studio automatically when prerequisites are installed for any server that has SQL Express instances. If not specified, a prompt will appear.

-IncludeTelnet

If specified, will include Telnet automatically when prerequisites for Front End servers, Director servers, Mediation servers, Edge servers, and/or Persistent Chat servers are installed. If not specified, a prompt will appear.

-IncludeFW

If specified, will include the firewall rules for Get-CsConnections automatically when prerequisites for Front End servers are installed. If not specified, a prompt will appear.

-IncludeHighPower

If specified, tells the script to automatically set the Power Config on the server to High Power. This is instead of the script prompting. This option is available for all server roles.

-IncludeStandard

If specified, tells the script to include the extra SQL Express instance required for Standard Edition front end servers. This is instead of the script prompting.

-GetInfoFromRegistry

This value is only used during mid-prereq reboots. It is automatically set and read by the script, and should never be manually specified.

-OWASOveride

Don’t use this parameter. It’s for internal testing only. Using it can render the server unusable.

-DownloadOnly

Tells this script to not install or configure anything – just download the files. This is useful if you’re going to be building servers that do not have Internet access and want to fetch the files beforehand. The big difference between this option and -DownloadAll, is that this option presents the normal menus, and allows you to download files for the options you pick. The -DownloadAll option downloads ALL files needed for ALL options.

-DownloadAll

Tells this script to not install or configure anything – just download ALL of the files. This is useful if you’re going to be building servers that do not have Internet access and want to fetch the files beforehand from a desktop computer. The big difference between this option and -DownloadOnly, is that this option downloads ALL files needed for ALL options, whereas -DownloadOnly allows a user to download files for specific options they choose.

-ClearRunningStatus

This switch forces the running status to be reset. This option should ONLY be used if the script exits/aborts dirty, and attempts to run the script again yield a “Script is already running” message.

-SkipCoreCheck

When specified, skips the check for Server Core. It is not meant to be called manually, as it’s used when the script needs to restart after a server reboot.

-Tail

When specified, opens another PowerShell session and tails the log file, similar to *nix. This is really only beneficial during troubleshooting.

-Skype4b

When specified, uses values specific to Skype For Business Server 2015 for prerequisites. If this option is NOT specified a pop-up will appear, asking which mode the script should operate in: Lync Server 2013 or Skype for Business Server 2015.

-SkipUpdateCheck

When specified, skips the check for a newer version of the script. This option is included mainly for when the script reboots the server.

-DisableAutoUpdates

When specified, skips the prompt and automatically disables auto updates for Windows Server. If not specified, a prompt is displayed.

-IncludeLanguagePack

When specified, skips the prompt for the installation of the Office Online Server English language pack. If not specified, a prompt is displayed.

-SkipEdgeNicConfig

When specified, skips the configuration of the NICs on edge servers. This requires that you manually complete those steps.

Installation

No installation is necessary.

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.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Known Issues

The only issue I’m aware of at the release of the latest version is that pinning shortcuts to the taskbar in Windows Server 2016 doesn’t seem to be working. If you come across something, please let me know. Contact info is in the header of the script, and the script also has option 96, ‘how to report a bug’ that will tell you what information is critical when reporting a problem.

Frequently Asked Questions

Question: Does this script support Windows Server 2016?

Answer: Yes – starting with version 4.20, prerequisites for Windows Server 2016 are included.


Question: Why doesn’t this script support Windows Server 2008 R2 and earlier?

Answer: I get asked this all the time. There are several reasons. The first is that out of the box, Server 2008 R2 has PowerShell 2.0 installed, and this script is written in PowerShell 3.0. Requiring you to upgrade to PowerShell 3.0 first, before running a script that installs prerequisites, seems counter-intuitive. And converting the script to just use PowerShell 2.0 is taking a step backwards, especially considering that the current version of PowerShell is 5.0, and even as this is written, 5.1 is in preview.

Next is sheer time. I test changes I make. And then I test them again. And then I choose different options and combinations and test them. Testing on just Server 2012 and Server 2012 R2 is exhausting. Adding Server 2008 R2 would mean even more testing, plus I’d have to add those resources in my already overtaxed test labs. That would slow down my ability to add new features and test fixes.

Third is that Server 2008 R2 is three versions back. Get with the times already!


Question: Does the script support Windows Server 2016?

Answer: No, and the primary reason is that Lync Server 2013 and Skype for Business Server 2015 are not supported on Windows Server 2016. Once they are supported on Windows Server 2016 (and it will likely only be Skype for Business Server 2015 that’s supported), I’ll adjust the script as needed. I’ve already done some preliminary work.


Question: Can you add feature x?

Answer: I LOVE getting feature requests. Seriously! Best method to suggest features is to send me an email. My email address is in the comment section at the top of every script I publish. Please be detailed in what you’d like to see, as well as any scenarios you’d use the option (so I can try to duplicate testing). This also goes for additional tools, whether Microsoft or third-party.


Question: How do I submit bug reports?

Answer: Email is best. Grab my email address from the comment section at the top of the script. Please be VERY detailed. Please include screen shots if possible, and ALWAYS include the log file. If the script will start, select option 96, “Report a bug/problem with this script”. If you’re not using the latest version of the script, please download it from the Downloads section below and see if you can duplicate the problem before reporting it.


Question: What if my server doesn’t have Internet access?

Answer: Fear not. Download the required files using either the -DownloadOnly or -DownloadAll options from another machine and place them in the TargetFolder, which is c:\_install by default. The script looks to see if the file is available locally before attempting to download. An exception to this is the latest cumulative update, which is always downloaded, since the URL and file name don’t change, even when the version does.


Question: When I run the script again, I get “Script already running”

Answer: This is because the script didn’t exit gracefully. Many reasons this can happen, such as rebooting the server while it’s still running. If you’re positive it’s not running anywhere else (including by other users logged into the same server), run the script with the -ClearRunningStatus switch to clear that flag. Then run it as normal.


Question: Is there an option to specify where (i.e. path) all of the various tools are installed?

Answer: No. And not for a lack of trying. Some tools don’t support automated installs with a specified path. And some of those that DO, actually still dump some core files in a “default” location. The more I tried to come up with the solution, the more I realized that it would entail a substantial amount of overhead in the script.


Question: Why does the script report an unsupported version of .NET Framework?

Answer: Because Lync Server 2013 and Skype for Business Server 2015 don’t support the version detected. Once they do, I’ll adjust the script accordingly.


Download

v4.4 – 11-12-2017 – Set-CsFeatures.v4.40.zip

v4.30 – 10-11-2017 – Set-CsFeatures.v4.30.zip

v4.20 – 09-04-2017 – Set-CsFeatures.v4.20.zip

v4.10 – 05-15-2017 – Set-CsFeatures.v4.10.zip

v4.09 – 05-13-2017 – Set-CsFeatures.v4.09.zip

v4.08 – 04-19-2017 – Set-CsFeatures.v4.08.zip

v4.07 – 04-14-2017 – Set-CsFeatures.v4.07.zip

v4.06 – 02-05-2017 – Set-CsFeatures.v4.06.zip

v4.05 – 11-04-2016 – Set-CsFeatures.v4.05.zip

v4.04 – 11-02-2016 – Set-CsFeatures.v4.04.zip

v4.03 – 11-01-2016 – Set-CsFeatures.v4.03.zip

v4.02 – 10-28-2016 – Set-CsFeatures.v4.02.zip

v4.01 – 10-25-2016 – Set-CsFeatures.v4.01.zip

v4.0 – 10-24-2016 – Set-CsFeatures.v4.0.zip

Changelog

See the changelog for information on what’s changed/included in each version.

Function: Get-UpdateInfo – Making It Easy for Your Users to Get the Latest Version of Your Scripts

October 10th, 2016 No comments

updatepromptDescription

As a PowerShell developer, you always want your users to have the latest version of a script. It makes support a lot easier, while also making sure that users have the latest features and bug fixes. But how to encourage that? Well, for me, users of my scripts are typically not within the same environment as me. So Group Policy Objects, logon scripts, etc, aren’t a solution. Having the script automatically check for an update is much easier, and doesn’t require anything from the user1. So let’s take a look at a quick and easy method.

First, we need a repository where the update information will be held. XML is perfect for this. In this example, I created the following file, and saved it as version.xml:

<?xml version="1.0"?>
<catalog>
<article id="1697">
<title>Set-CsFeatures.ps1</title>
<author>Pat Richard</author>
<version>3.9.57</version>
<publish_date>2016-10-08</publish_date>
<description>Installs all required Windows 2012/Windows 2012 R2 components & optional tools.</description>
</article>
</catalog>

This file can reside anywhere. A file path, a web site, wherever. I chose a website for the reasons I mentioned above. You can see the above file in action at http://www.ucunleashed.com/downloads/version.xml. Some key points to the file. Each article I publish going forward will have it’s own “article” node. The ID I chose to tie to it is also the ID of the article’s URL, for consistency sake. In this example, 1697 is the prereq script seen at http://www.ucunleashed.com/1697. The version value is the version of the latest general availability (“GA”) build. We’ll query that value, compare it against the version of the script running the query, and see if it’s newer. Note that there is some other info in the XML file, and that’s irrelevant to what we’re discussing here.

[xml] $xml = (New-Object System.Net.WebClient).DownloadString("http://www.ucunleashed.com/downloads/version.xml")
$Ga = ($xml.catalog.article | Where-Object {$_.id -eq $article}).version

We supply the $article value when making the call. After that, it’s a simple comparison. In the prereq script, near the beginning, I assign a variable, $version, with a value. Let’s say it’s “3.9.55”. We compare $Ga against $Version

$Ga -gt $Version

If it’s true, we know a newer version exists. If it’s false, we know the currently running script is the latest version. In theory, we could also use this to alert of a regression in case we needed to downgrade (gasp!). So let’s put this together. We assign a variable, $xml, to the results of downloading an xml file. Then, we assign $ga to the value of “version” for the specific node within the xml file that contains the info for the article. Lastly, we do our comparison and give some output if there is an update.

[xml] $xml = (New-Object System.Net.WebClient).DownloadString("http://www.ucunleashed.com/downloads/version.xml")
$Ga = ($xml.catalog.article | Where-Object {$_.id -eq $article}).version
if ($Ga -gt $Version){Write-Output "A new version is available!"}

Now, obviously, we can pretty this up a bit. But before we do that, let’s think of issues we could run into. The big one is making sure we have an Internet connection to use to check the XML file. As much as we can often assume there will be one, a LOT of organizations block Internet access to servers as part of their security posture. So we shouldn’t assume. We can check using the following:

[bool] $HasInternetAccess = ([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}')).IsConnectedToInternet)

And then using an IF loop against $HasInternetAccess. So let’s throw this all into a function we can incorporate into our scripts and modules:

function Get-UpdateInfo {
  [CmdletBinding(SupportsShouldProcess, SupportsPaging)]
  param (
    # Article/script to check for updates
    [parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
    [string] $article
  )
  [bool] $HasInternetAccess = ([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}')).IsConnectedToInternet)
  if ($HasInternetAccess){
    [xml] $xml = (New-Object System.Net.WebClient).DownloadString("http://www.ucunleashed.com/downloads/version.xml")
    $Ga = ($xml.catalog.article | Where-Object {$_.id -eq $article}).Version    
    if ($Ga -gt $version){
      Write-Log -Level Warn -Message "Outdated version. Version $Ga is latest version. Prompting user" -NoConsole
      $wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
      $updatePrompt = $wshell.Popup("A new version ($ga) of the script is available. Would you like to download it?",0,"A new version is available",68)
      if ($updatePrompt -eq 6){
        Start-Process "http://www.ucunleashed.com/$article"
      }
    }
  }else{
    Write-Output "No Internet connectivity. Unable to check online for update info."
  }
} # end function function Get-UpdateInfo

Here we incorporate a simple ComObject popup message to ask if the user wants to download the new version. Since we have assigned the GA number to $ga, we can use that in the popup text, as well, as shown in the image at the beginning of this article. If $updatePrompt is “6”, then the user clicked “Yes” on the popup, and we can take action such as opening a browser window and navigating to the articles page. Or we could download a file, or any of a number of actions. If $updatePrompt is “7”, then the user clicked “No”.

So, as you can see, it’s really not that hard to add an update checker to your scripts. When you release a new version, simply update the XML file to reflect accordingly.

Note: Take care in what kind of characters are in the XML file. Some special characters, such an ampersand (“&”), aren’t handled very well. When in doubt, open a browser window and navigate to the file.

1 – Depending on the action you require once it’s known an update is available.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Automatically Installing and Configuring WireShark for Skype for Business

October 7th, 2016 2 comments

wiresharkDescription

I mention in the blog article Script: Set-Cs2013Features.ps1 – Easily Install Prerequisites and Tools for Microsoft Lync Server 2013 that one of the options in the menu, #30, is download, install, and configure WireShark. The configuration settings are based on those mentioned by Jeff Schertz (Wireshark Capture Tips) and Matt Landis (Getting Started With Lync and Wireshark: Tips & Quirks) , as well as those I’ve found useful. Most of these settings REALLY help when you’re looking at traces (and who doesn’t love an afternoon of doing that?). Among some of the configuration settings are:

  1. adds Source Port (resolved) column
  2. adds Destination Port (resolved) column
  3. adds DSCP column
  4. Configures RTP protocol “Try to decode RTP outside of conversations”
  5. Configures SIP protocol for ports 5060-5068 (instead of WireShark’s default of 5060)
  6. Sets the time format to human readable format

Why manually configure these on your server (or worse, many servers), if we can automate it? Let’s make our deployment life easier. Getting WireShark installed programmatically isn’t like other programs. There is no .msi file, or silent install switches. Methods I’ve used in other scripts just didn’t work. And believe me, I tried. And tried. And tried. So, I went medieval on it, and used AutoIt to create a macro that steps through the installer, clicking the right buttons. This works exceptionally well, and is fairly fast. But I wanted to also include the configuration steps mentioned above. And this is where it got interesting. WireShark’s config file seems to change formats and details often. So writing something that would change the config file directly seemed like it would be a losing battle. So, back to AutoIt. For 95% of the config, it worked great. But there seemed to be a need to click on the custom columns in order to set their name. AutoIt allows for moving the mouse to a certain vector, then clicking. But even with maximizing everything, the coordinates were never the same on different servers with different resolutions or RDP sessions. So that part of it would often not work. You’d get the columns, but they’d be named “New Column”. Not ideal. Finally, after taking a break from trying to figure that out, I rethought about it, and was able to figure out the right keyboard combination to accomplish the same thing. Success! There is one section right after that where the mouse is required to move the new columns into the desired order, but that seems to always work, and there’s no keyboard control for that. A remaining issue has been there since I first started this task. And that is the fact that AutoIt is written to take action based on app windows with certain titles. Usually not an issue at all, except that WireShark has always included the version number in the title bar. So every time there is a new version released, I’d have to open the source file, change the version number, re-compile to an .exe file, test, upload to my server, and update the prereq script. All in all, it is like 10 minutes of work, but I’ll need to continue to do that. As a result, I’m releasing the macros bundled the appropriate version of WireShark. Not sure if that violates some license with WireShark, but since they seem uninterested in making a silent installer method… Download the file from the link below. Unzip anywhere, as long all of the files are in the same folder. You’ll see there are three files:

  1. The WireShark bits, which are named with the version number, such as Wireshark-win64-2.2.1.exe for version 2.2.1. This is the file as it comes from WireShark.
  2. The installer macro, which is also named according to the WireShark version it applies to, such as WireShark_2.2.1-install.exe
  3. The config macro, which is also named according to the WireShark version it applies to, such as WireShark_2.2.1-config.exe

Run the installer macro first by double clicking on it. You’ll see it zip through the WireShark install routine. Once that closes, you can run the config macro. You’ll see it walk though the config. I do NOT recommend running the config macro more than once – lest you end up with a completely mangled config. It takes a minute or so to run. Once it’s done, you can open WireShark Legacy and use it. Once you start a trace, you should immediately be able to see the added columns:

ports

Added columns in WireShark. Click for a larger version.

If you wander through the config menus, you’ll see the other settings as well. The v2.x WireShark application that is also installed when you install WireShark is configured somewhat differently, and I’ll address that in the future. Right now, I’m not aware that it provides any added benefit for Skype for Business/Lync admins anyways. But really, WireShark, would it kill you to use an XML file for your config?! Or registry values? If you have some specific config settings you use for WireShark, pass them along!

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Downloads

WireShark v2.1.10 – 10-22-2017 – WireShark_2.2.10-install.zip

WireShark v2.2.9 – 09-04-2017 – WireShark_2.2.9-install.zip

WireShark v2.2.7 – 06-01-2017 – Wireshark_2.2.7-install.zip

WireShark v2.2.6 – 04-12-2017 – Wireshark_2.2.6-install.zip

WireShark v2.2.5 – 03-06-2017 – Wireshark_2.2.5-install.zip

WireShark v2.2.4 – 01-31-2017 – Wireshark_2.2.4-install.zip

WireShark v2.2.3 – 12-23-2016 – Wireshark_2.2.3-install.zip

WireShark v2.2.2. – 11-24-2016 – WireShark_2.2.2-install.zip

WireShark v2.2.1 – 10-07-2016 – WireShark_2.2.1-install.zip

Changelog

See the changelog for information on what’s changed/included in each version.

Writing a Book – A Labor of Love

October 5th, 2016 1 comment

book-coverAny tech types who’ve written tech books can attest to the fact that it’s a LOT of work. And this one was no different. Skype for Business is a very dynamic product, with features being added and updated on a continuing basis. Fortunately, I had the chance to work with some great tech luminaries – people far smarter than me, for Skype for Business Unleashed. That includes Phil Sharp, Rui Maximo, and Alex Lewis. But don’t let the fact that there are four names on the cover fool you. Plenty of others work behind the scenes, including contributing authors, editors, and publisher staff. I can’t possibly name them all, but I would like to point out a few. Stale Hansen stepped up and wrote a killer chapter on the VDI components of Skype for Business, while John Cook handled, what else, the Mac client chapter. Tom Morgan, one of Modality Systems’ ace developers, wrote on Developing Skype for Business Solutions. Former colleagues Tom Arbuthnot and Iain Smith also contributed. Even ‘The Hoff’ himself, Ken Lasko, added some great info. And to keep us all true to the product, Tim Harrington served as the tech editor. Jamie Stark, a beloved Program Manager in the Skype product group at Microsoft, wrote a killer forward.

During the project, several events occurred that seemed to derail the project. The publisher, Pearson, eliminated 4000 staff in a corporate downsizing. This was also around the time that Microsoft Press also underwent a significant restructuring. The project was in doubt for a while, but Pearson came back, committed to getting the book on to the shelves. Our normal full time gigs, family lives, and other interests also came into play. And unfortunately, someone involved in the book suffered a tragic loss. All of these caused the project timeline to slip. And during this time, the product group kept working on the product. Each time a Cumulative Update was released, we would have to review what had already been written to verify it still was valid, including details, screen shots, PowerShell commands, and more.

So why write this book? We certainly aren’t getting rich doing it. In fact, we’d all likely agree that you can’t survive on writing books at this pace. And time spent away from family and friends, and other interests can be tough. But seeing it on the shelf is rewarding on so many levels. It’s great to add the publication to your resume, LinkedIn profile, and more. Name recognition is always nice. But more importantly, getting the knowledge and experience into a format that can be beneficial to others is extremely personally rewarding to me. Is every little tidbit in there? Of course not. The book is 1100 pages. Decisions were made on how much space we could to allocate to each topic. Some chapters could be exponentially larger. But we tried to touch on the important stuff. Enough to get an environment properly designed, build, configured, and administered. And I think we did pretty well in that regard. And of course, as soon as we turned in the final edits, new features were released by the product group.

Books don’t sell unless people know about them. So we don our marketing hats and get on LinkedIn, Twitter, Facebook, blogs, and other online resources and let the world know it’s out there. Modality Systems was generous enough to put together a book signing event at Microsoft Ignite, and gave away some signed copies, as well. Twitter followers even started sending in pictures of where the book had been sighted, including the Microsoft Conference Store, MIT, and more. A signed copy even made its way to Gurdeep Pall‘s desk. Gurdeep is the Corporate Vice President of the Skype business unit at Microsoft, and he tweeted a selfie of himself holding the book. As I write this article, the book is the highest ranked Skype for Business book on Amazon. And that’s no easy task, as the other books were also written by some other top notch nerds like us.

cth_vttw8aij5ka-jpg-large

Book signing event at Microsoft Ignite 2016. From left to right: Stale Hansen, Phil Sharp, me, Rui Maximo, and Tom Morgan.

I again want to thank everyone involved. It would not have been possible without them. I’d also like to thank the entire Product Group, as well as the Skype for Business MVPs. Both of these groups were instrumental in answering questions that popped up throughout this process.

I hope you enjoy the book, and welcome any comments or concerns.

One Liner: Add Trusted Root Cert Authorities to Edge Servers

September 19th, 2015 4 comments

Chris Hayward (@WeakestLync) wrote a great blog post with a neat & easy way to add trusted root certificates for your edge servers. Of course, everything in Lync and Skype for Business uses certificates, so ensuring you have all of the certificates is crucial for federation with other organizations.

Once I saw Chris’s method, I, of course, thought that PowerShell could do this as well. Voila, a one-liner to do it. This example uses the same list from Chris’s blog post, and suppresses the output so you can use it your provisioning scripts.

'https://comodo.com', 'https://digicert.com', 'https://www.entrust.net', 'https://geotrust.com', 'https://www.globalsign.com', 'https://godaddy.com', 'https://www.symantec.com', 'https://thawte.com', 'https://wisekey.com' | ForEach-Object {$null = Invoke-WebRequest -Uri $_}

This method essentially just cycles through each item in the array, and does a web request for each. As each web request is completed, any new certificates are automatically added to the trusted root cert store. Usually, some of these already exist, so don’t be surprised if the total certificate count doesn’t increase by the same number of items in the array.

Script: Install-OfficeWebAppsLanguagePacks.ps1 – Easier Installation of Selected Language Packs

March 7th, 2015 No comments

PowerShell-logo-128x84Description

I was working with a global customer lately who has datacenters in various global regions (as most global orgs do). The customer had not decided, and basically, hadn’t even thought about what language packs to install on their Office Web Apps Servers (OWAS). I suggested that there are 49 language packs including the English pack that I install by default on every OWAS server. Those languages are:

Azeri (Latin)
Basque
Bosnian (Latin)
Bulgarian
Catalan
Chinese (Simplified)
Chinese (Traditional)
Croatian
Czech
Danish
Dari
Dutch
English
Estonian
Finnish
French
Galician
German
Greek
Hebrew
Hindi
Hungarian
Indonesian
Irish – Ireland
Italian
Japanese
Kazakh
Korean
Latvian
Lithuanian
Macedonian (FYROM)
Malay (Malaysia)
Norwegian (Bokmal)
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Romanian
Russian
Serbian (Cyrillic)
Serbian (Latin)
Slovak
Slovenian
Spanish
Swedish
Thai
Turkish
Ukranian
Vietnamese
Welsh

The customer decided on which language packs to install.

If you’ve ever tried to install these, you know you go to the language pack download page, and pick your desired language. When the next page comes up, you notice that it’s in the language of the desired language pack. You hope you’re clicking on the right link, download the file, then run the installer, which is mostly in the desired language, and go from there. It can be somewhat confusing, but extremely repetitive – especially if you’re installing a lot of language packs. It got me thinking that this was an area ripe for automation (what area isn’t?).

Well, as I’ve mentioned on this blog before, I’m lazy (as most coders are). So I wrote this script to make my life easier, and as a result, you gain from it. Here’s what the script does:

  1. Detects which (if any) language packs are installed on the local machines. This is accomplished by looking for the correct GUID in the Uninstall branch of the registry.
  2. Displays a grid list of the language packs that are available and not already installed on the machine (see image below). You can select one or more language packs to install and click “Ok”.
  3. The script will download the language pack(s)
  4. It will mount (if they are an .img file), or extract (if an .exe).
  5. It will silently install the language pack
  6. It will clean up after itself (unmount or clean up extracted files)

Here is the selection list presented. Notice that English is not in the list as that language pack is already installed.

OWAS language pack selection

Once installation is completed, you’re left with your language packs installed and a nice little log file.

OWAS post installation

Extract the files to any folder. The script and the .csv file MUST be in the same folder. Run it by calling Install-OWASLanguagePack.ps1 and it will default to using the following path structure (which it will create if it doesn’t already exist):

Path Purpose 
c:\_Install Root working folder. Can be changed using -TargetFolder when calling the script.
c:\_Install\logs Log files from the script are stored here
c:\_Install\OWASLanguagePacks Downloaded language pack files are stored here. Folder name can be changed using -OWASLanguagePackFolder. Language packs are placed in sub folders of this folder. The sub folders match the language of the language pack.

A little bit of a rant. I *REALLY* wish the language packs were an MSI file that supported silent install instead of an .img file that must be mounted or an .exe that must be extracted, and then each called with complex syntax.

Syntax

Install-OWASLanguagePacks.ps1 [[-TargetFolder]][[-OWASLanguagePackFolder]] [-WhatIf] [-Confirm] [-IncludeTotalCount] [-Skip] [-First][<commonparameters>]

Installation

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.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Assumptions

None

Download

v1.0 – 03-07-2015 – Install-OWASLanguagePacks.v1.0.zip

Changelog

See the changelog for information on what’s changed/included in each version.

One Liner: Set-TaskbarGrouping – Configure Desktop Taskbar Grouping

February 18th, 2015 No comments

In One Liner: Configuring Shutdown Tracker in Windows Server I mentioned that it’s often preferable to quickly configure some server settings when building servers. As a consultant, I like to set up my server profile when building servers in a manner that’s efficient and convenient for me. One thing that drives me completely insane is the default taskbar group setting. Taskbar grouping is how Windows groups common items together on the taskbar. By default, all similar items are lumped together, i.e. all Internet Explorer windows. So to go back to an IE window could take two mouse clicks instead of one. Let’s take a look at streamlining this configuration for Server 2012 and Server 2012 R2.

Taskbar grouping has three settings. The default “always combine” mentioned previously, “combine when taskbar full” which doesn’t start grouping until there are enough items to fill the taskbar, and my favorite, “never combine”. As you can probably guess, “never combine” doesn’t group taskbar items at all. Since I usually don’t have more than 4 or 5 apps open when building servers, this suits my style.

Just like the shutdown tracker, this setting is stored in the registry. A one liner for this would look like this:

Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name TaskbarGlomLevel -Value 0

0 is the value for “always combine”, 1 for “combine when taskbar full” and 2 for “never combine”. In order for the setting to take effect, one of two things has to happen. Either log off/restart, or restart the explorer.exe process. The later can be performed by running the following:

Stop-Process -ProcessName explorer -force

If you’d like to use a function for this, we can use something like the code below in our server build script:

function Set-TaskbarGrouping {
    [CmdletBinding(SupportsShouldProcess, SupportsPaging, DefaultParameterSetName = 'NeverCombine')]
    param(
        # Always combines similar shortcuts into groups
        [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'AlwaysCombine')]        
        [switch] $AlwaysCombine,
        
        # Combines similar shortcuts into groups only when the taskbar is full
        [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'CombineWhenTaskbarFull')]
        [switch] $CombineWhenTaskbarFull,
        
        # Never combines similar shortcuts into groups
        [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'NeverCombine')]
        [switch] $NeverCombine,
        
        # Restarts explorer in order for the grouping setting to immediately take effect. If not specified, the change will take effect after the computer is restarted
        [switch] $NoReboot
    )
    switch ($PsCmdlet.ParameterSetName) {
        'AlwaysCombine' {
            Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name TaskbarGlomLevel -Value 0
        }
        'CombineWhenTaskbarFull' {
            Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name TaskbarGlomLevel -Value 1
        }
        'NeverCombine' {
            Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name TaskbarGlomLevel -Value 2
        }
    }
    if ($NoReboot){
        Stop-Process -Name explorer -Force
    }else{
        Write-Verbose -Message 'Change will take effect after the computer is restarted'
    }
} # end function Set-TaskbarGrouping

I use parameter set names so that only one of the parameters can be used when the function is called. The three options are “NeverCombine” “CombineWhenTaskbarFull” and “AlwaysCombine”. But since I define the parameters in a param block, you get tab completion. So no need to even remember the options. For example:

Set-TaskbarGrouping -NeverCombine

If you also include the -NoReboot parameter when calling the function, it will restart explorer.exe to avoid the need to log off/restart.

One Liner: Configuring Shutdown Tracker in Windows Server

February 17th, 2015 1 comment

When you spend time building servers, there are often some minor tweaks that you use to make life easier. In many environments, Group Policy Objects (GPOs) are used to configure these settings. But in a lot of environments, that’s not the case. If you build a lot of servers, you may have some scripts to help streamline the process. I often see this being the case among consultants who are engaged to deploy a solution. If you’ve followed my blog for a while, you know that’s what I do. And I look for many ways to streamline the deployment. Many solutions I write are all about the actual deployment, whereas this particular post is about the working environment I’ll be spending time in.

One thing that always drives me nuts is the Shutdown Tracker. That’s the little dialog box that pops up when you want to restart or shutdown a server. You’re presented with a prompt to pick the reason why you’re restarting or shutting down. While this can certainly have its place in an enterprise environment, it’s not generally needed during a deployment. And it’s not likely needed in a lab environment where you might be testing various configurations and restarting often. So let’s gag that annoying prompt.

To disable Shutdown Tracker, open an elevated PowerShell prompt and enter the following one line:

Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability" -Name ShutdownReasonOn -Value 0

This will take care of the problem. If you later want to enable the Shutdown Tracker, you can simply run it again, specifying a 1 for the value.

We can make this a little more flexible by creating a function to let us enable or disable as needed.

function Set-ShutdownTracker {
	[CmdletBinding(SupportsShouldProcess = $True, SupportsPaging = $True, DefaultParameterSetName = "disabled")]
	param(
		# Disable the shutdown tracker
		[Parameter(ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True, ParameterSetName = "disabled")]
		[switch] $Disabled,
		
		# Enable the shutdown tracker
		[Parameter(ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True, ParameterSetName = "enabled")]
		[switch] $Enabled
	)
	switch ($PsCmdlet.ParameterSetName) {
		"enabled" {
			Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability" -Name ShutdownReasonOn -Value 1
		}
		"disabled" {
			Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Reliability" -Name ShutdownReasonOn -Value 0
		}
	}
} # end function Set-ShutdownTracker

And the script can be called with either the -Enabled or -Disabled parameters.

Adding the one liners or the function to your deployment scripts might make life a little easier.

Function: Set-PowerPlan – Adjust The Power Plan of a Server

February 25th, 2014 1 comment

Description

Just something I worked up based on a suggestion by someone. This will change the power plan of the machine it’s run on. This can be critical if you want to ensure that the machine doesn’t go to sleep while an extended process is running. Simply run the function with the desired power plan and the change is immediate. For example:

Set-PowerPlan "High Performance"

The three power plans you can choose from are “high performance”, “balanced”, and Power Saver. That’s all there is to it.

function Set-PowerPlan {
	[CmdletBinding(SupportsShouldProcess = $True)]
	param (
		[ValidateSet("High performance", "Balanced", "Power saver")]
		[ValidateNotNullOrEmpty()]
		[string] $PreferredPlan = "High Performance"
	)
	 
	Write-Verbose "Setting power plan to `"$PreferredPlan`""
	$guid = (Get-WmiObject -Class Win32_PowerPlan -Namespace root\cimv2\power -Filter "ElementName='$PreferredPlan'").InstanceID.ToString()
	$regex = [regex]"{(.*?)}$"
	$plan = $regex.Match($guid).groups[1].value 
	
	powercfg -S $plan
	$Output = "Power plan set to "
	$Output += "`"" + ((Get-WmiObject -Class Win32_PowerPlan -Namespace root\cimv2\power -Filter "IsActive='$True'").ElementName) + "`""
	Write-Verbose $Output
}

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Categories: PowerShell Tags: ,

Script: New-CsLyncRoomSystem.ps1 – Easily Deploy Lync Room Systems

January 28th, 2014 4 comments

Description

One of the really cool features of Lync Server 2013 is the Lync Room System. LRS is comprised of a single or dual screen system, video camera, and control unit. This system provides for a rich conferencing experience by providing HD video, touch screens with white-boarding, audio & video inputs, and more. For more information on Lync Room system, see the Product Group’s blog post. To see the systems optimized for Lync, see the catalog.

Deploying a Lync Room System involves several steps, and is outlined (albeit poorly) in the LRS Deployment Guide. I say poorly because from a PowerShell perspective, the 10 steps outlined can be combined down to about 6. Some are Exchange related, some are Active Directory related, and some are Lync related.

What I’ve done is to automate & streamline the process, add a ton of error checking, optimization, and validation. Instead of picking an Exchange server, the script will automatically find and connect to Exchange. It then performs the following tasks:

  1. Create an Exchange mailbox configured as a room resource. Additionally, the description is defined, and the company name on the account is configured (see http://www.ucunleashed.com/2266 for why this is important). The room account is enabled. You’re prompted for a password for the account, and that password must conform to the organizations’ password policy for complexity. If the mailbox already exists, which would be common in most scenarios, the script will handle it gracefully, ensuring it’s configured properly.
  2. The mailtip for the account is defined. It merely reminds users to make meeting requests a Lync meeting.
  3. Set calendar processing to AutoAccept so that when the room account is added to meetings, it will automatically accept the request.
  4. The AD account is enabled
  5. The Lync Meeting room is created, and uses the email address for the SIP address. This is important to avoid Exchange Web Services (EWS) issues.
  6. If a LineURI is defined, the meeting room is enterprise voice enabled. LineURI should be specified in E.164 format.

Any other configuration, such as conferencing policies, etc., can be set after the script runs. I’ve used this script to deploy a 70″ dual display SMART Room System.

See the assumptions section below for more info.

Syntax

New-CsLyncRoomSystem.ps1 [[-Alias] ] [[-Name] ] [[-UPN] ] [[-SamAccountName] ] [[-RegistrarPool] ] [[-LineURI] ] [[-CompanyName] ] [[-ResponseText] ] [[-ResourceCapacity] ] [-DeleteSubject ] [[-EnableResponseDetails] ] [-WhatIf ] [-Confirm ] []

example

New-CsLyncRoomSystem.ps1 -Alias nycconfroom -Name "New York City Conference Room" -Upn "nycconfroom@contoso.com" -RegistrarPool "frontendpool.contoso.com"

The SamAccountName only needs to specified if it needs to be different than the alias.

Installation

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.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Assumptions

  • The SIP address is set to match the SMTP address. This is to avoid issues where the two don’t match and Exchange Web Services (EWS) calls fail.
  • Exchange 2010 or 2013 exists in the environment
  • The user running the script has the appropriate rights in Exchange (Recipient Management or higher) and Lync (RTCUniversalUserAdmin or higher)
  • The machine that the script runs on has both the Lync and Active Directory modules installed.

Download

v1.2 – 06-10-2014 – New-CsLyncRoomSystem.v1.2.zip

v1.1 – 02-08-2014 – New-CsLyncRoomSystem.v1.1.zip

v1.0 – 01-28-2014 – New-CsLyncRoomSystem.v1.0.zip

Changelog

See the changelog for information on what’s changed/included in each version.