PowerShell 7 gotchas

With the release of PowerShell 7, several improvements and changes were introduced to enhance performance, compatibility, and functionality. However, some of these changes may impact existing scripts if you’re upgrading from PowerShell Core 6.x or earlier versions. In this post, we’ll explore some more significant breaking changes and provide examples to help you understand how they might affect your scripts. Microsoft have a document that lists more changes here https://learn.microsoft.com/en-us/powershell/scripting/whats-new/differences-from-windows-powershell

1. Changes in .Split() method behaviour with multiple characters

Previous behaviour:

In PowerShell Core 6.x, when using the .Split() method with a string containing multiple characters, PowerShell would split the input string on each individual character found in the delimiter string.

Example in PowerShell Core 6.x:

$value = "ab12cd34ef"  
$result = $value.Split("bde")  
$result  

Output:

a  
12c  
34  
f  

Here, the string is split at every occurrence of ‘b’, ‘d’, and ‘e’, treating each character separately.

PowerShell 7 behaviour:

In PowerShell 7, the .Split() method treats the entire delimiter string as a single unit. If you want to retain the previous behaviour and split on individual characters, you need to explicitly convert the delimiter string to a character array.

Example in PowerShell 7:

$value = "ab12cd34ef"  
$result = $value.Split("bde")  
$result  

Output:

ab12cd34ef  

In this case, the string “bde” is not found as a whole in the input, so no splitting occurs.

To split on each character in PowerShell 7:

$value = "ab12cd34ef"  
$result = $value.Split([char[]]"bde")  
$result  

Output:

a  
12c  
34  
f  

This behaviour mimics the splitting on each character as seen in PowerShell Core 6.x.

Summary:

PowerShell 7’s .Split() method now treats multi-character strings as single delimiters by default. If you need the old behaviour of splitting on each character, use [char[]] to explicitly convert the delimiter.

2. Changes in ConvertFrom-Json handling of single-item arrays

Previous behaviour:

In PowerShell Core 6.x, when using ConvertFrom-Json to parse a JSON array with a single object, the result was treated as an array, even with only one item.

Example in PowerShell Core 6.x:

$json = '[{"name": "John"}]'  
$object = $json | ConvertFrom-Json  
$object.GetType()  

Output:

IsPublic IsSerial Name                                     BaseType  
-------- -------- ----                                     --------  
True     True     Object[]                                 System.Array  

In this example, the result is an array, despite containing a single item.

PowerShell 7 behaviour:

In PowerShell 7, ConvertFrom-Json returns a PSCustomObject when the JSON array contains only a single item, rather than treating it as an array.

Example in PowerShell 7:

$json = '[{"name": "John"}]'  
$object = $json | ConvertFrom-Json  
$object.GetType()  

Output:

IsPublic IsSerial Name                                     BaseType  
-------- -------- ----                                     --------  
True     True     PSCustomObject                           System.Object  

In this case, the result is a PSCustomObject, simplifying scenarios where only one item is present.

Summary:

This change in PowerShell 7 simplifies the handling of single-item JSON arrays, reducing unnecessary array handling and making it easier to work with such objects directly.

3. Introduction of ForEach-Object -Parallel

Previous behaviour:

In PowerShell 5.x and PowerShell Core 6.x, the ForEach-Object cmdlet processed items sequentially. There was no built-in option to execute tasks in parallel within the pipeline.

Example in PowerShell 5.x or PowerShell Core 6.x:

1..5 | ForEach-Object {  
    Start-Sleep -Seconds 1  
    "Processed $_"  
}  

Output:

Processed 1  
Processed 2  
Processed 3  
Processed 4  
Processed 5  

The commands are executed one by one, resulting in a total sleep time of 5 seconds.

PowerShell 7 behaviour:

PowerShell 7 introduces the -Parallel parameter for the ForEach-Object cmdlet, allowing you to process items in parallel, which can significantly speed up tasks.

Example in PowerShell 7:

1..5 | ForEach-Object -Parallel {  
    Start-Sleep -Seconds 1  
    "Processed $_"  
}  

Output:

Processed 1  
Processed 2  
Processed 3  
Processed 4  
Processed 5  

This time, all tasks are processed in parallel, reducing the overall sleep time to approximately 1 second.

Summary:

The ForEach-Object -Parallel parameter in PowerShell 7 offers a powerful way to speed up processing by running tasks concurrently, a feature not available in previous versions.

4. Default UTF-8 encoding with BOM

Previous behaviour:

In PowerShell 5.x and PowerShell Core 6.x, when you created a new file or redirected output to a file, the default encoding was often system-specific, typically ANSI or UTF-16 without a Byte Order Mark (BOM).

PowerShell 7 behaviour:

PowerShell 7 changes the default encoding to UTF-8 with BOM for new files and output redirection. This ensures better cross-platform compatibility and consistency.

Example in PowerShell 7:

"Hello, World!" > hello.txt  

This creates a hello.txt file encoded in UTF-8 with BOM by default.

Summary:

PowerShell 7’s shift to UTF-8 with BOM as the default encoding helps standardize file encoding, especially in cross-platform environments.

5. Out-Null in Pipeline Optimization

Previous behaviour:

In PowerShell 5.x and PowerShell Core 6.x, using Out-Null in a pipeline simply discarded the output but did not offer any performance benefits.

PowerShell 7 behaviour:

In PowerShell 7, the pipeline handling for Out-Null is optimized for performance. This means that when Out-Null is used, PowerShell skips generating the output altogether, leading to faster script execution.

Example:

1..100000 | ForEach-Object { $_ } | Out-Null  

In PowerShell 7, this operation is optimized, resulting in faster execution compared to previous versions.

Summary:

The optimization of Out-Null in PowerShell 7 can lead to performance improvements in scripts where unnecessary output is being discarded.


PowerShell 7 introduces several changes that improve functionality and performance, but it’s important to be aware of these breaking changes to ensure your scripts run smoothly. By understanding and adapting to these differences, you can take full advantage of what PowerShell 7 has to offer.


Comments

Add a comment
Loading...
Follow
Follow