ForEach-Object
Esegue un'operazione su ogni elemento in una raccolta di oggetti di input.
Sintassi
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>]
Descrizione
Il ForEach-Object
cmdlet esegue un'operazione su ogni elemento in una raccolta di oggetti di input. Gli oggetti di input possono essere inviati tramite pipe al cmdlet o specificati usando il parametro InputObject .
A partire da Windows PowerShell 3.0, esistono due modi diversi per costruire un ForEach-Object
comando.
Blocco script. È possibile usare un blocco di script per specificare l'operazione. All'interno del blocco di script usare la
$_
variabile per rappresentare l'oggetto corrente. Il blocco di script è il valore del parametro Process. Il blocco di script può contenere qualsiasi script di PowerShell.Ad esempio, il comando seguente ottiene il valore della proprietà ProcessName di ogni processo nel computer.
Get-Process | ForEach-Object {$_.ProcessName}
ForEach-Object
supporta ibegin
blocchi , eend
process
come descritto in about_functions.Nota
I blocchi di script vengono eseguiti nell'ambito del chiamante. Pertanto, i blocchi hanno accesso alle variabili nell'ambito e possono creare nuove variabili che persistono in tale ambito dopo il completamento del cmdlet.
Istruzione Operation. È anche possibile scrivere un'istruzione di operazione, che è molto più simile al linguaggio naturale. È possibile usare l'istruzione di operazione per specificare un valore di proprietà o chiamare un metodo. Le istruzioni di operazione sono state introdotte in Windows PowerShell 3.0.
Ad esempio, il comando seguente ottiene anche l valore della proprietà ProcessName di ogni processo nel computer.
Get-Process | ForEach-Object ProcessName
Blocco di script in esecuzione parallela. A partire da PowerShell 7.0, è disponibile un terzo set di parametri che esegue ogni blocco di script in parallelo. Il parametro ThrottleLimit limita il numero di script paralleli in esecuzione alla volta. Come in precedenza, usare la
$_
variabile per rappresentare l'oggetto di input corrente nel blocco di script. Usare la$using:
parola chiave per passare i riferimenti delle variabili allo script in esecuzione.In PowerShell 7 viene creato un nuovo runspace per ogni iterazione del ciclo per garantire l'isolamento massimo. Questa può essere una risorsa e prestazioni di grandi dimensioni se il lavoro che si sta facendo è piccolo rispetto alla creazione di nuovi spazi di esecuzione o se sono presenti molte iterazioni che eseguono un lavoro significativo. A partire da PowerShell 7.1, i runspace da un pool di runspace vengono riutilizzati per impostazione predefinita. Il parametro ThrottleLimit imposta le dimensioni del pool di runspace. La dimensione predefinita del pool di runspace è 5. È comunque possibile creare un nuovo runspace per ogni iterazione usando l'opzione UseNewRunspace .
Per impostazione predefinita, gli script paralleli usano la directory di lavoro corrente del chiamante che ha avviato le attività parallele.
Per altre informazioni, vedere la sezione NOTES di questo articolo.
Esempio
Esempio 1: Dividere gli interi in una matrice
Questo esempio accetta una matrice di tre numeri interi e li divide per 1024.
30000, 56798, 12432 | ForEach-Object -Process {$_/1024}
29.296875
55.466796875
12.140625
Esempio 2: Ottenere la lunghezza di tutti i file in una directory
In questo esempio vengono elaborati i file e le directory nella directory $PSHOME
di installazione di PowerShell.
Get-ChildItem $PSHOME |
ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; " " }}
Se l'oggetto non è una directory, il blocco di script ottiene il nome del file, divide il valore della relativa proprietà Length per 1024 e aggiunge uno spazio (" ") per separarlo dalla voce successiva. Il cmdlet usa la proprietà PSISContainer per determinare se un oggetto è una directory.
Esempio 3: Operare sugli eventi di sistema più recenti
In questo esempio vengono scritti 1000 eventi più recenti dal registro eventi di sistema a un file di testo. L'ora corrente viene visualizzata prima e dopo l'elaborazione degli eventi.
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
ottiene i 1000 eventi più recenti dal registro eventi di sistema e li pipe al ForEach-Object
cmdlet. Il parametro Begin visualizza la data e l'ora correnti. Il parametro Process usa quindi il Out-File
cmdlet per creare un file di testo denominato events.txt e archivia la proprietà del messaggio di ognuno degli eventi nel file. Infine, il parametro End viene usato per visualizzare la data e l'ora dopo il completamento dell'elaborazione.
Esempio 4: Modificare il valore di una chiave del Registro di sistema
In questo esempio viene modificato il valore della voce del Registro di sistema RemotePath in tutte le sottochiavi nella HKCU:\Network
chiave in testo maiuscolo.
Get-ItemProperty -Path HKCU:\Network\* |
ForEach-Object {
Set-ItemProperty -Path $_.PSPath -Name RemotePath -Value $_.RemotePath.ToUpper()
}
È possibile usare questo formato per modificare la forma o il contenuto del valore di una voce del Registro di sistema.
Ogni sottochiave nella chiave di rete rappresenta un'unità di rete mappata che riconnette all'accesso. La voce RemotePath contiene il percorso UNC dell'unità connessa. Ad esempio, se si esegue il mapping dell'unità E:
a \\Server\Share
, viene creata HKCU:\Network
una sottochiave E con il valore del Registro di sistema RemotePath impostato su \\Server\Share
.
Il comando usa il Get-ItemProperty
cmdlet per ottenere tutte le sottochiavi della chiave di rete e il Set-ItemProperty
cmdlet per modificare il valore della voce del Registro di sistema RemotePath in ogni chiave. Set-ItemProperty
Nel comando il percorso è il valore della proprietà PSPath della chiave del Registro di sistema. Si tratta di una proprietà dell'oggetto Microsoft .NET Framework che rappresenta la chiave del Registro di sistema, non una voce del Registro di sistema. Il comando usa il metodo ToUpper() del valore RemotePath , ovvero una stringa REG_SZ.
Poiché Set-ItemProperty
cambia la proprietà di ogni chiave, il ForEach-Object
cmdlet è necessario per accedere alla proprietà.
Esempio 5: Usare la variabile automatica $null
In questo esempio viene illustrato l'effetto del piping della $null
variabile automatica al ForEach-Object
cmdlet.
1, 2, $null, 4 | ForEach-Object {"Hello"}
Hello
Hello
Hello
Hello
Poiché PowerShell considera $null
come segnaposto esplicito, il ForEach-Object
cmdlet genera un valore per $null
come avviene per altri oggetti inoltrati.
Esempio 6: Ottenere i valori delle proprietà
Questo esempio ottiene il valore della proprietà Path di tutti i moduli di PowerShell installati usando il parametro MemberName del ForEach-Object
cmdlet.
Get-Module -ListAvailable | ForEach-Object -MemberName Path
Get-Module -ListAvailable | Foreach Path
Il secondo comando è equivalente al primo. Usa l'alias del cmdlet e omette il Foreach
nome del ForEach-Object
parametro MemberName , facoltativo.
Il ForEach-Object
cmdlet è utile per ottenere i valori delle proprietà, perché ottiene il valore senza modificare il tipo, a differenza dei cmdlet Format o del cmdlet, che modificano Select-Object
il tipo di valore della proprietà.
Esempio 7: Suddividere i nomi dei moduli in nomi dei componenti
In questo esempio vengono illustrati tre modi per dividere due nomi di modulo separati da punti nei nomi dei componenti. I comandi chiamano il metodo Split delle stringhe. I tre comandi usano una sintassi diversa, ma sono equivalenti e intercambiabili. L'output è lo stesso per tutti e tre i casi.
"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
Il primo comando usa la sintassi tradizionale, che include un blocco di script e l'operatore $_
dell'oggetto corrente. Usa la sintassi del punto per specificare il metodo e le parentesi per racchiudere l'argomento delimitatore.
Il secondo comando usa il parametro MemberName per specificare il metodo Split e il parametro ArgumentList per identificare il punto (.
) come delimitatore di divisione.
Il terzo comando usa l'alias Foreach del ForEach-Object
cmdlet e omette i nomi dei parametri MemberName e ArgumentList , facoltativi.
Esempio 8: Uso di ForEach-Object con due blocchi di script
In questo esempio vengono passati due blocchi di script in modo posizionato. Tutti i blocchi di script vengono associati al parametro Process . Tuttavia, vengono trattati come se fossero stati passati ai parametri Begin e Process .
1..2 | ForEach-Object { 'begin' } { 'process' }
begin
process
process
Esempio 9: Uso di ForEach-Object con più di due blocchi di script
In questo esempio vengono passati quattro blocchi di script in modo posizionato. Tutti i blocchi di script vengono associati al parametro Process . Tuttavia, vengono trattati come se fossero stati passati ai parametri Begin, Process e End .
1..2 | ForEach-Object { 'begin' } { 'process A' } { 'process B' } { 'end' }
begin
process A
process B
process A
process B
end
Nota
Il primo blocco di script viene sempre mappato al begin
blocco, l'ultimo blocco viene mappato al end
blocco e i due blocchi intermedi vengono mappati al process
blocco.
Esempio 10: Eseguire più blocchi di script per ogni elemento della pipeline
Come illustrato nell'esempio precedente, più blocchi di script passati usando il parametro Process vengono mappati ai parametri Begin e End . Per evitare questo mapping, è necessario specificare valori espliciti per i parametri Begin e End .
1..2 | ForEach-Object -Begin $null -Process { 'one' }, { 'two' }, { 'three' } -End $null
one
two
three
one
two
three
Esempio 11: Eseguire uno script lento in batch paralleli
In questo esempio viene eseguito un blocco di script che valuta una stringa e dorme per un secondo.
$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
Il valore del parametro ThrottleLimit è impostato su 4 in modo che l'input venga elaborato in batch di quattro.
La $using:
parola chiave viene usata per passare la $Message
variabile in ogni blocco di script paralleli.
Esempio 12: Recuperare le voci di log in parallelo
In questo esempio vengono recuperate 50.000 voci di log da 5 log di sistema in un computer Windows locale.
$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
Il parametro Parallel specifica il blocco di script eseguito in parallelo per ogni nome del log di input. Il parametro ThrottleLimit garantisce che tutti e cinque i blocchi di script vengano eseguiti contemporaneamente.
Esempio 13: Esecuzione in parallelo come processo
In questo esempio viene creato un processo che esegue un blocco di script in parallelo, due alla volta.
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 …
Il parametro ThrottleLimit limita il numero di blocchi di script paralleli in esecuzione alla volta. Il parametro AsJob fa sì che il cmdlet restituisca un oggetto processo anziché l'output ForEach-Object
di streaming nella console. La $job
variabile riceve l'oggetto processo che raccoglie i dati di output e monitora lo stato in esecuzione. La $job.ChildJobs
proprietà contiene i processi figlio che eseguono i blocchi di script paralleli.
Esempio 14: Uso di riferimenti a variabili thread-safe
In questo esempio vengono richiamati blocchi di script in parallelo per raccogliere oggetti Process denominati in modo univoco.
$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
Una singola istanza di un oggetto ConcurrentDictionary viene passata a ogni blocco di script per raccogliere gli oggetti. Poiché ConcurrentDictionary è thread-safe, è possibile modificarlo con ogni script parallelo. Un oggetto non thread-safe, ad esempio System.Collections.Generic.Dictionary, non è sicuro da usare qui.
Nota
Questo esempio è un uso inefficiente del parametro Parallel . Lo script aggiunge l'oggetto di input a un oggetto dizionario simultaneo. È semplice e non vale la pena richiamare ogni script in un thread separato. L'esecuzione ForEach-Object
senza l'opzione Parallel è più efficiente e veloce. Questo esempio è destinato solo a illustrare come usare le variabili thread-safe.
Esempio 15: Scrittura di errori con esecuzione parallela
Questo esempio scrive nel flusso di errori in parallelo, in cui l'ordine degli errori scritti è casuale.
1..3 | ForEach-Object -Parallel {
Write-Error "Error: $_"
}
Write-Error: Error: 1
Write-Error: Error: 3
Write-Error: Error: 2
Esempio 16: Terminazione degli errori nell'esecuzione parallela
In questo esempio viene illustrato un errore irreversibile in un blocco di script in esecuzione parallelo.
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
non viene mai scritto perché lo scriptblock parallelo per tale iterazione è stato terminato.
Nota
Le variabili di parametro comuni PipelineVariablenon sono supportate negli Foreach-Object -Parallel
scenari anche con la $using:
parola chiave .
Esempio 17: Passaggio di variabili nello script parallelo annidato ScriptBlockSet
È possibile creare una variabile all'esterno di un Foreach-Object -Parallel
blocco di script con ambito e usarla all'interno del blocco script con la $using
parola chiave .
$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.
Lo scriptblock annidato non può accedere alla $test2
variabile e viene generato un errore.
Esempio 18: Creazione di più processi che eseguono script in parallelo
Il parametro ThrottleLimit limita il numero di script paralleli in esecuzione durante ogni istanza di ForEach-Object -Parallel
. Non limita il numero di processi che è possibile creare quando si usa il parametro AsJob . Poiché i processi stessi vengono eseguiti simultaneamente, è possibile creare più processi paralleli, ognuno dei quali viene eseguito fino al numero limitato di blocchi di script simultanei.
$jobs = for ($i=0; $i -lt 10; $i++) {
1..10 | ForEach-Object -Parallel {
./RunMyScript.ps1
} -AsJob -ThrottleLimit 5
}
$jobs | Receive-Job -Wait
In questo esempio vengono creati 10 processi in esecuzione. Ogni processo non viene eseguito più di 5 script contemporaneamente. Il numero totale di istanze in esecuzione simultaneamente è limitato a 50 (10 processi volte il valore throttleLimit di 5).
Parametri
-ArgumentList
Specifica una matrice di argomenti per una chiamata al metodo. Per altre informazioni sul comportamento di ArgumentList, vedere about_Splatting.
Questo parametro è stato introdotto in Windows PowerShell 3.0.
Type: | Object[] |
Aliases: | Args |
Position: | Named |
Default value: | None |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-AsJob
Fa sì che la chiamata parallela sia eseguita come processo di PowerShell. Viene restituito un singolo oggetto processo anziché l'output dai blocchi di script in esecuzione. L'oggetto processo contiene processi figlio per ogni blocco di script parallelo eseguito. È possibile usare l'oggetto processo con uno dei cmdlet del processo di PowerShell per visualizzare lo stato di esecuzione e recuperare i dati.
Questo parametro è stato introdotto in PowerShell 7.0.
Type: | SwitchParameter |
Position: | Named |
Default value: | None |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-Begin
Specifica un blocco di script eseguito prima che questo cmdlet elabori tutti gli oggetti di input. Questo blocco di script viene eseguito una sola volta per l'intera pipeline. Per altre informazioni sul begin
blocco, vedere about_Functions.
Type: | ScriptBlock |
Position: | Named |
Default value: | None |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-Confirm
Richiede la conferma dell'utente prima di eseguire il cmdlet.
Type: | SwitchParameter |
Aliases: | cf |
Position: | Named |
Default value: | False |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-End
Specifica un blocco di script eseguito dopo l'elaborazione di tutti gli oggetti di input da parte di questo cmdlet. Questo blocco di script viene eseguito una sola volta per l'intera pipeline. Per altre informazioni sul end
blocco, vedere about_Functions.
Type: | ScriptBlock |
Position: | Named |
Default value: | None |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-InputObject
Specifica gli oggetti di input. ForEach-Object
esegue l'istruzione del blocco di script o dell'operazione in ogni oggetto di input. Immettere una variabile che contiene gli oggetti oppure digitare un comando o un'espressione che ottiene gli oggetti.
Quando si usa il parametro InputObject con ForEach-Object
, anziché i risultati del comando piping in ForEach-Object
, il valore InputObject viene considerato come un singolo oggetto. Questo vale anche se il valore è una raccolta che è il risultato di un comando, ad esempio -InputObject (Get-Process)
.
Poiché InputObject non può restituire singole proprietà da una matrice o da una raccolta di oggetti, è consigliabile usare per ForEach-Object
eseguire operazioni su una raccolta di oggetti per gli oggetti con valori specifici nelle proprietà definite, come ForEach-Object
illustrato negli esempi di questo argomento.
Type: | PSObject |
Position: | Named |
Default value: | None |
Required: | False |
Accept pipeline input: | True |
Accept wildcard characters: | False |
-MemberName
Specifica il nome della proprietà membro da ottenere o il metodo membro da chiamare. I membri devono essere membri dell'istanza, non membri statici.
I caratteri jolly sono consentiti, ma funzionano solo se la stringa risultante viene risolta in un valore univoco.
Ad esempio, se si esegue Get-Process | ForEach -MemberName *Name
, il modello con caratteri jolly corrisponde a più membri che causano l'esito negativo del comando.
Questo parametro è stato introdotto in Windows PowerShell 3.0.
Type: | String |
Position: | 0 |
Default value: | None |
Required: | True |
Accept pipeline input: | False |
Accept wildcard characters: | True |
-Parallel
Specifica il blocco di script da usare per l'elaborazione parallela di oggetti di input. Immettere un blocco di script che descrive l'operazione.
Questo parametro è stato introdotto in PowerShell 7.0.
Type: | ScriptBlock |
Position: | Named |
Default value: | None |
Required: | True |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-Process
Specifica l'operazione eseguita in ogni oggetto di input. Questo blocco di script viene eseguito per ogni oggetto nella pipeline. Per altre informazioni sul process
blocco, vedere about_Functions.
Quando si forniscono più blocchi di script al parametro Process , il primo blocco di script viene sempre mappato al begin
blocco. Se sono presenti solo due blocchi di script, il secondo blocco viene mappato al process
blocco. Se sono presenti tre o più blocchi di script, il primo blocco di script viene sempre mappato al begin
blocco, l'ultimo blocco viene mappato al end
blocco e i blocchi intermedi vengono mappati al process
blocco.
Type: | ScriptBlock[] |
Position: | 0 |
Default value: | None |
Required: | True |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-RemainingScripts
Specifica tutti i blocchi di script che non vengono presi dal parametro Process .
Questo parametro è stato introdotto in Windows PowerShell 3.0.
Type: | ScriptBlock[] |
Position: | Named |
Default value: | None |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-ThrottleLimit
Specifica il numero di blocchi di script eseguiti in parallelo. Gli oggetti di input vengono bloccati fino a quando il conteggio dei blocchi di script in esecuzione scende sotto l'oggetto ThrottleLimit. Il valore predefinito è 5
.
Il parametro ThrottleLimit limita il numero di script paralleli in esecuzione durante ogni istanza di ForEach-Object -Parallel
. Non limita il numero di processi che possono essere creati quando si usa il parametro AsJob . Poiché i processi stessi vengono eseguiti simultaneamente, è possibile creare un numero di processi paralleli, ognuno in esecuzione fino al numero limitato di scriptblock simultanei.
Questo parametro è stato introdotto in PowerShell 7.0.
Type: | Int32 |
Position: | Named |
Default value: | 5 |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-TimeoutSeconds
Specifica il numero di secondi in cui attendere l'elaborazione di tutti gli input in parallelo. Dopo il timeout specificato, tutti gli script in esecuzione vengono arrestati. Tutti gli oggetti di input rimanenti da elaborare vengono ignorati. Il valore predefinito di 0
disabilita il timeout e ForEach-Object -Parallel
può essere eseguito in modo indefinito. Digitando CTRL+C nella riga di comando viene arrestato un comando in esecuzione ForEach-Object -Parallel
. Questo parametro non può essere usato insieme al parametro AsJob .
Questo parametro è stato introdotto in PowerShell 7.0.
Type: | Int32 |
Position: | Named |
Default value: | 0 |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-UseNewRunspace
Causa la chiamata parallela per creare un nuovo runspace per ogni iterazione ciclo anziché riutilizzare gli spazi di esecuzione dal pool di runspace.
Questo parametro è stato introdotto in PowerShell 7.1
Type: | SwitchParameter |
Position: | Named |
Default value: | False |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-WhatIf
Mostra l'esito in caso di esecuzione del cmdlet. Il cmdlet non viene eseguito.
Type: | SwitchParameter |
Aliases: | wi |
Position: | Named |
Default value: | False |
Required: | False |
Accept pipeline input: | False |
Accept wildcard characters: | False |
Input
È possibile inviare tramite pipe qualsiasi oggetto a questo cmdlet.
Output
Questo cmdlet restituisce oggetti determinati dall'input.
Note
PowerShell include gli alias seguenti per ForEach-Object
:
- Tutte le piattaforme:
%
foreach
Il ForEach-Object
cmdlet funziona in modo molto simile all'istruzione Foreach , ad eccezione del fatto che non è possibile inviare tramite pipe l'input a un'istruzione Foreach . Per altre informazioni sull'istruzione Foreach , vedere about_Foreach.
A partire da PowerShell 4.0 Where
sono ForEach
stati aggiunti metodi per l'uso con le raccolte. Altre informazioni su questi nuovi metodi sono disponibili qui about_arrays
Utilizzo di ForEach-Object -Parallel
:
ForEach-Object -Parallel
esegue ogni blocco di script in un nuovo spazio di esecuzione. I nuovi spazi di esecuzione creano un sovraccarico notevolmente maggiore rispetto all'esecuzioneForEach-Object
con l'elaborazione sequenziale. È importante usare Parallel in cui il sovraccarico dell'esecuzione in parallelo è ridotto rispetto al lavoro eseguito dal blocco di script. Ad esempio:- Script a elevato utilizzo di calcolo in computer multicore
- Script che impiegano tempo in attesa dei risultati o che eseguono operazioni su file
L'uso del parametro Parallel può causare l'esecuzione degli script molto più lenta del normale. Soprattutto se gli script paralleli sono semplici. Sperimentare con Parallel per scoprire dove può essere utile.
Quando vengono eseguiti in parallelo, gli oggetti decorati con ScriptProperties o ScriptMethods non possono essere garantiti per funzionare correttamente se vengono eseguiti in uno spazio di esecuzione diverso rispetto agli script originariamente collegati.
La chiamata a Scriptblock tenta sempre di essere eseguita nello spazio di esecuzione home , indipendentemente dalla posizione in cui viene effettivamente richiamata. Tuttavia,
ForEach-Object -Parallel
crea spazi di esecuzione temporanei che vengono eliminati dopo l'uso, quindi non esiste più spazio di esecuzione per gli script da eseguire.Questo comportamento può funzionare finché lo spazio di esecuzione home esiste ancora. Tuttavia, è possibile non ottenere il risultato desiderato se lo script dipende da variabili esterne presenti solo nello spazio di esecuzione del chiamante e non nello spazio di esecuzione home.
Gli errori non irreversibili vengono scritti nel flusso di errore del cmdlet man mano che si verificano in paralleli scriptblock in esecuzione. Poiché l'ordine di esecuzione di scriptblock parallelo non è deterministico, l'ordine in cui gli errori vengono visualizzati nel flusso di errori è casuale. Analogamente, i messaggi scritti in altri flussi di dati, ad esempio avvisi, verbose o informazioni vengono scritti in tali flussi di dati in un ordine indeterminato.
Errori di terminazione, ad esempio le eccezioni, terminano la singola istanza parallela dei blocchi di script in cui si verificano. Un errore irreversibile in uno scriptblocks potrebbe non causare la chiusura del
Foreach-Object
cmdlet. Gli altri scriptblock, in esecuzione in parallelo, continuano a essere eseguiti a meno che non verifichino anche un errore irreversibile. L'errore di terminazione viene scritto nel flusso dei dati di errore come ErrorRecord con fullyQualifiedErrorId diPSTaskException
. Gli errori di terminazione possono essere convertiti in errori non irreversibili tramite PowerShelltry
/catch
otrap
blocchi.Le variabili di parametro comuni PipelineVariablenon sono supportate in scenari paralleli anche con la
$using:
parola chiave .Importante
Il set di
ForEach-Object -Parallel
parametri esegue blocchi di script in parallelo su thread di processo separati. La$using:
parola chiave consente di passare riferimenti a variabili dal thread di chiamata del cmdlet a ogni thread del blocco di script in esecuzione. Poiché i blocchi di script vengono eseguiti in thread diversi, le variabili oggetto passate per riferimento devono essere usate in modo sicuro. In genere è possibile leggere da oggetti a cui si fa riferimento che non cambiano. Se è necessario modificare lo stato dell'oggetto, è necessario usare oggetti thread-safe, ad esempio i tipi .NET System.Collection.Concurrent (vedere l'esempio 14).