Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4/26/2024 PM Publish #11057

Merged
merged 2 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
---
description: Describes easier, more natural-language ways of scripting filters for collections of objects.
Locale: en-US
ms.date: 06/09/2017
ms.date: 04/26/2024
online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_simplified_syntax?view=powershell-5.1&WT.mc_id=ps-gethelp
schema: 2.0.0
title: about Simplified Syntax
---

# about_Simplified_Syntax

## Short description

Describes easier, more natural-language ways of scripting filters for
collections of objects.

## Long description

Simplified syntax, introduced in Windows PowerShell 3.0, lets you build some
filter commands without using script blocks. The simplified syntax more
closely resembles natural language, and is primarily useful with collections
of objects that get piped into commands `Where-Object` and `ForEach-Object` and
their corresponding aliases `where` and `foreach`.
filter commands without using script blocks. The simplified syntax more closely
resembles natural language, and is primarily useful with collections of objects
that get piped into commands `Where-Object` and `ForEach-Object` or their
corresponding aliases `where` and `foreach`.

You can use a method on the members of a collection (most commonly, an array)
without referring to the automatic variable `$_` inside a script block.
Expand All @@ -30,41 +28,65 @@ Consider the following two invocations:
### Standard Syntax

```powershell
dir Cert:\LocalMachine\Root | where { $_.FriendlyName -eq 'Verisign' }
dir Cert:\ -Recurse | foreach { $_.GetKeyAlgorithm() }
Get-ChildItem Cert:\LocalMachine\Root |
Where-Object -FilterScript { $_.FriendlyName -eq 'Verisign' }
Get-ChildItem Cert:\ -Recurse |
ForEach-Object -FilterScript { $_.GetKeyAlgorithm() }
```

> [!NOTE]
> In the second command, the `GetKeyAlgorithm` method is called on each object
> in the collection. If the object received from the pipeline doesn't have a
> `GetKeyAlgorithm` method, the command produces an error.

### Simplified syntax

Under the simplified syntax, comparison operators that work on members of objects in a
collection are treated as parameters. You can invoke a method on objects in a
collection without referring to the automatic variable `$_` inside a script block.
Compare the following two invocations to those of the previous example:
Under the simplified syntax, comparison operators that work on members of
objects in a collection are implemented as parameters. Also, you can invoke a
method on objects in a collection without referring to the automatic variable
`$_` inside a script block. Compare the following two invocations to the
standard syntax examples:

```powershell
Get-ChildItem Cert:\LocalMachine\Root |
Where-Object -Property FriendlyName -EQ 'Verisign'
Get-ChildItem Cert:\ -Recurse |
ForEach-Object -MemberName GetKeyAlgorithm
```

Since the **Property** and **MemberName** parameters are positional, you can
omit them from the command. Using aliases, you can further simplify the
commands:

```powershell
dir Cert:\LocalMachine\Root | where FriendlyName -eq 'Verisign'
dir Cert:\ -Recurse | foreach GetKeyAlgorithm
dir Cert:\LocalMachine\Root | Where FriendlyName -EQ 'Verisign'
dir Cert:\ -Recurse | ForEach GetKeyAlgorithm
```

While both syntaxes work, the simplified syntax returns results without
referring to the automatic variable `$_` inside a script block.
The method name `GetKeyAlgorithm` is treated as a parameter of `ForEach-Object`.
The second command returns the same results, but without errors,
because the simplified syntax does not attempt to return results for items
for which the specified argument did not apply.
referring to the automatic variable `$_` inside a script block. The simplified
syntax reads more like a natural language statement and can be easier to
understand.

The method name `GetKeyAlgorithm` is passed as an argument for the
**MemberName** parameter of `ForEach-Object`. When you invoke the method using
the simplified syntax, the method is called for each object in pipeline only if
that object has that method. Therefore, you get the same results, but without
errors.

In this example, the `Process` property `Description` is passed as the member name
parameter to the `ForEach-Object` command. The results are descriptions of active
processes.
In the next example, `Description` is passed to the **MemberName** parameter of
`ForEach-Object`. The command displays the description of each
**System.Diagnostics.Process** object returned by `Get-Process`.

```powershell
Get-Process | foreach Description
```

In this example, the `DirectoryInfo` method `GetFiles` is passed as the member name
parameter of the `ForEach-Object` command.
The method is called with the search pattern parameter `.*`.
The results are `FileInfo` records for all Unix-style hidden files in user home directories.
In this example, the method name `GetFiles` is passed to the **MemberName**
parameter of the `ForEach-Object` command. The `.*` value is passed to the
**ArgumentList** parameter. The `GetFiles()` method is called with the search
pattern parameter `.*` for each **System.IO.DirectoryInfo** object returned by
`Get-ChildItem`.

```powershell
Get-ChildItem /home -Directory | foreach GetFiles .*
Expand Down
65 changes: 36 additions & 29 deletions reference/5.1/Microsoft.PowerShell.Core/ForEach-Object.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
external help file: System.Management.Automation.dll-Help.xml
Locale: en-US
Module Name: Microsoft.PowerShell.Core
ms.date: 01/13/2023
ms.date: 04/26/2024
online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-5.1&WT.mc_id=ps-gethelp
schema: 2.0.0
title: ForEach-Object
Expand Down Expand Up @@ -49,7 +49,7 @@ command.
[about_functions](about/about_functions.md#piping-objects-to-functions).

> [!NOTE]
> The script blocks run in the caller's scope. Therefore the blocks have access to variables in
> The script blocks run in the caller's scope. Therefore, the blocks have access to variables in
> that scope and can create new variables that persist in that scope after the cmdlet completes.

- **Operation statement**. You can also write an operation statement, which is much more like
Expand Down Expand Up @@ -86,7 +86,7 @@ Get-ChildItem $PSHOME |
ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; " " }}
```

If the object is not a directory, the script block gets the name of the file, divides the value of
If the object isn't a directory, the script block gets the name of the file, divides the value of
its **Length** property by 1024, and adds a space (" ") to separate it from the next entry. The
cmdlet uses the **PSISContainer** property to determine whether an object is a directory.

Expand All @@ -96,16 +96,17 @@ This example writes the 1000 most recent events from the System event log to a t
current time is displayed before and after processing the events.

```powershell
$Events = Get-EventLog -LogName System -Newest 1000
$events | ForEach-Object -Begin {Get-Date} -Process {Out-File -FilePath Events.txt -Append -InputObject $_.Message} -End {Get-Date}
Get-EventLog -LogName System -Newest 1000 |
ForEach-Object -Begin {Get-Date} -Process {
Out-File -FilePath Events.txt -Append -InputObject $_.Message
} -End {Get-Date}
```

`Get-EventLog` gets the 1000 most recent events from the System event log and stores them in the
`$Events` variable. `$Events` is then piped to the `ForEach-Object` cmdlet. The **Begin** parameter
displays the current date and time. Next, the **Process** parameter uses the `Out-File` cmdlet to
create a text file that is named events.txt and stores the message property of each of the events in
that file. Last, the **End** parameter is used to display the date and time after all the processing
has completed.
`Get-EventLog` gets the 1000 most recent events from the System event log and pipes them to the
`ForEach-Object` cmdlet. The **Begin** parameter displays the current date and time. Next, the
**Process** parameter uses the `Out-File` cmdlet to create a text file that's named events.txt and
stores the message property of each of the events in that file. Last, the **End** parameter is used
to display the date and time after all the processing has completed.

### Example 4: Change the value of a Registry key

Expand All @@ -114,13 +115,15 @@ This example changes the value of the **RemotePath** registry entry in all the s

```powershell
Get-ItemProperty -Path HKCU:\Network\* |
ForEach-Object {Set-ItemProperty -Path $_.PSPath -Name RemotePath -Value $_.RemotePath.ToUpper();}
ForEach-Object {
Set-ItemProperty -Path $_.PSPath -Name RemotePath -Value $_.RemotePath.ToUpper()
}
```

You can use this format to change the form or content of a registry entry value.

Each subkey in the **Network** key represents a mapped network drive that reconnects at sign on. The
**RemotePath** entry contains the UNC path of the connected drive. For example, if you map the E:
**RemotePath** entry contains the UNC path of the connected drive. For example, if you map the `E:`
drive to `\\Server\Share`, an **E** subkey is created in `HKCU:\Network` with the **RemotePath**
registry value set to `\\Server\Share`.

Expand All @@ -129,7 +132,7 @@ The command uses the `Get-ItemProperty` cmdlet to get all the subkeys of the **N
the `Set-ItemProperty` command, the path is the value of the **PSPath** property of the registry
key. This is a property of the Microsoft .NET Framework object that represents the registry key, not
a registry entry. The command uses the **ToUpper()** method of the **RemotePath** value, which is a
string (REG_SZ).
string **REG_SZ**.

Because `Set-ItemProperty` is changing the property of each key, the `ForEach-Object` cmdlet is
required to access the property.
Expand All @@ -155,7 +158,7 @@ a value for `$null` as it does for other objects piped to it.

### Example 6: Get property values

This example gets the value of the **Path** property of all installed PowerShell modules by using
This example gets the value of the **Path** property of all installed PowerShell modules using
the **MemberName** parameter of the `ForEach-Object` cmdlet.

```powershell
Expand All @@ -177,9 +180,12 @@ The commands call the **Split** method of strings. The three commands use differ
are equivalent and interchangeable. The output is the same for all three cases.

```powershell
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | ForEach-Object {$_.Split(".")}
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | ForEach-Object -MemberName Split -ArgumentList "."
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | Foreach Split "."
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" |
ForEach-Object {$_.Split(".")}
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" |
ForEach-Object -MemberName Split -ArgumentList "."
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" |
Foreach Split "."
```

```Output
Expand All @@ -204,7 +210,7 @@ the **MemberName** and **ArgumentList** parameters, which are optional.
### Example 8: Using ForEach-Object with two script blocks

In this example, we pass two script blocks positionally. All the script blocks bind to the
**Process** parameter. However, they are treated as if they had been passed to the **Begin** and
**Process** parameter. However, they're treated as if they had been passed to the **Begin** and
**Process** parameters.

```powershell
Expand All @@ -220,7 +226,7 @@ process
### Example 9: Using ForEach-Object with more than two script blocks

In this example, we pass four script blocks positionally. All the script blocks bind to the
**Process** parameter. However, they are treated as if they had been passed to the **Begin**,
**Process** parameter. However, they're treated as if they had been passed to the **Begin**,
**Process**, and **End** parameters.

```powershell
Expand All @@ -238,7 +244,7 @@ end

> [!NOTE]
> The first script block is always mapped to the `begin` block, the last block is mapped to the
> `end` block, and the blocks in between are all mapped to the `process` block.
> `end` block, and the two middle blocks are mapped to the `process` block.

### Example 10: Run multiple script blocks for each pipeline item

Expand Down Expand Up @@ -324,8 +330,8 @@ the objects.

When you use the **InputObject** parameter with `ForEach-Object`, instead of piping command results
to `ForEach-Object`, the **InputObject** value is treated as a single object. This is true even if
the value is a collection that is the result of a command, such as `-InputObject (Get-Process)`.
Because **InputObject** cannot return individual properties from an array or collection of objects,
the value is a collection that's the result of a command, such as `-InputObject (Get-Process)`.
Because **InputObject** can't return individual properties from an array or collection of objects,
we recommend that if you use `ForEach-Object` to perform operations on a collection of objects for
those objects that have specific values in defined properties, you use `ForEach-Object` in the
pipeline, as shown in the examples in this topic.
Expand All @@ -344,7 +350,8 @@ Accept wildcard characters: False

### -MemberName

Specifies the property to get or the method to call.
Specifies the name of the member property to get or the member method to call. The members must be
instance members, not static members.

Wildcard characters are permitted, but work only if the resulting string resolves to a unique value.
For example, if you run `Get-Process | ForEach -MemberName *Name`, the wildcard pattern matches more
Expand All @@ -366,15 +373,15 @@ Accept wildcard characters: True

### -Process

Specifies the operation that is performed on each input object. This script block is run for every
Specifies the operation that's performed on each input object. This script block is run for every
object in the pipeline. For more information about the `process` block, see
[about_Functions](about/about_functions.md#piping-objects-to-functions).

When you provide multiple script blocks to the **Process** parameter, the first script block is
always mapped to the `begin` block. If there are only two script blocks, the second block is mapped
to the `process` block. If there are three or more script blocks, first script block is always
mapped to the `begin` block, the last block is mapped to the `end` block, and the blocks in between
are all mapped to the `process` block.
mapped to the `begin` block, the last block is mapped to the `end` block, and the middle blocks are
mapped to the `process` block.

```yaml
Type: System.Management.Automation.ScriptBlock[]
Expand All @@ -390,7 +397,7 @@ Accept wildcard characters: False

### -RemainingScripts

Specifies all script blocks that are not taken by the **Process** parameter.
Specifies all script blocks that aren't taken by the **Process** parameter.

This parameter was introduced in Windows PowerShell 3.0.

Expand Down Expand Up @@ -424,7 +431,7 @@ Accept wildcard characters: False

### -WhatIf

Shows what would happen if the cmdlet runs. The cmdlet is not run.
Shows what would happen if the cmdlet runs. The cmdlet isn't run.

```yaml
Type: System.Management.Automation.SwitchParameter
Expand Down
5 changes: 3 additions & 2 deletions reference/5.1/Microsoft.PowerShell.Core/Where-Object.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
external help file: System.Management.Automation.dll-Help.xml
Locale: en-US
Module Name: Microsoft.PowerShell.Core
ms.date: 11/16/2023
ms.date: 04/26/2024
online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/where-object?view=powershell-5.1&WT.mc_id=ps-gethelp
schema: 2.0.0
title: Where-Object
Expand Down Expand Up @@ -1091,7 +1091,8 @@ Accept wildcard characters: False

### -Property

Specifies the name of an object property. The parameter name, **Property**, is optional.
Specifies the name of a property of the input object. The property must be an instance property, not
a static property. This is a positional parameter, so the name, **Property**, is optional.

This parameter was introduced in Windows PowerShell 3.0.

Expand Down
Loading