Today, we are releasing the sixth preview of the PowerShell 7.1 release!
Further in this blog post I’ll provide details on some important changes you should be aware of as you starting trying out this preview.
PowerShell 7.1 Roadmap update
We are planning the last preview release around the first week of September. This will allow us to get in the last of our significant code changes before we start minimizing risk (and code churn) for our Release Candidate.
We expect our first Release Candidate in the second half of September. Release Candidates are “go-live” meaning they are supported in production. If there is a critical security or blocking issue, we will provide an updated servicing release for a Release Candidate. We would like users to start deploying the Release Candidate so that we can address any major issues as we head towards a General Availability release at the end of this year.
Unlike preview releases, Release Candidates will not have Experimental Features enabled by default. Some Experimental Features will be taken out of experimental state and their designs will be considered final while others will stay in experimental state and will need to be explicitly enabled to continue use.
As a reminder, Experimental Features are not considered design complete. This means that the design may change based on real world usage feedback and such changes are not considered breaking changes. Production code should not depend on experimental features.
Noteworthy Changes
There are some changes in PowerShell 7.1 Preview 6 that are worth going into detail and some are breaking changes.
Rename -FromUnixTime
to -UnixTimeSeconds
on Get-Date
to allow Unix time input
Unix time is the number of seconds since January 1st, 1970 at 00:00:00 UTC.
In Preview 2 of PowerShell 7.1, we merged a community submitted pull request to add -FromUnixTime
to the Get-Date
cmdlet.
However, it was discovered later that the prefix From
was inconsistent with existing parameters on that cmdlet.
So a change was accepted to simply call it -UnixTimeSeconds
which accepts a value in Unix time similar to how
-Date
accepts a value in date time format.
get-date -UnixTimeSeconds 1597615564
Sunday, August 16, 2020 3:06:04 PM
This feature was added by community member aetos382!
Make $ErrorActionPreference
not affect stderr
output of native commands
Native commands support three streams: stdin, stdout, and stderr.
stdin
is for sending input to a native command.
stdout
is for any output from a native command you might want to pass further down the pipeline.
stderr
(despite “error” being in the name) is used for all other output.
stderr
can include error messages, but also text content equivalent to PowerShell verbose, debug, and information streams
as well as progress information or help text.
The de facto standard way to determining if a native command has succeeded or failed is by looking at the exit code
(in PowerShell this is by the $LASTEXITCODE
automatic variable).
Since stderr
typically contains non-error information, it is not a reliable way to detect errors from native commands.
Text output from stderr
are wrapped as ErrorRecord
s but tagged to indicate it is from stderr.
Prior to this change, because these are ErrorRecord
instances, they would get added to the $Error
automatic variable
which is a running log of errors.
If you set $ErrorActionPreference
to a value that affects execution (like Stop
or Inquire
) then any text written
to stderr
would cause your script execution to be impacted.
With this change, stderr
is just treated like an information stream (although it is still stream number 2 for redirection) and
is not affected by $ErrorActionPreference
which also means stderr
output does not show up in $Error
nor does it
cause $?
to be $false
indicating the last command failed.
There is an existing RFC to allow script execution to be impacted by native command exit code that we hope to be in a future version of PowerShell.
Allow explicitly specified named parameter to supersede the same one from hashtable splatting
Splatting is a feature in PowerShell allowing passing parameters to commands defined in a hashtable. For example, if you have a script that calls the same or different cmdlets multiple times where the parameters and their values are the same, then instead of typing it multiple times you can define it once and pass the same hashtable to each cmdlet. If a parameter or value changes, you would then just update the hashtable.
$myParams = @{
Uri = 'https://api.github.com/repos/powershell/powershell/releases'
Method = 'Get'
FollowRelLink = $true
}
Invoke-RestMethod @myParams
Note: The above example shows how to pass the
-FollowRelLink
switch using splatting
In some scripts, you may want to override one of the values in the hashtable for a specific instance. Previously, you would get an error that the parameter was already specified:
Invoke-RestMethod @myParams -Uri https://api.github.com/repos/dotnet/runtime
Invoke-RestMethod: Cannot bind parameter because parameter 'Uri' is specified more than once. To provide multiple values to parameters that can accept multiple values, use the array syntax. For example, "-parameter value1,value2,value3".
With this change, the above example now works as one would expect in that the -Uri
parameter value will be the one explicitly
specified in the command line and not the one in the hashtable.
Experimental Feature: PSManageBreakpointsInRunspace
PowerShell has powerful built-in scripting debugging capabilities. However, previously the debugging cmdlets would only allow you to manage breakpoints in the current PowerShell session (called a runspace). Community member Kirk Munro added the ability to specify a different runspace to the breakpoint management cmdlets!
$job = Start-Job { $pid; Start-Sleep -Seconds 5; Write-Verbose "Hello" }
# wait until the job process starts
while ($job.ChildJobs[0].Runspace.RunspaceStateInfo.State -ne 'Opened') {
Start-Sleep -Milliseconds 50
}
Set-PSBreakpoint -Command Write-Verbose -Action { break } -Runspace $job.ChildJobs[0].Runspace
# wait until the job is waiting at the breakpoint
while ($job.State -ne 'AtBreakpoint') {
Start-Sleep -Seconds 1
}
# get the job process id to debug it later
$jobpid = $job | Receive-Job
$job | Get-Job
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
7 Job7 BackgroundJob AtBreakpoint True localhost Start-Sleep -Seconds 5;…
# Connect to the running job process
Enter-PSHostProcess -id $jobpid
# Find the runspace where the running script is stopped at the breakpoint and attach debugger to it
Get-Runspace | Where-Object { $_.Debugger.InBreakpoint -eq $true } | Debug-Runspace
Debugging Runspace: RemoteHost
To end the debugging session type the 'Detach' command at the debugger prompt, or type 'Ctrl+C' otherwise.
Hit Command breakpoint on 'Write-Verbose'
At line:1 char:32
+ $pid; Start-Sleep -Seconds 5; Write-Verbose "Hello"
+ ~~~~~~~~~~~~~~~~~~~~~
Here you see that execution stopped exactly where we set the breakpoint.
Note: As the script is stopped at the breakpoint, it will wait indefinitely for a debugger to be attached
Built in Pager for Get-Help
As part of additional work to improve the PowerShell help experience (more on this later!), we wrote our own pager to provide a consistent experience across platforms.
This is a work in progress so a bit limited in functionality currently. Contributions and issues are certainly welcome in the Pager repo.
You can try it out using the new -Paged
switch with Get-Help
:
Get-Help -Paged Get-Command
PSReadLine will leverage this pager for its new “Dynamic Help” feature where you can use a keyboard combination to get help while in the middle of typing out a command-line and being able to return to exactly where you left off!
New -MaskInput
switch for Read-Host
This was a community requested feature to hide the input the user types.
Normally, you would use -AsSecureString
for sensitive information that you would not want echoed onto the screen or end up in logs/transcripts.
However, there are scenarios where you don’t want to deal with a SecureString and prefer to get plain text.
This switch will still mask the input the user types, but returns a string.
$input = Read-Host -MaskInput -Prompt "Tell me a secret"
Summary
There are, of course, many bug fixes and smaller improvements not mentioned in this blog post provided by both the community as well as the PowerShell team. We have a few more important changes to get into the PowerShell 7.1 release before we hit our first Release Candidate in September.
Early this month, the majority of PowerShell usage (not including Windows PowerShell) switched from PowerShell Core 6.2 to PowerShell 7.0!
We hit a high point of 4.5 million startups of pwsh
in a single day!
See more data at our public PowerBI dashboard.
Reminder that PowerShell Core 6.2 support ends next month!
Wouldn’t you want the precedent to be whichever parameter was last? This would allow the user to use the explicit as a default and splatting as an override, if the order is reversed.
I think the example makes sense, and that it’s logical. The point is to define the default by using splatting, then explicitly defining an alternative.