We have many different ways to build our servers so they are, and stay, the same: Desired State Configuration, is one way. In case you’re not there yet (and, I’m not, entirely), you may need to compare the roles and features between your servers to check for any differences.
In this first example, we’ll create two variables to store the installed roles and features of two different servers. Keep in mind that I’m working from a Windows 8.1 client, and two Server 2012 R2 servers. You’ll need to make sure you’re using these versions, as the Get-WindowsFeature cmdlet in 8.1 returns an error when trying to connect to a 2008 R2 server. As well, some of the Roles and Features’ names have changed. Therefore, I decided to only focus on 2012 R2.
PS> $DC01 = Get-WindowsFeature -Computer DC01 | Where-Object InstallState -eq Installed PS> $NewDC = Get-WindowsFeature -Computer NewDC | Where-Object InstallState -eq Installed
Now that we have our populated variables, we can do our comparison between the two on their Name properties.
PS> Compare-Object -ReferenceObject $DC01.Name -DifferenceObject $NewDC.Name InputObject SideIndicator ----------- ------------- AD-Domain-Services <= DNS <= RSAT-DNS-Server <= RSAT-File-Services <= RSAT-DFS-Mgmt-Con <=
If you want to view the roles and features that are installed on both servers, then include the -IncludeEqual parameter on Compare-Object, such as in the example below.
PS> Compare-Object -ReferenceObject $DC01.Name -DifferenceObject $NewDC.Name -IncludeEqual InputObject SideIndicator ----------- ------------- NET-Framework-Features == NET-Framework-Core == NET-Framework-45-Features == NET-Framework-45-Core == NET-WCF-Services45 == NET-WCF-TCP-PortSharing45 == AD-Domain-Services <= DNS <= RSAT-DNS-Server <= RSAT-File-Services <= RSAT-DFS-Mgmt-Con <=
What might not be immediately evident for some, is that we could have skipped setting the first two variables and only used a single Compare-Object command. It can retrieve the information from each server and then compare it, at nearly the same time. We’ve remove the -IncludeEqual parameter is this example.
Compare-Object -ReferenceObject ((Get-WindowsFeature -ComputerName DC01 | Where-Object InstallState -eq Installed).Name) -DifferenceObject ((Get-WindowsFeature -ComputerName NewDC | Where-Object InstallState -eq Installed).Name) InputObject SideIndicator ----------- ------------- AD-Domain-Services <= DNS <= RSAT-DNS-Server <= RSAT-File-Services <= RSAT-DFS-Mgmt-Con <=
Based on these results, and the ones further above, we have determined that our reference computer, DC01, has five additional packages installed.
If you need to compare Windows 2008 R2 to Server 2012 (R2) you’ll want to modify your request slightly to account for the differences between the “installed” properly and the “InstallState” property.
Some other things like the actual features changed names so it isn’t perfect, but it should be possible to create a mapping document (Microsoft may already have one). Sadly this doesn’t work via a remote call as mentioned in the article, but from the servers you can run the below commands to at least dump the text feature list.
$gwf2012R2 = Get-WindowsFeature | where InstallState -eq Installed | sort -Property DisplayName |ft -auto DisplayName,Name
$gwf2008R2 = Get-WindowsFeature | where Installed -eq True | sort -property displayname | ft DisplayName,Name