- 5 biggest Linux and open-source stories of 2024: From AI arguments to security close calls
- Trump taps Sriram Krishnan for AI advisor role amid strategic shift in tech policy
- Interpol Identifies Over 140 Human Traffickers in New Initiative
- 5 network automation startups to watch
- The State of Security in 2024: The Fortra Experts Take a Look
How PowerShell can find features and roles on Windows servers
The PowerShell Get-WindowsFeature command—or, more properly, cmdlet—can retrieve a list of Windows features, including server roles, that are installed on a server or workstation running Windows, making it a handy tool for server admins.
Learning about it can point up its value and how a broader knowledge of PowerShell commands may lead to more efficient administration of Windows servers.
By default, the output of the Get-WindowsFeature cmdlet provides something of a hierarchical view with individual features having boxes checked or not depending on their installation status. (Click to expand the image at left.) This is great for quickly eyeballing a single server to get an idea of what functions it provides, but as the list contains upwards of 250 roles and features, it starts to lose practicality when you are looking for a specific set of features or want to inventory multiple servers in a single pass.
Fortunately Get-WindowsFeature provides an easy way to focus on specific sets of features. Any text typed immediately after the cmdlet—called a parameter in PowerShell—will be used to search against the feature name and will filter the list of roles and features.
For example, Get-WindowsFeature Hyper-V will return the Hyper-V server role from the list and indicate whether the role is installed or available for installation. If you want to find all Hyper-V-related features, you can add an asterisk for a wildcard search: Get-WindowsFeature Hyper-V*.
Inventory remote servers and offline VMs
To get an overview of the purpose of GetWindowsFeature, you can use the Get-Help cmdlet with GetWindowsFeature as the first parameter. The output provides an overview of what GetWindowsFeature does, the syntax for its use, and any parameters that are available. Adding the -Examples switch:
Get-Help Get-WindowsFeature -Examples
will provide a handful of sample use cases with the necessary parameters and syntax already completed as below; simply copy, paste, and edit the parameters to suit your needs. (A switch is a parameter that doesn’t require any additional input.)
The output at the left identifies a couple of important things about Get-WindowsFeature. First is the -Computername parameter, which is fairly ubiquitous in PowerShell and executes the command against a remote computer rather than the computer with the open PowerShell window. Many cmdlets let you specify multiple computers using this method, but Get-WindowsFeature supports only one as indicated by the -Computername parameter showing a format of <String>. (The Get-Help output for the Get-Process cmdlet would show the format <string[ ]>, which would prompt a list/array of strings. There are ways to work around this limitation, which we’ll get to later.)
Applying this to the earlier example of using Hyper-V as a parameter with Get-WindowsFeature, if you want to check whether any Hyper-V features are installed on a remote server, you could execute
Get-WindowsFeature Hyper-V -ComputerName RemoteServer01
and get an answer fairly quickly. Note that credentials come into play here, so you’ll either need to be running PowerShell as a user with the appropriate permissions on the remote server or you can pass the -Credential parameter to achieve the same result. (Typically, you’d prompt for a new credential and store it in a variable—a unit of memory for storing values—like:
$cred = Get-Credential
and then pass the stored credential to the cmdlet using -Credential $cred.)
The second important thing that Get-Help points out about Get-WindowsFeature is that the -Vhd parameter can have it directly evaluate Virtual Machine (VM) hard drives (specifically VHD or VHDX files used by Hyper-V) without having to bring them online. It’s not something everyone will use, but if you have a library of VHD files used as templates for quickly deploying VMs or even have VMs you only spin up for certain situations, this could be a major win.
If you run Get-WindowsFeature you get results formatted in three columns: Display Name, Name, and Install State. These details provide a starting point for evaluating the makeup of your servers, but there is more detail hidden below the surface if you use the right cmdlet. Again using Hyper-V as an example, check out below how the Select-Object cmdlet expands the view of the output.
The “Name” is the short name of the role or feature, and “DisplayName” is the friendly readable name. In this case, they happen to be the same—Hyper-V.
The Installed and InstallState fields are similar but have some key differences. Installed is a Boolean (True or False) field making it super easy to filter on. For example, a one-liner like:
Get-WindowsFeature | Where-Object Installed
will provide a list of only the roles and features installed on a server.
InstallState has three potential values: Installed, Available, or Removed. The key distinction here is the difference between Available and Removed. Both indicate the feature isn’t currently installed and running, but Available means that the feature is available to be installed directly from the system. Removed means even the installation files have been purged from the system, so to install the feature you need to do so from media.
The next set of fields speaks to how roles and features relate to each other. The DependsOn field references any other features that are required. Parent and SubFeatures fields identify the relationships between features, showing the features that are direct parents of the feature you’re installing or optional sub-components.
Not all roles, and certainly not all features, have Windows services, but some server roles have multiple services that are leveraged to perform their function. Get-WindowsFeature lists these services in the “System Service” field, so you can discover which services are role-based and then check their status to make sure they are running properly.
Invoke-Command to reduce individual queries
Often when using PowerShell to perform bulk actions against a list of systems, you need to perform more than a single task or cmdlet against each system. Microsoft offers a couple of different methods to accomplish this, but here we’ll focus on the Invoke-Command cmdlet. Invoke-Command uses two primary parameters, the first is -Computername (of the variety that accepts more than one value), and the second is -ScriptBlock, which allows you to define a set of commands to be run against the remote systems. Because PowerShell is so consistent in naming and syntax, the code used to query multiple computers for their roles and features is very straightforward:
$features = Invoke-Command -ComputerName ‘srv01’, ‘srv02’, ‘srv03’ -ScriptBlock { Get-WindowsFeature }
Here the full output of the Get-WindowsFeature cmdlet is assigned to the $features variable. This enables analyzing the returned information in multiple ways without having to re-run the cmdlet against remote computers, which would likely result in a bigger performance hit than simply retaining the data in memory for a short time.
One way the data contained in the $features variable can be used is to create a list of installed features:
$features | Where-Object Installed | Format-Table Name, DisplayName, InstallState, PSComputerName
This starts with the $features variable and filters the results to instances where the value of Installed is true then formats the output as a table displaying the specified columns.
Another example is to output installed server roles to a CSV file, which allows for sharing via email or a file store or analysis via Excel. You would start with the $features variable again, limit to installed server roles (not features), and then export to a CSV file using a single line of PowerShell:
$features | Where-Object {$_.Installed -and $_.FeatureType -eq ‘Role’} | Export-CSV ‘C:UsersAdministratorDocumentsServerRoles.csv’
Time spent learning PowerShell can save time
The PowerShell scripting language is undoubtedly one of the more significant contributions Microsoft has made to the data center and to overworked system admins in the last decade. It’s not only robust and implemented with enough ubiquity to be useful across a wide range of Microsoft operating systems and cloud platforms, but it has a consistent, cohesive structure, and a healthy community helping drive best practices and established use cases.
Many system admins have PowerShell on their list of things to learn at some point because it can save time doing daily tasks, but that can be a Catch-22: Saving that time requires an investment of time up-front in order to learn it. Perhaps this introduction provided the push needed to make that leap.
Copyright © 2021 IDG Communications, Inc.