4. Exploring Experimental Features in PowerShell 7
PowerShell 7 marks the first long-term servicing release to support experimental features, though PowerShell Core 6.1 introduced them to the community. In this chapter, you learn about PowerShell experimental features along with their basic command usage. Additionally, you learn how to include them in your code and module manifest.
As a bonus, this chapter includes a few ideas on how to collect metrics, which can be valuable in determining the success and adoption rate of experimental features.
Experimental Features Definition
New features or behavior that are not production-ready are considered experimental.
For example, the new ConciseView for $ErrorView in PowerShell 7 was initially implemented as an experimental feature.
Users can choose to opt-in for an experimental feature on an individual basis. Administrators can choose to opt-in at the system level.
Using the built-in support for experimental features for your module, you can provide users with alternate commands, parameters, or behaviors as required.
Experimental Feature Commands
The following commands allow you to discover, enable, and disable experimental features.
Get-ExperimentalFeature
The command Get-ExperimentalFeature displays a list of experimental features discovered on the system at the beginning of the PowerShell session.
These features can come from the PowerShell engine itself or modules.
The output of this command is an object with the properties Name, Enabled, Source, and Description.
The Source property shows where the experimental feature is defined.
Experimental features can be specific to an Operating System as you can see in the following table.
| Name | Source | Operating System |
|---|---|---|
| PSCommandNotFoundSuggestion | PSEngine | All |
| PSImplicitRemotingBatching | PSEngine | All |
| PSNullConditionalOperators | PSEngine | All |
| PSUnixFileStat | PSEngine | Linux |
| Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace | Module | All |
| PSDesiredStateConfiguration.InvokeDscResource | Module | All |
Enable-ExperimentalFeature
The Enable-ExperimentalFeature command turns on one or more experimental features for the current user or all users.
Enabling a feature adds it to an array in the ExperimentalFeatures key in the PowerShell configuration file, $PSHOME\powershell.config.json.
If you do not specify a Scope, it defaults to CurrentUser.
You can turn on all experimental features in one line, as shown below.
Get-ExperimentalFeature | Enable-ExperimentalFeature -Scope AllUsers
$PSHOME\powershell.config.json After Enabling Experimental Features for All Users on Windows{
"WindowsPowerShellCompatibilityModuleDenyList": [
"PSScheduledJob",
"BestPractices",
"UpdateServices"
],
"Microsoft.PowerShell:ExecutionPolicy":"RemoteSigned",
"ExperimentalFeatures": [
"PSCommandNotFoundSuggestion",
"PSImplicitRemotingBatching",
"PSNullConditionalOperators",
"Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace",
"PSDesiredStateConfiguration.InvokeDscResource"
]
}
Disable-ExperimentalFeature
The Disable-ExperimentalFeature command turns off one or more experimental features.
PSNullConditionalOperators for All UsersDisable-ExperimentalFeature -Name PSNullConditionalOperators -Scope AllUsers
As with enabling, when you disable one or more features, you must close all PowerShell sessions and start a new session.
Disabling the feature removes its entry from the enabled feature list in the configuration file for the given scope.
The ExperimentalFeatures key remains even if you disable all experimental features.
Adding Experimental Features to Your Module
You can add multiple experimental commands, parameters, or behaviors to your module.
First, name each experimental feature and prepare a description for it.
Next, add a new entry for each in the PrivateData.PSData section in the module manifest.
After updating the module manifest, you can then add experimental behavior using one or both of the following methods.
- Add the
Experimentalattribute and the appropriateExperimentaction where needed. - Include experimental feature behavior directly in your code.
Experimental Feature Name and Description
Experimental feature names must be in the format of ModuleName.FeatureName.
Assume that you want to include an experimental feature for the module PSTemperature to support the Rankine temperature scale.
A valid name could be PSTemperature.SupportRankine.
The name could include very short descriptive text that identifies where you include the experimental feature in your module.
DemoModule.FunctionShowHelloWorld could indicate that the function Show-HelloWorld is experimental or that it has an experimental counterpart.
The name can include multiple periods if your module name includes periods. For instance, the name
Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace
is valid as Microsoft.PowerShell.Utility is the module’s name.
In addition to the name, you must write a short description of the experimental feature that you will include in the module manifest. This description should provide the user with information about the experimental behavior and, potentially, how to access it once enabled.
Module Manifest
In the module manifest file, typically named ModuleName.psd1, you must add a new entry to the section PrivateData.PSData.
The entry is an array of hashtables, with each hashtable being a specific experimental feature.
The hashtable must include Name and Description keys.
PrivateData = @{
PSData = @{
ExperimentalFeatures = @(
@{
Name = 'PSTemperature.SupportRankine'
Description = 'Support Rankine Temperature Scale'
}
)
}
}
You can include more than one experimental feature in your module. Each one must have a unique name.
PrivateData = @{
PSData = @{
ExperimentalFeatures = @(
@{
Name = 'DemoModule.ExperimentalFunction'
Description = 'Demo of Experimental Function'
},
@{
Name = 'DemoModule.ExpParameter'
Description = 'Demo of Experimental Parameter'
}
)
}
}
Once you have added the experimental feature(s) to the module manifest file, you should test its validity by using the Test-ModuleManifest command.
Test-ModuleManifest -Path 'PSTemperature.psd1'
If an experimental feature name does not meet the correct format, Test-ModuleManifest will fail.
Test-ModuleManifest Error Due to Invalid Experimental Feature NameTest-ModuleManifest:
One or more invalid experimental feature names found: PSDemoExpFeature.
A module experimental feature name should follow this convention:
'ModuleName.FeatureName'.
Experimental Attribute and Experiment Action
You must include the Experimental attribute and an appropriate Experiment action to a function or cmdlet declaration or a parameter declaration.
The Experimental Attribute is a decorator much like the CmdletBinding Attribute and the Parameter Attribute.
Decorators, which are the embodiment of the decorator design pattern, add behaviors to an object.
For instance, including [CmdletBinding()] at the beginning of a function or a [Parameter()] attribute for any parameter, it becomes an advanced function which enables it to inherit common parameters and take advantage of the pipeline.
Each of these decorators has parameters that change how the script, function, or parameter behaves.
Add the following code to your function, cmdlet, or parameter to enable the experimental behavior.
[Experimental(NameOfExperimentalFeature, ExperimentAction)]
In a previous section, you learned about the naming scheme for NameOfExperimentalFeature.
The ExperimentAction is an enum with values of Hide or Show.
-
Hidedisables specific behavior with the experimental feature state disabled—this is the default state. -
Showenables specific behavior with the experimental feature state enabled.
For functions, you can use either the text or reference the enum directly with
[ExperimentAction]::Hide or [ExperimentAction]::Show.
For cmdlets, written in C#, you must use ExperimentAction.Hide or ExperimentAction.Show.
When used correctly, they can enforce mutual exclusivity between different versions of a command or parameter.
ExperimentActionfunction Get-LoremIpsum {
[CmdletBinding()]
param(
[Experimental('DemoModule.ExpParameter', [ExperimentAction]::Hide)]
[switch]$Display,
[Experimental('DemoModule.ExpParameter', [ExperimentAction]::Show)]
[switch]$Show
)
if ($Display) {
$Lorem = @()
$Lorem += 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
$Lorem += 'Sed varius mi erat, in laoreet nibh eleifend eget.'
$Lorem += 'Phasellus odio diam, tincidunt rhoncus massa in, feugiat'
$Lorem += 'iaculis mauris. Nulla ornare enim et semper tincidunt.'
$Lorem += 'Maecenas ac tempor quam, in scelerisque lorem.'
$Lorem -join ' ' | Write-Output
}
if ($Show) {
'The quick brown fox jumps over the lazy dog.' | Write-Output
}
}
When DemoModule.ExpParameter is not enabled, the function Get-LoremIpsum will have the Display switch parameter (along with the common parameters).
The Show switch parameter replaces the Display parameter when the experimental feature is enabled.
# disabled
Get-LoremIpsum -Display
# enabled
Get-LoremIpsum -Show
Similarly, you can include two functions that are mutually exclusive based on the state of the experimental feature.
# This function is exported when the experimental feature is disabled.
# This is the default.
function Show-HelloWorld {
[Experimental('DemoModule.ExperimentalFunction', [ExperimentAction]::Hide)]
[CmdletBinding()]
param()
'PowerShell 7 is shipping soon!' | Write-Host -ForegroundColor Green
}
# This function is exported when the experimental feature is enabled.
function Show-HelloWorld {
[Experimental('DemoModule.ExperimentalFunction', [ExperimentAction]::Show)]
[CmdletBinding()]
param()
'PowerShell 7 is here!' | Write-Host -ForegroundColor Yellow
}
The command names need not be the same.
However, be sure to include all exportable commands, regardless of their experimental feature state in the module manifest FunctionsToExport or CmdletsToExport entries.
Include Experimental Feature Behavior Inside a Code Block
You can include additional behavior not tied directly to a function, cmdlet, or parameter.
Once you have named your experimental feature and updated the module manifest, use the static IsEnabled() method of the System.Management.Automation.ExperimentalFeature class.
if ([ExperimentalFeature]::IsEnabled('DemoModule.ExperimentalBehavior')) {
# code specific to experimental feature
}
When writing Pester tests for your experimental code, you can check the state of an experimental feature similarly.
Collecting Metrics
Whether your module includes experimental features or not, a good practice would be to understand users’ experience with it. Metrics on the frequency of use, environment configuration, and generated exceptions or errors are prime candidates for collection.
The collection process, sometimes called telemetry, can look very different, given the target audience and its size. Target audiences can include colleagues in your department, employees within your company, employees or contractors in other companies, the public at large, or any combination of these.
For experimental features, the collected metrics should provide the developer, or development team, with enough information to decide on the next step for the feature.
Questions that metrics should help answer:
- Should the experimental feature be graduated to stable and be included as a regular feature in an upcoming release?
- What errors generated will be addressed?
- Given a low adoption rate of the experimental feature, should it be removed entirely from the module?
- Can the experimental feature be redesigned to better align with user expectations?
Conduct a Survey
For small-to-midsize target audiences, a simple survey may provide sufficient data. The survey could be in the form of directly asking the handful of users if they have used the experimental feature and, if so, what did they like or dislike about it. Alternatively, the survey could be an email to the users, or it could be implemented via a hosted survey service.
The data you collect in your surveys would need to be collated and presented in a report. The more data points included in your report, the longer creating the report will take. Though you may collect more metrics than you use, the report should focus only on the data points that will help make the module better.
Send Metrics to a Local Repository
For midsize target audiences, a simple survey would generate considerable overhead consuming valuable time you could spend on writing code. You can shift this overhead to the development of an automated collection of metrics to a local repository, whether a text file on a network share or tables in a relational database.
Once you have collected the metrics, you can then generate the metrics report using this data.
Send Metrics to a Cloud Service
Gathering telemetry requires adequate infrastructure and appropriate access. Unless your team has time and resources to handle configuration and access requests to send telemetry data to a local repository, you should consider using a cloud-hosted solution, ideal for most mid-to-large sized target audiences.
In the software development realm, Application Performance Management/Monitoring (APM) solutions include telemetry. Microsoft offers Azure Application Insights, while Amazon Web Services (AWS) offers several third-party APM solutions in their AWS Marketplace. Many other vendors offer APM solutions, as well.
Cost and ease of use would be two factors that you must take into account when selecting an APM solution. Ultimately, it will be up to your company, or you, to determine which solution is the best for your particular situation.
Additional Information
Learn more about Experimental Features by reviewing the contextual help, Get-Help about_Experimental_Features or each command’s help, Get-Help Get-ExperimentalFeature, locally or online using the -Online switch.
Be sure to Update-Help to get the latest help links.
To learn how the PowerShell Team addressed the original proposal for experimental features, visit the finalized Request for Comments (RFC) for Experimental Features RFC0029.
Sample Modules
This chapter includes examples from two sample modules, one a script module and the other a binary module. You can find them in this book’s Extras GitHub repo. Once there, navigate to Volume 3 and look for this chapter’s name on the list.
Summary
Experimental feature support in PowerShell 7 provides users the choice to opt-in to alternate, not-widely-tested behaviors. It includes three commands that allow you to discover and enable or disable experimental features. PowerShell, itself, delivers several experimental features via the engine and two others with included modules.
As a PowerShell developer, you can include experimental features with your modules, as well.
After updating your module’s manifest with the name and description of your new experimental feature, you can include the Experimental attribute and appropriate Experiment action, as often as needed.
You can also include the experimental code within an if statement that validates whether the feature is enabled before exposing the new behavior.
Lastly, you learned about collecting metrics that can help you in determining whether to graduate an experimental feature or abandon it.