Deploying Windows Servers can be a pain, even when you’ve got a templating system. How do I know that the template matches my current requirements? What do I know now that I didn’t know when that template was built? How do I easily manage the one-off differences between that template and the needs of this new system?
It’s even worse when you don’t have a template system or have overriding reasons to not to use one. You’re stuck building each new server from scratch, checking those boxes like it’s your first time.
Or, are you?
If you’re looking for a fast way to save or copy the list of selected Windows Server features and roles and apply them to a new system, PowerShell can easily help.
Duplicate Feature Selections from Another Server
Let’s say that you already have a server and you want the new one to use the same features. Web (IIS) servers that share a farm are a fantastic example. Vendor application servers with a complicated requirements list are another. On the new system, execute the following:
Get-WindowsFeature -ComputerName <source-system> | ? Installed | Add-WindowsFeature
Get-WindowsFeature -ComputerName <source-system> | ? Installed -ne $true | Remove-WindowsFeature
If you’re new to PowerShell, the question mark (?) is an alias for the Where-Object cmdlet. It evaluates a statement for a true or false condition. So, the first part of each line loads all of the Windows features from the source system and passes them across the pipe to the second part. The second part of each line takes that input and checks each item to see whether or not the property named “Installed” is set to true. If the item matches the condition check, it is passed across the pipe to the last part of the line. The final part then carries out its action on that item.
This isn’t the most efficient way to perform this task because it retrieves the list of Windows features from the source system two times and processes it two times. However, it’s very easy to type and to remember. It also allows you to easily skip either process as needed.
Storing and Applying Installed Feature Selections
The above will quickly get you started with a new server. But what if you want something a bit more permanent? What if you want to be able to keep the settings in the event that you no longer have the original server and won’t be restoring from some sort of backup? What if you’re using servers with different ownership and don’t have permission to access the source system?
Essentially, you need a way to easily store the feature selection for a Windows Server. By “store”, I don’t necessarily mean long-term storage, like a hard disk. I’m referring to a method that allows easy transport from one system to another. For this task, PowerShell natively includes the infinitely useful Export-Clixml and Import-Clixml cmdlets. With these, most anything that can be piped out can be piped right back in, even across time and space.
I’m going to assume that you do want to use permanent storage for my first example.
Get-WindowsFeature | ? Installed | Export-Clixml -Path C:\Source\WebServerInstalledFeatures.xml
The above will store only the currently enabled features. You can then save that file somewhere and use it on another system later:
Import-Clixml -Path \\files\configs\WebServerInstalledFeatures.xml | Add-WindowsFeature
Remember that the above line will work as expected only because the XML file contains only installed features. I like this option because it reduces the likelihood of a mistake. If you were to export all feature states and then forget to filter against the Installed property, then you would inadvertently attempt to enable all possible features on the target system!
You can still use the installed-only list to remove unwanted features (like SMB 1.0):
Get-WindowsFeature | ? Name -notin (Import-Clixml -Path \\files\configs\WebServerInstalledFeatures.xml).Name | Remove-WindowsFeature
That’s a fair bit of typing, but it’s a safe approach that helps to reduce the likelihood of mistakes.
Storing All Feature Selections
If you’d rather store the entire configuration, you can do so very easily:
Get-WindowsFeature | Export-Clixml -Path C:\Source\WebServerFeatures.xml
Remember that this particular file contains every feature, installed or not. The Installed property is present, so you can test against it at import:
Import-Clixml -Path \\files\configs\WebServerFeatures.xml | ? Installed Add-WindowsFeature
Import-Clixml -Path \\files\configs\WebServerFeatures.xml | ? Installed -ne $true | Remove-WindowsFeature
You can also import the feature set into a variable to reduce the number of visits to the network/disk:
$WebServerFeatures = Import-Clixml -Path \\files\configs\WebServerFeatures.xml
$WebServerFeatures | ? Installed | Add-WindowsFeature
$WebServerFeatures | ? Installed -ne $true | Remove-WindowsFeature
These aren’t the only techniques at your disposal for role and feature management on Windows. Desired State Configuration is a logical, powerful choice. You can apply feature selections to offline images and deploy them as templates. These PowerShell techniques are fast and flexible. They are a useful addition to a sysadmin’s toolkit.