Learning about the PowerShell Get-WindowsFeature command is a good introduction to the time-savings that Powershell scripting can bring to server admins. Credit: Shutterstock / Shashkin 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. Tim Ferrill 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. Tim Ferrill 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.) Tim Ferrill 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 . (The Get-Help output for the Get-Process cmdlet would show the format , 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. Getting an extra level of detail from Get-WindowsFeature 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. Tim Ferrill 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. Related content news analysis Cisco, AWS strengthen ties between cloud-management products Combining insights from Cisco ThousandEyes and AWS into a single view can dramatically reduce problem identification and resolution time, the vendors say. By Michael Cooney Nov 28, 2023 4 mins Network Management Software Cloud Computing opinion Is anything useful happening in network management? Enterprises see the potential for AI to benefit network management, but progress so far is limited by AI’s ability to work with company-specific network data and the range of devices that AI can see. By Tom Nolle Nov 28, 2023 7 mins Generative AI Network Management Software brandpost Sponsored by HPE Aruba Networking SASE, security, and the future of enterprise networks By Adam Foss, VicePresident Pre-sales Consulting, HPE Aruba Networking Nov 28, 2023 4 mins SASE news AWS launches Cost Optimization Hub to help curb cloud expenses At its ongoing re:Invent 2023 conference, the cloud service provider introduced several new and free updates that are expected to help enterprises optimize their AWS costs. By Anirban Ghoshal Nov 28, 2023 3 mins Amazon re:Invent Podcasts Videos Resources Events NEWSLETTERS Newsletter Promo Module Test Description for newsletter promo module. Please enter a valid email address Subscribe