Windows PowerShell and PowerShell 7 compatibility
Microsoft's edit ·
Microsoft's commit message in MicrosoftDocs/PowerShell-Docs · commit c1e5ad3 · +416 −2 lines · also on GitHub
11
---
2
−description: This article summarizes the differences and breaking changes from Windows PowerShell 5.1 and the current version of PowerShell that is based on .NET Core.
3
−ms.date: 02/03/2020
2
+ms.date: 09/17/2021
43
title: Differences between Windows PowerShell 5.1 and PowerShell 7.x
4
+description: This article summarizes the differences and breaking changes from Windows PowerShell 5.1 and the current version of PowerShell that is based on .NET Core.
5
+---
6
+# Differences between Windows PowerShell 5.1 and PowerShell 7.x
7
+
8
+Windows PowerShell 5.1 is built on top of the .NET Framework v4.5. With the release of PowerShell
9
+6.0, PowerShell became an open source project built on .NET Core 2.0. PowerShell 7.0 is built on
10
+.NET Core 3.1. And, with the release of PowerShell 7.2, PowerShell will be built on .NET 6.0. Moving
11
+from the .NET Framework to .NET Core allowed PowerShell to become a cross-platform solution.
12
+PowerShell runs on Windows, macOS, and Linux.
13
+
14
+There are few differences in the PowerShell language between Windows PowerShell and PowerShell. The
15
+differences are most notable in the availability and behavior of PowerShell cmdlets between Windows
16
+and non-Windows platforms and the changes that stem from the differences between the .NET Framework
17
+and .NET Core.
18
+
19
+This article summarizes the significant differences and breaking changes between Windows PowerShell
20
+and the current version of PowerShell. This summary does not include new features or cmdlets that
21
+have been added. Nor does this article discuss what changed between versions. The goal of this
22
+article is to present the current state of PowerShell and how that is different from Windows
23
+PowerShell. For a detailed discussion of changes between versions and the addition of new features,
24
+see the **What's New** articles for each version.
25
+
26
+- [What's new in PowerShell 7.x](What-s-New-in-PowerShell-71.md)
27
+- [What's new in PowerShell 6.x](/previous-versions/powershell/scripting/whats-new/what-s-new-in-powershell-core-62?view=powershell-6&preserve-view=true)
28
+
29
+## .NET Framework vs .NET Core
30
+
31
+PowerShell on Linux and macOS uses .NET Core, which is a subset of the full .NET Framework on
32
+Microsoft Windows. This is significant because PowerShell provides direct access to the underlying
33
+framework types and methods. As a result, scripts that run on Windows may not run on non-Windows
34
+platforms because of the differences in the frameworks. For more information about changes in .NET
35
+Core, see
36
+[Breaking changes for migration from .NET Framework to .NET Core](/dotnet/core/compatibility/fx-core).
37
+
38
+With the advent of
39
+[.NET Standard 2.0](https://devblogs.microsoft.com/dotnet/introducing-net-standard/), PowerShell can
40
+load many traditional Windows PowerShell modules without modification. Additionally, PowerShell 7
41
+includes a Windows PowerShell Compatibility feature that allows you to use Windows PowerShell
42
+modules that still require the full framework.
43
+
44
+For more information see:
45
+
46
+- [about_Windows_PowerShell_Compatibility](/powershell/module/microsoft.powershell.core/about/about_windows_powershell_compatibility)
47
+- [PowerShell 7 module compatibility](module-compatibility.md)
48
+
49
+[!INCLUDE [Product terminology](../../includes/product-terms.md)]
50
+
51
+## Modules no longer shipped with PowerShell
52
+
53
+For various compatibility reasons, the following modules are no longer included in PowerShell.
54
+
55
+- ISE
56
+- Microsoft.PowerShell.LocalAccounts
57
+- Microsoft.PowerShell.ODataUtils
58
+- Microsoft.PowerShell.Operation.Validation
59
+- PSScheduledJob
60
+- PSWorkflow
61
+- PSWorkflowUtility
62
+
63
+### PowerShell Workflow
64
+
65
+[PowerShell Workflow][workflow] is a feature in Windows PowerShell that builds on top of
66
+[Windows Workflow Foundation (WF)][workflow-foundation] that enables the creation of robust runbooks
67
+for long-running or parallelized tasks.
68
+
69
+Due to the lack of support for Windows Workflow Foundation in .NET Core, we removed PowerShell
70
+Workflow from PowerShell.
71
+
72
+In the future, we would like to enable native parallelism/concurrency in the PowerShell language
73
+without the need for PowerShell Workflow.
74
+
75
+If there is a need to use checkpoints to resume a script after the OS restarts, we recommend
76
+using Task Scheduler to run a script on OS startup, but the script would need to maintain
77
+its own state (like persisting it to a file).
78
+
79
+[workflow]: /previous-versions/powershell/scripting/components/workflows-guide
80
+[workflow-foundation]: /dotnet/framework/windows-workflow-foundation/
81
+
82
+## Cmdlets removed from PowerShell
83
+
84
+For the modules that are included in PowerShell, the following cmdlets were removed from PowerShell
85
+for various compatibility reasons or the use of unsupported APIs.
86
+
87
+CimCmdlets
88
+
89
+- `Export-BinaryMiLog`
90
+
91
+Microsoft.PowerShell.Core
92
+
93
+- `Add-PSSnapin`
94
+- `Export-Console`
95
+- `Get-PSSnapin`
96
+- `Remove-PSSnapin`
97
+- `Resume-Job`
98
+- `Suspend-Job`
99
+
100
+Microsoft.PowerShell.Diagnostics
101
+
102
+- `Export-Counter`
103
+- `Import-Counter`
104
+
105
+Microsoft.PowerShell.Management
106
+
107
+- `Add-Computer`
108
+- `Checkpoint-Computer`
109
+- `Clear-EventLog`
110
+- `Complete-Transaction`
111
+- `Disable-ComputerRestore`
112
+- `Enable-ComputerRestore`
113
+- `Get-ComputerRestorePoint`
114
+- `Get-ControlPanelItem`
115
+- `Get-EventLog`
116
+- `Get-Transaction`
117
+- `Get-WmiObject`
118
+- `Invoke-WmiMethod`
119
+- `Limit-EventLog`
120
+- `New-EventLog`
121
+- `New-WebServiceProxy`
122
+- `Register-WmiEvent`
123
+- `Remove-Computer`
124
+- `Remove-EventLog`
125
+- `Remove-WmiObject`
126
+- `Reset-ComputerMachinePassword`
127
+- `Restore-Computer`
128
+- `Set-WmiInstance`
129
+- `Show-ControlPanelItem`
130
+- `Show-EventLog`
131
+- `Start-Transaction`
132
+- `Test-ComputerSecureChannel`
133
+- `Undo-Transaction`
134
+- `Use-Transaction`
135
+- `Write-EventLog`
136
+
137
+Microsoft.PowerShell.Utility
138
+
139
+- `Convert-String`
140
+- `ConvertFrom-String`
141
+
142
+PSDesiredStateConfiguration
143
+
144
+- `Disable-DscDebug`
145
+- `Enable-DscDebug`
146
+- `Get-DscConfiguration`
147
+- `Get-DscConfigurationStatus`
148
+- `Get-DscLocalConfigurationManager`
149
+- `Publish-DscConfiguration`
150
+- `Remove-DscConfigurationDocument`
151
+- `Restore-DscConfiguration`
152
+- `Set-DscLocalConfigurationManager`
153
+- `Start-DscConfiguration`
154
+- `Stop-DscConfiguration`
155
+- `Test-DscConfiguration`
156
+- `Update-DscConfiguration`
157
+
158
+### WMI v1 cmdlets
159
+
160
+The following WMI v1 cmdlets were removed from PowerShell:
161
+
162
+- `Register-WmiEvent`
163
+- `Set-WmiInstance`
164
+- `Invoke-WmiMethod`
165
+- `Get-WmiObject`
166
+- `Remove-WmiObject`
167
+
168
+The CimCmdlets module (aka WMI v2) cmdlets perform the same function and provide new functionality
169
+and a redesigned syntax.
170
+
171
+### `New-WebServiceProxy` cmdlet removed
172
+
173
+.NET Core does not support the Windows Communication Framework, which provide services for using the
174
+SOAP protocol. This cmdlet was removed because it requires SOAP.
175
+
176
+### `*-Transaction` cmdlets removed
177
+
178
+These cmdlets had very limited usage. The decision was made to discontinue support for them.
179
+
180
+- `Complete-Transaction`
181
+- `Get-Transaction`
182
+- `Start-Transaction`
183
+- `Undo-Transaction`
184
+- `Use-Transaction`
185
+
186
+### `*-EventLog` cmdlets
187
+
188
+Due to the use of unsupported APIs, the `*-EventLog` cmdlets have been removed from PowerShell.
189
+`Get-WinEvent` and `New-WinEvent` are available to get and create events on Windows.
190
+
191
+### Cmdlets that use the Windows Presentation Framework (WPF)
192
+
193
+.NET Core 3.1 added support for WPF, so the release of PowerShell 7.0 restored the following
194
+Windows-specific features:
195
+
196
+- The `Show-Command` cmdlet
197
+- The `Out-GridView` cmdlet
198
+- The **ShowWindow** parameter of `Get-Help`
199
+
200
+### PowerShell Desired State Configuration (DSC) changes
201
+
202
+`Invoke-DscResource` was restored as an experimental feature in PowerShell 7.0.
203
+
204
+Beginning with PowerShell 7.2, the PSDesiredStateConfiguration module has been removed from
205
+PowerShell and has been published to the PowerShell Gallery. For more information, see the
206
+[announcement](https://devblogs.microsoft.com/powershell/announcing-psdesiredstateconfiguration-on-powershell-gallery/)
207
+in the PowerShell Team blog.
208
+
209
+## Engine/language changes
210
+
211
+### Renamed `powershell.exe` to `pwsh.exe`
212
+
213
+The binary name for PowerShell has been changed from `powershell(.exe)` to `pwsh(.exe)`. This
214
+change provides a deterministic way for users to run PowerShell on machines and support
215
+side-by-side installations of Windows PowerShell and PowerShell.
216
+
217
+Additional changes to `pwsh(.exe)` from `powershell.exe`:
218
+
219
+- Changed the first positional parameter from `-Command` to `-File`. This change fixes the usage of
220
+ `#!` (aka as a shebang) in PowerShell scripts that are being executed from non-PowerShell shells
221
+ on non-Windows platforms. It also means that you can run commands like `pwsh foo.ps1` or
222
+ `pwsh fooScript` without specifying `-File`. However, this change requires that you explicitly
223
+ specify `-c` or `-Command` when trying to run commands like `pwsh.exe -Command Get-Command`.
224
+- `pwsh` accepts the `-i` (or `-Interactive`) switch to indicate an interactive shell.
225
+ This allows PowerShell to be used as a default shell on Unix platforms.
226
+- Removed parameters `-ImportSystemModules` and `-PSConsoleFile` from `pwsh.exe`.
227
+- Changed `pwsh -version` and built-in help for `pwsh.exe` to align with other native tools.
228
+- Invalid argument error messages for `-File` and `-Command` and exit codes consistent with Unix
229
+ standards
230
+- Added `-WindowStyle` parameter on Windows. Similarly, package-based installations updates on
231
+ non-Windows platforms are in-place updates.
232
+
233
+The shortened name is also consistent with naming of shells on non-Windows platforms.
234
+
235
+### Support running a PowerShell script with bool parameter
236
+
237
+Previously, using `pwsh.exe` to execute a PowerShell script using `-File` provided no way to pass
238
+`$true`/`$false` as parameter values. Support for `$true`/`$false` as parsed values to parameters
239
+was added. Switch values are also supported.
240
+
241
+### Support PowerShell as a default Unix shell
242
+
243
+On Unix, it is a convention for shells to accept `-i` for an interactive shell and many tools
244
+expect this behavior (`script` for example, and when setting PowerShell as the default shell) and
245
+calls the shell with the `-i` switch. This change is breaking in that `-i` previously could be used
246
+as short hand to match `-inputformat`, which now needs to be `-in`.
247
+
248
+### Custom snap-ins
249
+
250
+[PowerShell snap-ins][snapin] are a predecessor to PowerShell modules that do not have widespread
251
+adoption in the PowerShell community.
252
+
253
+Due to the complexity of supporting snap-ins and their lack of usage in the community, we no longer
254
+support custom snap-ins in PowerShell.
255
+
256
+[snapin]: /powershell/module/microsoft.powershell.core/about/about_pssnapins
257
+
258
+### Experimental feature flags
259
+
260
+We enabled support for [Experimental Features][exp]. This allows PowerShell developers to deliver
261
+new features and get feedback before the design is complete. This way we avoid making breaking
262
+changes as the design evolves.
263
+
264
+Use `Get-ExperimentalFeature` to get a list of available experimental features. You can enable or
265
+disable these features with `Enable-ExperimentalFeature` and `Disable-ExperimentalFeature`.
266
+
267
+[exp]: /powershell/module/Microsoft.PowerShell.Core/About/about_Experimental_Features
268
+
269
+### Load assembly from module base path before trying to load from the GAC
270
+
271
+Previously, when a binary module has the module assembly in GAC, we loaded the assembly from GAC
272
+before trying to load it from module base path.
273
+
274
+### Skip null-element check for collections with a value-type element type
275
+
276
+For the `Mandatory` parameter and `ValidateNotNull` and `ValidateNotNullOrEmpty` attributes, skip
277
+the null-element check if the collection's element type is value type.
278
+
279
+### Preserve `$?` for **ParenExpression**, **SubExpression** and **ArrayExpression**
280
+
281
+This PR alters the way we compile subpipelines `(...)`, subexpressions `$(...)` and array
282
+expressions `@()` so that `$?` is not automatically **true**. Instead the value of `$?` depends on
283
+the result of the pipeline or statements executed.
284
+
285
+### Fix `$?` to not be `$false` when native command writes to `stderr`
286
+
287
+`$?` is not set to `$false` when native command writes to `stderr`. It is common for native
288
+commands to write to `stderr` without intending to indicate a failure. `$?` is set to `$false` only
289
+when the native command has a non-zero exit code.
290
+
291
+### Make `$ErrorActionPreference` not affect `stderr` output of native commands
292
+
293
+It is common for native commands to write to `stderr` without intending to indicate a failure. With
294
+this change, `stderr` output is still captured in **ErrorRecord** objects, but the runtime no longer
295
+applies `$ErrorActionPreference` if the **ErrorRecord** comes from a native command.
296
+
297
+### Change `$OutputEncoding` to use `UTF-8 NoBOM` encoding rather than ASCII
298
+
299
+The previous encoding, ASCII (7-bit), would result in incorrect alteration of the output in some
300
+cases. Making `UTF-8 NoBOM` the default preserves Unicode output with an encoding supported by most
301
+tools and operating systems.
302
+
303
+### Unify cmdlets with parameter `-Encoding` to be of type `System.Text.Encoding`
304
+
305
+The `-Encoding` value `Byte` has been removed from the filesystem provider cmdlets. A new
306
+parameter, `-AsByteStream`, is now used to specify that a byte stream is required as input or that
307
+the output is a stream of bytes.
308
+
309
+### Change `New-ModuleManifest` encoding to `UTF8NoBOM` on non-Windows platforms
310
+
311
+Previously, `New-ModuleManifest` creates `psd1` manifests in UTF-16 with BOM, creating a problem for
312
+Linux tools. This breaking change changes the encoding of `New-ModuleManifest` to be UTF (no BOM) in
313
+non-Windows platforms.
314
+
315
+### Remove `AllScope` from most default aliases
316
+
317
+To speed up scope creation, `AllScope` was removed from most default aliases. `AllScope` was left
318
+for a few frequently used aliases where the lookup was faster.
319
+
320
+### `-Verbose` and `-Debug` no longer overrides `$ErrorActionPreference`
321
+
322
+Previously, if `-Verbose` or `-Debug` were specified, it overrode the behavior of
323
+`$ErrorActionPreference`. With this change, `-Verbose` and `-Debug` no longer affect the behavior
324
+of `$ErrorActionPreference`.
325
+
326
+Also, the `-Debug` parameter sets `$DebugPreference` to **Continue** instead of **Inquire**.
327
+
328
+### Make `$PSCulture` consistently reflect in-session culture changes
329
+
330
+In Windows PowerShell, the current culture value is cached, which can allow the value to get out of
331
+sync with the culture is change after session-startup. This caching behavior is fixed in PowerShell
332
+core.
333
+
334
+### Allow explicitly specified named parameter to supersede the same one from hashtable splatting
335
+
336
+With this change, the named parameters from splatting are moved to the end of the parameter list so
337
+that they are bound after all explicitly specified named parameters are bound. Parameter binding for
338
+simple functions doesn't throw an error when a specified named parameter cannot be found. Unknown
339
+named parameters are bound to the `$args` parameter of the simple function. Moving splatting to the
340
+end of the argument list changes the order the parameters appears in `$args`.
341
+
342
+For example:
343
+
344
+```powershell
345
+function SimpleTest {
346
+ param(
347
+ $Name,
348
+ $Path
349
+ )
350
+ "Name: $Name; Path: $Path; Args: $args"
351
+}
352
+```
353
+
354
+In the previous behavior, **MyPath** is not bound to `-Path` because it's the third argument in the
355
+argument list. ## So it ends up being stuffed into '$args' along with `Blah = "World"`
356
+
357
+```powershell
358
+PS> $hash = @{ Name = "Hello"; Blah = "World" }
359
+PS> SimpleTest @hash "MyPath"
360
+Name: Hello; Path: ; Args: -Blah: World MyPath
361
+```
362
+
363
+With this change, the arguments from `@hash` are moved to the end of the argument list. **MyPath**
364
+becomes the first argument in the list, so it is bound to `-Path`.
365
+
366
+```powershell
367
+PS> SimpleTest @hash "MyPath"
368
+Name: Hello; Path: MyPath; Args: -Blah: World
369
+```
370
+
371
+### Added `&` operator for job control
372
+
373
+Putting `&` at the end of a pipeline causes the pipeline to be run as a PowerShell job. When a
374
+pipeline is backgrounded, a job object is returned. Once the pipeline is running as a job, all of
375
+the standard `*-Job` cmdlets can be used to manage the job. Variables (ignoring process-specific
376
+variables) used in the pipeline are automatically copied to the job so `Copy-Item $foo $bar &` just
377
+works. The job is also run in the current directory instead of the user's home directory.
378
+
379
+### New methods/properties on `PSCustomObject`
380
+
381
+We've added new methods and properties to `PSCustomObject`. `PSCustomObject` now includes a
382
+`Count`/`Length` property like other objects.
383
+
384
+```powershell
385
+$PSCustomObject = [pscustomobject]@{foo = 1}
386
+
387
+$PSCustomObject.Length
388
+```
389
+
390
+```Output
391
+1
392
+```
393
+
394
+```powershell
395
+$PSCustomObject.Count
396
+```
397
+
398
+```Output
399
+1
400
+```
401
+
402
+This work also includes `ForEach` and `Where` methods that allow you to operate and filter on
403
+`PSCustomObject` items:
404
+
405
+```powershell
406
+$PSCustomObject.ForEach({$_.foo + 1})
407
+```
408
+
409
+```Output
410
+2
411
+```
412
+
413
+```powershell
414
+$PSCustomObject.Where({$_.foo -gt 0})
415
+```
416
+
417
+```Output
418
+foo
5419
---
6420
1
7421
```
⋯ 430 unchanged lines
Microsoft's Markdown source from MicrosoftDocs/PowerShell-Docs, © Microsoft Corporation, under CC BY 4.0. Changed lines with up to 3 unchanged lines around each; ChangeIntel kept this copy 10 Oct 03:16 UTC. The commit date is when the source changed, which can be hours or days before Learn published it.