ForEach-Object

Realiza una operación en cada elemento de una colección de objetos de entrada.

Syntax

ForEach-Object
            [-InputObject <PSObject>]
            [-Begin <ScriptBlock>]
            [-Process] <ScriptBlock[]>
            [-End <ScriptBlock>]
            [-RemainingScripts <ScriptBlock[]>]
            [-WhatIf]
            [-Confirm]
            [<CommonParameters>]
ForEach-Object
            [-InputObject <PSObject>]
            [-MemberName] <String>
            [-ArgumentList <Object[]>]
            [-WhatIf]
            [-Confirm]
            [<CommonParameters>]
ForEach-Object
            -Parallel <scriptblock>
            [-InputObject <psobject>]
            [-ThrottleLimit <int>]
            [-TimeoutSeconds <int>]
            [-AsJob]
            [-UseNewRunspace]
            [-WhatIf]
            [-Confirm]
            [<CommonParameters>]

Description

El ForEach-Object cmdlet realiza una operación en cada elemento de una colección de objetos de entrada. Los objetos de entrada se pueden canalizar al cmdlet o especificarse mediante el parámetro InputObject .

A partir de Windows PowerShell 3.0, hay dos maneras diferentes de construir un ForEach-Object comando.

  • Bloque de script. Puede usar un bloque de scripts para especificar la operación. Dentro del bloque de script, use la $_ variable para representar el objeto actual. El bloque de script es el valor del parámetro Process . El bloque de script puede contener cualquier script de PowerShell.

    Por ejemplo, el siguiente comando obtiene el valor de la propiedad ProcessName de cada proceso del equipo.

    Get-Process | ForEach-Object {$_.ProcessName}

    ForEach-Object admite los beginbloques , processy end como se describe en about_functions.

    Nota:

    Los bloques de script se ejecutan en el ámbito del autor de la llamada. Por lo tanto, los bloques tienen acceso a variables de ese ámbito y pueden crear nuevas variables que persistan en ese ámbito una vez completado el cmdlet.

  • Instrucción Operation. También puede escribir una instrucción operation, que es mucho más similar al lenguaje natural. Puede usar la instrucción de operación para especificar un valor de propiedad o llamar a un método. Las instrucciones de operación se presentaron en Windows PowerShell 3.0.

    Por ejemplo, el siguiente comando también obtiene el valor de la propiedad ProcessName de cada proceso del equipo.

    Get-Process | ForEach-Object ProcessName

  • Bloque de script en ejecución en paralelo. A partir de PowerShell 7.0, hay disponible un tercer conjunto de parámetros que ejecuta cada bloque de script en paralelo. El parámetro ThrottleLimit limita el número de scripts paralelos que se ejecutan a la vez. Como antes, use la $_ variable para representar el objeto de entrada actual en el bloque de script. Use la $using: palabra clave para pasar referencias de variables al script en ejecución.

    En PowerShell 7, se crea un nuevo espacio de ejecución para cada iteración de bucle para garantizar el aislamiento máximo. Esto puede ser un gran rendimiento y acierto de recursos si el trabajo que está realizando es pequeño en comparación con la creación de nuevos espacios de ejecución o si hay muchas iteraciones que realizan un trabajo significativo. A partir de PowerShell 7.1, los espacios de ejecución de un grupo de espacios de ejecución se reutilizan de forma predeterminada. El parámetro ThrottleLimit establece el tamaño del grupo de espacios de ejecución. El tamaño predeterminado del grupo de espacios de ejecución es 5. Todavía puede crear un nuevo espacio de ejecución para cada iteración mediante el modificador UseNewRunspace .

    De forma predeterminada, los bloques de scripts paralelos usan el directorio de trabajo actual del autor de la llamada que inició las tareas paralelas.

    Para obtener más información, consulte la sección NOTAS de este artículo.

Ejemplos

Ejemplo 1: Dividir enteros en una matriz

En este ejemplo se toma una matriz de tres enteros y se divide cada uno de ellos en 1024.

30000, 56798, 12432 | ForEach-Object -Process {$_/1024}

29.296875
55.466796875
12.140625

Ejemplo 2: Obtener la longitud de todos los archivos de un directorio

En este ejemplo se procesan los archivos y directorios del directorio $PSHOMEde instalación de PowerShell .

Get-ChildItem $PSHOME |
  ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; " " }}

Si el objeto no es un directorio, el bloque de script obtiene el nombre del archivo, divide el valor de su propiedad Length en 1024 y agrega un espacio (" ") para separarlo de la entrada siguiente. El cmdlet usa la propiedad PSISContainer para determinar si un objeto es un directorio.

Ejemplo 3: Operar en los eventos del sistema más recientes

En este ejemplo se escriben los 1000 eventos más recientes del registro de eventos del sistema en un archivo de texto. La hora actual se muestra antes y después de procesar los eventos.

$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 obtiene los 1000 eventos más recientes del registro de eventos del sistema y los almacena en la $Events variable . $Events A continuación, se canaliza al ForEach-Object cmdlet . El parámetro Begin muestra la fecha y hora actuales. A continuación, el parámetro Process usa el Out-File cmdlet para crear un archivo de texto denominado events.txt y almacena la propiedad message de cada uno de los eventos de ese archivo. Por último, el parámetro End se usa para mostrar la fecha y hora después de que se haya completado todo el procesamiento.

Ejemplo 4: Cambiar el valor de una clave del Registro

En este ejemplo se cambia el valor de la entrada del Registro RemotePath en todas las subclaves de la HKCU:\Network clave a texto en mayúsculas.

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

Puede usar este formato para cambiar la forma o el contenido de un valor de la entrada del Registro.

Cada subclave de la clave de red representa una unidad de red asignada que se vuelve a conectar al iniciar sesión. La entrada RemotePath contiene la ruta de acceso UNC de la unidad conectada. Por ejemplo, si asigna la unidad E: a \\Server\Share, se crea una subclave E en con el valor del Registro RemotePath establecido \\Server\Shareen HKCU:\Network .

El comando usa el Get-ItemProperty cmdlet para obtener todas las subclaves de la clave de red y el Set-ItemProperty cmdlet para cambiar el valor de la entrada del Registro RemotePath en cada clave. En el Set-ItemProperty comando , la ruta de acceso es el valor de la propiedad PSPath de la clave del Registro. Se trata de una propiedad del objeto de Microsoft .NET Framework que representa la clave del Registro, no una entrada del Registro. El comando usa el método ToUpper() del valor remotePath , que es una cadena REG_SZ.

Dado que Set-ItemProperty cambia la propiedad de cada clave, el ForEach-Object cmdlet es necesario para acceder a la propiedad .

Ejemplo 5: Uso de la variable automática $null

En este ejemplo se muestra el efecto de canalización de la $null variable automática al ForEach-Object cmdlet .

1, 2, $null, 4 | ForEach-Object {"Hello"}

Hello
Hello
Hello
Hello

Dado que PowerShell trata $null como un marcador de posición explícito, el ForEach-Object cmdlet genera un valor para $null como lo hace para otros objetos canalizaciones a él.

Ejemplo 6: Obtener valores de propiedad

En este ejemplo se obtiene el valor de la propiedad Path de todos los módulos de PowerShell instalados mediante el parámetro MemberName del ForEach-Object cmdlet .

Get-Module -ListAvailable | ForEach-Object -MemberName Path
Get-Module -ListAvailable | Foreach Path

El segundo comando es equivalente al primero. Usa el Foreach alias del ForEach-Object cmdlet y omite el nombre del parámetro MemberName , que es opcional.

El ForEach-Object cmdlet es útil para obtener valores de propiedad, ya que obtiene el valor sin cambiar el tipo, a diferencia de los cmdlets Format o el Select-Object cmdlet , que cambian el tipo de valor de propiedad.

Ejemplo 7: Dividir nombres de módulo en nombres de componente

En este ejemplo se muestran tres maneras de dividir dos nombres de módulo separados por puntos en sus nombres de componente. Los comandos llaman al método Split de cadenas. Los tres comandos usan una sintaxis diferente, pero son equivalentes e intercambiables. La salida es la misma para los tres casos.

"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

El primer comando usa la sintaxis tradicional, que incluye un bloque de script y el operador $_de objeto actual. Usa la sintaxis de puntos para especificar el método y los paréntesis para delimitar el argumento delimitador.

El segundo comando usa el parámetro MemberName para especificar el método Split y el parámetro ArgumentList para identificar el punto (.) como delimitador de división.

El tercer comando usa el alias Foreach del ForEach-Object cmdlet y omite los nombres de los parámetros MemberName y ArgumentList , que son opcionales.

Ejemplo 8: Uso de ForEach-Object con dos bloques de script

En este ejemplo, pasamos dos bloques de script de forma posicional. Todos los bloques de script se enlazan al parámetro Process . Sin embargo, se tratan como si se hubieran pasado a los parámetros Begin y Process .

1..2 | ForEach-Object { 'begin' } { 'process' }

begin
process
process

Ejemplo 9: Uso de ForEach-Object con más de dos bloques de script

En este ejemplo, pasamos cuatro bloques de script posicionalmente. Todos los bloques de script se enlazan al parámetro Process . Sin embargo, se tratan como si se hubieran pasado a los parámetros Begin, Process y End .

1..2 | ForEach-Object { 'begin' } { 'process A' }  { 'process B' }  { 'end' }

begin
process A
process B
process A
process B
end

Nota:

El primer bloque de script siempre se asigna al begin bloque, el último bloque se asigna al end bloque y los bloques entre se asignan al process bloque.

Ejemplo 10: Ejecución de varios bloques de script para cada elemento de canalización

Como se muestra en el ejemplo anterior, se asignan varios bloques de script mediante el parámetro Process a los parámetros Begin y End . Para evitar esta asignación, debe proporcionar valores explícitos para los parámetros Begin y End .

1..2 | ForEach-Object -Begin $null -Process { 'one' }, { 'two' }, { 'three' } -End $null

one
two
three
one
two
three

Ejemplo 11: Ejecución de scripts lentos en lotes paralelos

En este ejemplo se ejecuta un bloque de script que evalúa una cadena y se suspende durante un segundo.

$Message = "Output:"

1..8 | ForEach-Object -Parallel {
    "$using:Message $_"
    Start-Sleep 1
} -ThrottleLimit 4

Output: 1
Output: 2
Output: 3
Output: 4
Output: 5
Output: 6
Output: 7
Output: 8

El valor del parámetro ThrottleLimit se establece en 4 para que la entrada se procese en lotes de cuatro. La $using: palabra clave se usa para pasar la $Message variable a cada bloque de script paralelo.

Ejemplo 12: Recuperación de entradas de registro en paralelo

En este ejemplo se recuperan 50 000 entradas de registro de 5 registros del sistema en una máquina Windows local.

$logNames = 'Security','Application','System','Windows PowerShell','Microsoft-Windows-Store/Operational'

$logEntries = $logNames | ForEach-Object -Parallel {
    Get-WinEvent -LogName $_ -MaxEvents 10000
} -ThrottleLimit 5

$logEntries.Count

50000

El parámetro Parallel especifica el bloque de script que se ejecuta en paralelo para cada nombre de registro de entrada. El parámetro ThrottleLimit garantiza que los cinco bloques de script se ejecuten al mismo tiempo.

Ejemplo 13: Ejecutar en paralelo como un trabajo

En este ejemplo se crea un trabajo que ejecuta un bloque de script en paralelo, dos a la vez.

PS> $job = 1..10 | ForEach-Object -Parallel {
    "Output: $_"
    Start-Sleep 1
} -ThrottleLimit 2 -AsJob

PS> $job

Id     Name            PSJobTypeName   State         HasMoreData     Location      Command
--     ----            -------------   -----         -----------     --------      -------
23     Job23           PSTaskJob       Running       True            PowerShell    …

PS> $job.ChildJobs

Id     Name            PSJobTypeName   State         HasMoreData     Location      Command
--     ----            -------------   -----         -----------     --------      -------
24     Job24           PSTaskChildJob  Completed     True            PowerShell    …
25     Job25           PSTaskChildJob  Completed     True            PowerShell    …
26     Job26           PSTaskChildJob  Running       True            PowerShell    …
27     Job27           PSTaskChildJob  Running       True            PowerShell    …
28     Job28           PSTaskChildJob  NotStarted    False           PowerShell    …
29     Job29           PSTaskChildJob  NotStarted    False           PowerShell    …
30     Job30           PSTaskChildJob  NotStarted    False           PowerShell    …
31     Job31           PSTaskChildJob  NotStarted    False           PowerShell    …
32     Job32           PSTaskChildJob  NotStarted    False           PowerShell    …
33     Job33           PSTaskChildJob  NotStarted    False           PowerShell    …

El parámetro ThrottleLimit limita el número de bloques de script paralelos que se ejecutan a la vez. El parámetro AsJob hace que el ForEach-Object cmdlet devuelva un objeto de trabajo en lugar de transmitir la salida a la consola. La $job variable recibe el objeto de trabajo que recopila datos de salida y supervisa el estado de ejecución. La $job.ChildJobs propiedad contiene los trabajos secundarios que ejecutan los bloques de script paralelos.

Ejemplo 14: Uso de referencias de variables seguras para subprocesos

En este ejemplo se invocan bloques de script en paralelo para recopilar objetos Process con nombre único.

$threadSafeDictionary = [System.Collections.Concurrent.ConcurrentDictionary[string,object]]::new()
Get-Process | ForEach-Object -Parallel {
    $dict = $using:threadSafeDictionary
    $dict.TryAdd($_.ProcessName, $_)
}

$threadSafeDictionary["pwsh"]

NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
     82    82.87     130.85      15.55    2808   2 pwsh

Se pasa una sola instancia de un objeto ConcurrentDictionary a cada bloque de script para recopilar los objetos. Dado que ConcurrentDictionary es seguro para subprocesos, es seguro modificarlo cada script paralelo. Un objeto no seguro para subprocesos, como System.Collections.Generic.Dictionary, no sería seguro usarlo aquí.

Nota:

Este ejemplo es un uso muy ineficaz del parámetro Parallel . El script simplemente agrega el objeto de entrada a un objeto de diccionario simultáneo. Es trivial y no vale la pena invocar cada script en un subproceso independiente. La ejecución ForEach-Object normalmente sin el conmutador Parallel es mucho más eficaz y más rápida. Este ejemplo solo está pensado para demostrar cómo usar variables seguras para subprocesos.

Ejemplo 15: Escritura de errores con ejecución paralela

En este ejemplo se escribe en la secuencia de errores en paralelo, donde el orden de los errores escritos es aleatorio.

1..3 | ForEach-Object -Parallel {
    Write-Error "Error: $_"
}

Write-Error: Error: 1
Write-Error: Error: 3
Write-Error: Error: 2

Ejemplo 16: Finalización de errores en la ejecución en paralelo

En este ejemplo se muestra un error de terminación en un scriptblock en ejecución paralelo.

1..5 | ForEach-Object -Parallel {
    if ($_ -eq 3)
    {
        throw "Terminating Error: $_"
    }

    Write-Output "Output: $_"
}

Exception: Terminating Error: 3
Output: 1
Output: 4
Output: 2
Output: 5

Output: 3 nunca se escribe porque se finalizó el scriptblock paralelo para esa iteración.

Nota:

Las variables de parámetro comunes PipelineVariable no se admiten en Foreach-Object -Parallel escenarios incluso con la $using: palabra clave .

Ejemplo 17: Pasar variables en script paralelo anidado ScriptBlockSet

Puede crear una variable fuera de un Foreach-Object -Parallel scriptblock con ámbito y usarla dentro del scriptblock con la $using palabra clave .

$test1 = 'TestA'
1..2 | Foreach-Object -Parallel {
    $using:test1
}

TestA
TestA

# You CANNOT create a variable inside a scoped scriptblock
# to be used in a nested foreach parallel scriptblock.
$test1 = 'TestA'
1..2 | Foreach-Object -Parallel {
    $using:test1
    $test2 = 'TestB'
    1..2 | Foreach-Object -Parallel {
        $using:test2
    }
}

Line |
   2 |  1..2 | Foreach-Object -Parallel {
     |         ~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The value of the using variable '$using:test2' can't be retrieved because it has not been
     | set in the local session.

El scriptblock anidado no puede acceder a la $test2 variable y se produce un error.

Ejemplo 18: Creación de varios trabajos que ejecutan scripts en paralelo

El parámetro ThrottleLimit limita el número de scripts paralelos que se ejecutan durante cada instancia de ForEach-Object -Parallel. No limita el número de trabajos que se pueden crear al usar el parámetro AsJob . Dado que los propios trabajos se ejecutan simultáneamente, es posible crear una serie de trabajos paralelos, cada uno de los cuales se ejecuta hasta el número de límites de bloqueos de scripts simultáneos.

$jobs = for ($i=0; $i -lt 10; $i++) {
    1..10 | ForEach-Object -Parallel {
        ./RunMyScript.ps1
    } -AsJob -ThrottleLimit 5
}

$jobs | Receive-Job -Wait

En este ejemplo se crean 10 trabajos en ejecución. Cada trabajo no ejecuta más de 5 scripts simultáneamente. El número total de instancias que se ejecutan simultáneamente se limita a 50 (10 trabajos por el límite de 5).

Parámetros

-ArgumentList

Especifica una matriz de argumentos para una llamada de método. Para obtener más información sobre el comportamiento de ArgumentList, vea about_Splatting.

Este parámetro se incorporó en Windows PowerShell 3.0.

Type:Object[]
Aliases:Args
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-AsJob

Hace que la invocación paralela se ejecute como un trabajo de PowerShell. Se devuelve un único objeto de trabajo en lugar de la salida de los bloques de script en ejecución. El objeto de trabajo contiene trabajos secundarios para cada bloque de script paralelo que se ejecuta. Todos los cmdlets de trabajo de PowerShell pueden usar el objeto de trabajo para supervisar el estado en ejecución y recuperar datos.

Este parámetro se introdujo en PowerShell 7.0.

Type:SwitchParameter
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-Begin

Especifica un bloque de script que se ejecuta antes de que este cmdlet procese los objetos de entrada. Este bloque de script solo se ejecuta una vez para toda la canalización. Para obtener más información sobre el begin bloque, consulte about_Functions.

Type:ScriptBlock
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-Confirm

Le solicita su confirmación antes de ejecutar el cmdlet.

Type:SwitchParameter
Aliases:cf
Position:Named
Default value:False
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-End

Especifica un bloque de script que se ejecuta después de que este cmdlet procese todos los objetos de entrada. Este bloque de script solo se ejecuta una vez para toda la canalización. Para obtener más información sobre el end bloque, consulte about_Functions.

Type:ScriptBlock
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-InputObject

Especifica los objetos de entrada. ForEach-Object ejecuta la instrucción script block o operation en cada objeto de entrada. Especifique una variable que contenga los objetos o escriba un comando o una expresión que obtenga los objetos.

Cuando se usa el parámetro InputObject con ForEach-Object, en lugar de canalizar los resultados del comando a ForEach-Object, el valor InputObject se trata como un único objeto. Esto es true incluso si el valor es una colección que es el resultado de un comando, como -InputObject (Get-Process). Dado que InputObject no puede devolver propiedades individuales de una matriz o colección de objetos, se recomienda que si usa ForEach-Object para realizar operaciones en una colección de objetos para esos objetos que tienen valores específicos en propiedades definidas, se usa ForEach-Object en la canalización, como se muestra en los ejemplos de este tema.

Type:PSObject
Position:Named
Default value:None
Required:False
Accept pipeline input:True
Accept wildcard characters:False

-MemberName

Especifica la propiedad que se va a obtener o el método al que llamar.

Se permiten caracteres comodín, pero solo funcionan si la cadena resultante se resuelve en un valor único. Por ejemplo, si ejecuta Get-Process | ForEach -MemberName *Name, el patrón comodín coincide con más de un miembro que provoca un error en el comando.

Este parámetro se incorporó en Windows PowerShell 3.0.

Type:String
Position:0
Default value:None
Required:True
Accept pipeline input:False
Accept wildcard characters:True

-Parallel

Especifica el bloque de script que se va a usar para el procesamiento paralelo de objetos de entrada. Escriba un bloque de scripts que describa la operación.

Este parámetro se introdujo en PowerShell 7.0.

Type:ScriptBlock
Position:Named
Default value:None
Required:True
Accept pipeline input:False
Accept wildcard characters:False

-Process

Especifica la operación que se realiza en cada objeto de entrada. Este bloque de script se ejecuta para cada objeto de la canalización. Para obtener más información sobre el process bloque, consulte about_Functions.

Cuando se proporcionan varios bloques de script al parámetro Process , el primer bloque de script siempre se asigna al begin bloque . Si solo hay dos bloques de script, el segundo bloque se asigna al process bloque . Si hay tres o más bloques de script, el primer bloque de script siempre se asigna al begin bloque , el último bloque se asigna al end bloque y los bloques entre se asignan al process bloque.

Type:ScriptBlock[]
Position:0
Default value:None
Required:True
Accept pipeline input:False
Accept wildcard characters:False

-RemainingScripts

Especifica todos los bloques de script que el parámetro Process no toma.

Este parámetro se incorporó en Windows PowerShell 3.0.

Type:ScriptBlock[]
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-ThrottleLimit

Especifica el número de bloques de script que se ejecutan en paralelo. Los objetos de entrada se bloquean hasta que el recuento de bloques de script en ejecución se encuentra por debajo del LímiteLimit. El valor predeterminado es 5.

El parámetro ThrottleLimit limita el número de scripts paralelos que se ejecutan durante cada instancia de ForEach-Object -Parallel. No limita el número de trabajos que se pueden crear al usar el parámetro AsJob . Dado que los propios trabajos se ejecutan simultáneamente, es posible crear una serie de trabajos paralelos, cada uno de los cuales se ejecuta hasta el número de límites de bloqueos de scripts simultáneos.

Este parámetro se introdujo en PowerShell 7.0.

Type:Int32
Position:Named
Default value:5
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-TimeoutSeconds

Especifica el número de segundos que se van a esperar a que se procesen todas las entradas en paralelo. Después del tiempo de espera especificado, se detienen todos los scripts en ejecución. Y se omiten los objetos de entrada restantes que se van a procesar. El valor predeterminado de deshabilita el tiempo de 0 espera y ForEach-Object -Parallel se puede ejecutar indefinidamente. Al escribir Ctrl+C en la línea de comandos, se detiene un comando en ejecución.ForEach-Object -Parallel Este parámetro no se puede usar junto con el parámetro AsJob .

Este parámetro se introdujo en PowerShell 7.0.

Type:Int32
Position:Named
Default value:0
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-UseNewRunspace

Hace que la invocación paralela cree un nuevo espacio de ejecución para cada iteración de bucle en lugar de reutilizar los espacios de ejecución del grupo de espacios de ejecución.

Este parámetro se introdujo en PowerShell 7.1

Type:SwitchParameter
Position:Named
Default value:False
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-WhatIf

Muestra lo que sucedería si se ejecutara el cmdlet. El cmdlet no se ejecuta.

Type:SwitchParameter
Aliases:wi
Position:Named
Default value:False
Required:False
Accept pipeline input:False
Accept wildcard characters:False

Entradas

PSObject

Puede canalizar cualquier objeto a este cmdlet.

Salidas

PSObject

Este cmdlet devuelve objetos determinados por la entrada.

Notas

PowerShell incluye los siguientes alias para ForEach-Object:

  • Todas las plataformas:
    • %
    • foreach

El ForEach-Object cmdlet funciona de forma muy similar a la instrucción Foreach , excepto que no se puede canalizar la entrada a una instrucción Foreach . Para obtener más información sobre la instrucción Foreach , consulte about_Foreach.

A partir de PowerShell 4.0, Where y ForEach se agregaron métodos para su uso con colecciones. Puede obtener más información sobre estos nuevos métodos aquí about_arrays

Usar ForEach-Object -Parallel:

  • El ForEach-Object -Parallel conjunto de parámetros usa la API interna de PowerShell para ejecutar cada bloque de script en un nuevo espacio de ejecución. Esto es significativamente más sobrecarga que ejecutar ForEach-Object normalmente con procesamiento secuencial. Es importante usar Parallel donde la sobrecarga de ejecutarse en paralelo es pequeña en comparación con el trabajo que realiza el bloque de script. Por ejemplo:

    • Scripts intensivos de proceso en máquinas de varios núcleos
    • Scripts que pasan tiempo esperando resultados o realizando operaciones de archivo

    El uso del parámetro Parallel puede hacer que los scripts se ejecuten mucho más lentamente de lo normal. Especialmente si los scripts paralelos son triviales. Experimente con Parallel para descubrir dónde puede ser beneficioso.

  • Cuando se ejecuta en paralelo, los objetos decorados con ScriptProperties o ScriptMethods no se pueden garantizar que funcionen correctamente si se ejecutan en un espacio de ejecución diferente al que los scripts se asociaron originalmente a ellos.

    La invocación de scriptblock siempre intenta ejecutarse en su espacio de ejecución principal , independientemente de dónde se invoque realmente. Sin embargo, ForEach-Object -Parallel crea espacios de ejecución temporales que se eliminan después de su uso, por lo que ya no hay ningún espacio de ejecución para que los scripts se ejecuten en .

    Este comportamiento puede funcionar siempre que el espacio de ejecución principal siga existiendo. Sin embargo, es posible que no obtenga el resultado deseado si el script depende de variables externas que solo están presentes en el espacio de ejecución del autor de la llamada y no en el espacio de ejecución principal.

  • Los errores de no terminación se escriben en el flujo de errores del cmdlet a medida que se producen en los bloques de script en ejecución en paralelo. Dado que el orden de ejecución de scriptblock paralelo no es determinista, el orden en el que aparecen errores en la secuencia de errores es aleatorio. Del mismo modo, los mensajes escritos en otros flujos de datos, como la advertencia, el detalle o la información se escriben en esos flujos de datos en un orden indeterminado.

    Los errores de terminación, como excepciones, finalizan la instancia paralela individual de los bloques de script en los que se producen. Un error de terminación en un scriptblocks puede no provocar la terminación del Foreach-Object cmdlet. Los otros bloques de script, que se ejecutan en paralelo, continúan ejecutándose a menos que también encuentren un error de terminación. El error de terminación se escribe en el flujo de datos de error como errorRecord con un valor FullyQualifiedErrorId de PSTaskException. Los errores de terminación se pueden convertir en errores de no terminación mediante PowerShell try/catch o trap bloques.

  • Las variables de parámetro comunes PipelineVariable no se admiten en escenarios paralelos incluso con la $using: palabra clave .

    Importante

    El ForEach-Object -Parallel conjunto de parámetros ejecuta bloques de script en paralelo en subprocesos de proceso independientes. La $using: palabra clave permite pasar referencias de variables desde el subproceso de invocación de cmdlet a cada subproceso de bloque de script en ejecución. Dado que los bloques de script se ejecutan en subprocesos diferentes, las variables de objeto pasadas por referencia deben usarse de forma segura. Por lo general, es seguro leer de objetos a los que se hace referencia que no cambian. Pero si se está modificando el estado del objeto, debe usar objetos seguros para subprocesos, como los tipos System.Collection.Concurrent de .NET (vea el ejemplo 14).