Realiza uma operação contra cada item de uma colecção de objectos de entrada.
Syntax
ForEach-Object <ScriptBlock> >]
ForEach-Object <String> >]
ForEach-Object -Parallel <scriptblock>
Descrição
O ForEach-Object
cmdlet realiza uma operação em cada item de uma colecção de objectos de entrada. Os objectos de entrada podem ser canalizados para o cmdlet ou especificados usando o parâmetro InputObject.
Iniciar no Windows PowerShell 3.0, há duas formas diferentes de construir um ForEach-Object
command.
-
bloco de script. Pode utilizar um bloco de script para especificar a operação. Dentro do bloco de script,use o
$_
variável para representar o objecto actual. O bloco de script é o valor do parâmetroProcesso. O bloco de script pode conter qualquer script PowerShell.Por exemplo, o seguinte comando obtém o valor da propriedade ProcessName de cada processo no computador.
Get-Process | ForEach-Object {$_.ProcessName}
ForEach-Object
suporta obegin
process
, eend
blocos tal como descritos em relação às_funções.Nota
Os blocos de script são executados no âmbito do autor da chamada. Portanto, os blocos têm acesso a variáveis nesse âmbito e podem criar novas variáveis que persistem nesse âmbito após a cmdlet ter sido concluída.
-
Declaração de operação. Também se pode escrever uma declaração de operação, que é muito mais parecida com uma linguagem natural. Pode utilizar a declaração de operação para especificar um valor de propriedade ou chamar um método. As instruções de operação foram introduzidas no Windows PowerShell 3.0.
Por exemplo, o seguinte comando também obtém o valor da propriedade ProcessName de cada processo no computador.
Get-Process | ForEach-Object ProcessName
bloco de script em paralelo. A partir do PowerShell 7.0, está disponível um terceiro conjunto de parâmetros que executa cada bloco de script em paralelo. O parâmetro ThrottleLimit limita então o número de scripts paralelos a correr de cada vez. Como antes, utilizar a variável $_
para representar o objecto de entrada corrente no bloco de scripts. Use o $using:
palavra-chave para passar referências variáveis para o script em execução.
No PowerShell 7, é criado um novo espaço de execução para cada iteração de loop para assegurar o máximo isolamento.Isto pode ser uma grande performance e um impacto de recursos se o trabalho que está a fazer for pequeno em comparação com a criação de novos espaços de execução ou se houver muitas iterações a executar trabalho significativo. A partir dePowerShell 7.1, os espaços de execução de um conjunto de espaços de execução são reutilizados por defeito. O tamanho da piscina do runspace é especificado pelo parâmetro ThrottleLimit. O tamanho padrão da reserva de espaço de execução é 5. Ainda é possível criar um novo espaço de execução para cada iteração utilizando a chave UseNewRunspace.
Por defeito, os blocos de script paralelos utilizam o directório de trabalho actual do chamador que iniciou as tarefas paralelas.
Erros não terminados são escritos no fluxo de erros cmdlet à medida que ocorrem em blocos de script paralelos. Como a ordem de execução dos blocos de script paralelos não pode ser determinada, a ordem em que os erros aparecem no fluxo de erros é aleatória. Da mesma forma, mensagens escritas noutros fluxos de dados, como avisos, verbos, ou informação são escritas nesses fluxos de dados numa ordem indeterminada.
Erros de terminação, tais como excepções, terminam a instância paralela individual dos blocos de script em que ocorrem. Um erro de terminação em um bloco de script não pode causar a terminação do Foreach-Object
cmdlet. Os outros blocos de script, funcionando em paralelo, continuam a funcionar, a menos que também encontrem um erro de terminação. O erro de terminação é escrito no fluxo de dados do theerror como um ErrorRecord com um ErroErrorId Totalmente Qualificado de PSTaskException
.Os erros de terminação podem ser convertidos em erros de não terminação usando PowerShell try/catch ou trapblocks.
Exemplos
Exemplo 1: Divide inteiros num array
Este exemplo pega num array de três inteiros e divide cada um deles por 1024.
30000, 56798, 12432 | ForEach-Object -Process {$_/1024}29.29687555.46679687512.140625
Exemplo 2: Obtenha o comprimento de todos os ficheiros num directório
Este exemplo processa os ficheiros e directórios no directório de instalação PowerShell $PSHOME
.
Get-ChildItem $PSHOME | ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; " " }}
Se o objecto não for um directório, o bloco de script recebe o nome do ficheiro, divide o valor da sua propriedade Length por 1024, e adiciona um espaço (” “) para o separar da entrada seguinte. Ocmdlet utiliza a propriedade PSISContainer para determinar se um objecto é um directório.
Exemplo 3: Operar nos eventos mais recentes do Sistema
Este exemplo escreve os 1000 eventos mais recentes do registo de eventos do Sistema para um ficheiro de texto. A hora actual é exibida antes e depois do processamento dos 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
obtém os 1000 eventos mais recentes do registo de eventos do Sistema e armazena-os na variável$Events
$Events
é então canalizado para a variável ForEach-Object
cmdlet. O parâmetro Begin exibe a data e hora actuais. A seguir, o parâmetro Process usa o Out-File
cmdlet para criar um ficheiro de texto que se chama events.txt e armazena a propriedade de mensagem de cada um dos eventos nesse ficheiro. Por último, o parâmetro Fim é utilizado para mostrar a data e hora depois de todo o processamento ter terminado.
Exemplo 4: Alterar o valor de uma chave de Registo
Este exemplo altera o valor da entrada do registo RemotePath em todas as subchaves sob oHKCU:\Network
chave para texto em maiúsculas.
P>Pode usar este formato para alterar a forma ou o conteúdo de uma entrada de registo.
Cada subchave na chave de Rede representa uma unidade de rede mapeada que volta a ligar-se ao iniciar a sessão. A entradaRemotePath contém o caminho UNC da unidade ligada. Por exemplo, se mapear a unidade E:drive para \\Server\Share
, é criada uma subchave E em HKCU:\Network
com o valor de registo do Caminho Remoto definido para \\Server\Share
.
O comando usa o Get-ItemProperty
cmdlet para obter todas as subchaves da chave de Rede e o comando Set-ItemProperty
cmdlet para alterar o valor da entrada de registo do Caminho Remoto em cada chave. No comando Set-ItemProperty
, o caminho é o valor da propriedade PSPath da chave de registo. Esta é uma propriedade do objecto Microsoft .NET Framework que representa a chave de registo, nota de entrada de registo. O comando usa o método ToUpper() do valor do Caminho Remoto, que é astring (REG_SZ).
p>Porque Set-ItemProperty
altera a propriedade de cada chave, o ForEach-Object
cmdlet é necessário para aceder à propriedade.
Exemplo 5: Usar a variável automática $Null
Este exemplo mostra o efeito de canalização da variável automática $Null
para a variável automática ForEach-Object
cmdlet.
1, 2, $null, 4 | ForEach-Object {"Hello"}HelloHelloHelloHello
Porque o PowerShell trata nulo como um suporte de lugar explícito, o ForEach-Object
cmdlet gera um aval para $Null
, tal como faz para outros objectos que lhe canaliza.
Exemplo 6: Obter valores de propriedade
Este exemplo obtém o valor da propriedade Path de todos os módulos PowerShell instalados utilizando o parâmetro MemberName do ForEach-Object
cmdlet.
Get-Module -ListAvailable | ForEach-Object -MemberName PathGet-Module -ListAvailable | Foreach Path
O segundo comando é equivalente ao primeiro. Utiliza o Foreach
alias do ForEach-Object
cmdlet e omite o nome do parâmetro MemberName, que é opcional.
O ForEach-Object
cmdlet é útil para obter valores de propriedade, pois obtém o valor sem alterar o tipo, ao contrário do formato cmdlets ou do Select-Object
cmdlet, que alteram o tipo de valor de propriedade.
Exemplo 7: Dividir os nomes dos módulos em nomes de componentes
Este exemplo mostra três formas de dividir dois nomes de módulos separados por pontos nos seus nomes de componentes.
"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 "."MicrosoftPowerShellCoreMicrosoftPowerShellHost
Os comandos chamam o método Split de cordas. Os três comandos utilizam uma sintaxe diferente, mas são equivalentes e intercambiáveis.
O primeiro comando utiliza a sintaxe tradicional, que inclui um bloco de script e o objectoperador actual $_
. Utiliza a sintaxe do ponto para especificar o método e os parênteses para delimitar o delimitador.
O segundo comando utiliza o parâmetro MemberName para especificar o método Split e o parâmetroArgumentName para identificar o ponto (“.”) como o delimitador dividido.
O terceiro comando usa o parámetro Foreach do ForEach-Object
cmdlet e omite os nomes dos parâmetros MemberName e ArgumentList, que são opcionais.
Exemplo 8: Usando ForEach-Object com dois blocos de script
Neste exemplo, passamos dois blocos de script em posição. Todos os blocos de script ligam-se ao parâmetroProcessar. Contudo, são tratados como se tivessem sido passados para os parâmetros Begin andProcess.
1..2 | ForEach-Object { 'begin' } { 'process' }beginprocessprocess
Exemplo 9: Usando ForEach-Object com mais de dois blocos de script
Neste exemplo, passamos dois blocos de script posicionados. Todos os blocos de script ligam-se ao parâmetroProcessar. No entanto, são tratados como se tivessem sido passados para os parâmetros Início, Processo e Fim.
1..2 | ForEach-Object { 'begin' } { 'process A' } { 'process B' } { 'end' }beginprocess Aprocess Bprocess Aprocess Bend
Nota
O primeiro bloco de script é sempre mapeado para o bloco begin
, o último bloco é mapeado para o blocoend
, e os blocos no meio são todos mapeados para o bloco process
.
Exemplo 10: Executar blocos de script múltiplos para cada item do gasoduto
Como mostrado no exemplo anterior, blocos de script múltiplos passados usando o parâmetro Processar são mapeados para os parâmetros Início e Fim. Para evitar este mapeamento, deve fornecer valores explícitos para os parâmetros Início e Fim.
1..2 | ForEach-Object -Begin $null -Process { 'one' }, { 'two' }, { 'three' } -End $nullonetwothreeonetwothree
Exemplo 11: Executar script lento em lotes paralelos
Este exemplo executa um bloco de script simples que avalia uma string e dorme durante um segundo.
$Message = "Output:"1..8 | ForEach-Object -Parallel { "$using:Message $_" Start-Sleep 1} -ThrottleLimit 4Output: 1Output: 2Output: 3Output: 4Output: 5Output: 6Output: 7Output: 8
O valor do parâmetro ThrottleLimit é definido para 4 de modo a que a entrada seja processada em lotes de quatro.O $using:
palavra-chave é usada para passar o $Message
variável em cada bloco de script paralelo.
Exemplo 12: Recuperar entradas de log em paralelo
Este exemplo recupera 50.000 entradas de log de 5 logs de sistema numa 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.Count50000
O parâmetro Paralelo especifica o bloco de script que é executado em paralelo para cada logname de entrada. O parâmetro ThrottleLimit assegura que todos os cinco blocos de script sejam executados ao mesmo tempo.
Exemplo 13: Executar em paralelo como um job
Este exemplo executa um bloco de script simples em paralelo, criando dois jobs de fundo de cada vez.
$job = 1..10 | ForEach-Object -Parallel { "Output: $_" Start-Sleep 1} -ThrottleLimit 2 -AsJob$job | Receive-Job -WaitOutput: 1Output: 2Output: 3Output: 4Output: 5Output: 6Output: 7Output: 8Output: 9Output: 10
the $job
variável recebe o objecto job que recolhe os dados de saída e monitoriza o estado de execução. O objecto job é canalizado para Receive-Job
com o parâmetro Wait switch. E este fluxo de saída para a consola, tal como se ForEach-Object -Parallel
fosse executado sem AsJob.
Exemplo 14: Usando referências de variáveis seguras de thread
Este exemplo invoca blocos de script em paralelo para recolher objectos de Processo de nome único.
$threadSafeDictionary = ]::new()Get-Process | ForEach-Object -Parallel { $dict = $using:threadSafeDictionary $dict.TryAdd($_.ProcessName, $_)}$threadSafeDictionaryNPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName ------ ----- ----- ------ -- -- ----------- 82 82.87 130.85 15.55 2808 2 pwsh
Uma única instância de um objecto de Dicionário Concorrente é passada para cada bloco de script para recolher os objectos. Uma vez que o ConcurrentDictionary é seguro para threads, é seguro ser modificado por cada script paralelo. Um objecto não seguro para threads, como System.Collections.Generic.Dictionary, não seria seguro de utilizar aqui.
Nota
Este exemplo é uma utilização muito ineficiente do parâmetro Paralelo. O script simplesmente adiciona o inputobjecto a um objecto de dicionário concorrente. É trivial e não vale a sobrecarga de invocar cada script numa linha separada. Correr ForEach-Object
normalmente sem o Parallelswitch é muito mais eficiente e rápido. Este exemplo destina-se apenas a demonstrar como utilizar variáveis seguras.
Exemplo 15: Erros de escrita com execução paralela
Este exemplo escreve no fluxo de erros em paralelo, onde a ordem dos erros escritos é aleatória.
1..3 | ForEach-Object -Parallel { Write-Error "Error: $_"}Write-Error: Error: 1Write-Error: Error: 3Write-Error: Error: 2
Exemplo 16: Erros de terminação em execução paralela
Este exemplo demonstra um erro de terminação num bloco de script paralelo em execução.
1..5 | ForEach-Object -Parallel { if ($_ -eq 3) { throw "Terminating Error: $_" } Write-Output "Output: $_"}Exception: Terminating Error: 3Output: 1Output: 4Output: 2Output: 5
Output: 3
nunca é escrito porque o bloco de script paralelo para essa iteração foi terminado.
Exemplo 17: Passagem de variáveis em script paralelo aninhado ScriptBlockSet
É possível criar uma variável fora de um Foreach-Object -Parallel
scoped scriptblock e utilizá-la dentro do scriptblock com a palavra-chave $using
.
$test1 = 'TestA'1..2 | Foreach-Object -Parallel { $using:test1}TestATestA# 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' cannot be retrieved because it has not been set in the local session.
O bloco de script aninhado não pode aceder à variável $test2
e é lançado um erro.
Parametros
Especifica uma série de argumentos para uma chamada de método. Para mais informações sobre o comportamento deArgumentList, ver about_Splatting.
Este parâmetro foi introduzido no Windows PowerShell 3.0.
Type: | Object |
Aliases: | Args |
Posição: | Nome |
Valor por defeito: | Nenhum |
Aceitar entrada de gasoduto: | False |
Aceitar caracteres wildcard: | False |
P>Causa a invocação paralela para correr como um trabalho PowerShell. Um único objecto de trabalho é devolvido em vez da saída dos blocos de script em execução. O objecto de trabalho contém trabalhos filhos para cada bloco de script paralelo que corre. O objecto de trabalho pode ser usado por todos os cmdlets de trabalho PowerShell, para monitorizar o estado de execução e recuperar dados.
Este parâmetro foi introduzido no PowerShell 7.0.
Type: | SwitchParameter |
Position: | Nome |
Valor por defeito: | Nenhum |
Aceitar entrada da conduta: | False |
Aceitar caracteres wildcard: | False |
Escreve um bloco de script que corre antes deste cmdlet processar quaisquer objectos de entrada. Este bloco de script é executado apenas uma vez para todo o pipeline. Para mais informações sobre o bloco begin
, versobre_Funções.
Type: | ScriptBlock |
Posição: | Nome |
Valor por defeito: | Nenhum |
Aceitar entrada da conduta: | False |
False |
P>Procede para confirmação antes de executar o cmdlet.
Type: | SwitchParameter |
cf | |
Position: | Nome |
Valor por defeito: | False |
Aceitar entrada do gasoduto: | False |
Aceitar caracteres wildcard: | False |
p> Especifica um bloco de script que corre após este cmdlet processa todos os objectos de entrada. Este bloco de script é executado apenas uma vez para todo o pipeline. Para mais informações sobre o bloco end
, versobre_Funções.
Type: | ScriptBlock |
Posição: | Nome |
Valor por defeito: | Nenhum |
Aceitar entrada da conduta: | False |
Aceitar caracteres wildcard: | False |
Especifica os objectos de entrada. ForEach-Object
executa o bloco de script ou a declaração de operação em cada objecto de entrada. Introduz uma variável que contenha os objectos, ou escreve um comando ou expressão que obtenha os objectos.
Quando se usa o parâmetro InputObject com ForEach-Object
, em vez de piping command resultsto ForEach-Object
, o valor InputObject é tratado como um único objecto. Isto é verdade mesmo que o valor seja uma colecção resultante de um comando, tal como -InputObject (Get-Process)
.Porque o InputObject não pode devolver propriedades individuais de um array ou colecção de objectos, recomendamos que se usar ForEach-Object
para realizar operações sobre uma colecção de objectos de propriedades definidas, use ForEach-Object
na linha de navegação, como mostram os exemplos neste tópico.
Type: | PSObject |
Posição: | Nome |
Valor por defeito: | Nenhum |
Aceitar entrada da conduta: | Verdade |
Aceitar caracteres wildcard: | False |
Especifica a propriedade a obter ou o método a chamar.Por exemplo, se correr Get-Process | ForEach -MemberName *Name
, o padrão de wildcard corresponde mais do que um membro causando a falha do comando.
Este parâmetro foi introduzido no Windows PowerShell 3.0.
Type: | String |
Posição: | 0 |
Valor por defeito: | Nenhum |
Conceito de entrada do pipeline: | False |
Aceitar caracteres wildcard: | True |
Especifica o bloco de script a ser utilizado para processamento paralelo de objectos de entrada. Introduzir um bloco de script que descreve a operação.
Este parâmetro foi introduzido no PowerShell 7.0.
Type: | ScriptBlock |
Posição: | Nome |
Valor por defeito: | Nenhum |
Aceitar entrada da conduta: | False |
Aceitar caracteres wildcard: | False |
Especifica a operação que é executada em cada objecto de entrada. Este bloco de script é executado para cada objecto no pipeline. Para mais informações sobre o bloco process
, versobre_Funções.
Quando fornece blocos de script múltiplos ao parâmetro Process, o primeiro bloco de script é sempre mapeado para o bloco begin
. Se houver apenas dois blocos de script, o segundo bloco é mapeado para o bloco process
. Se houver três ou mais blocos de script, o primeiro bloco de script é sempre mapeado para o bloco begin
, o último bloco é mapeado para o bloco end
, e os blocos no meio são todos mapeados para o bloco process
.
Type: | ScriptBlock |
Posição: | 0 |
Valor por defeito: | Nenhum |
Aceitar entrada da conduta: | False |
Aceitar caracteres wildcard: | False |
Especifica todos os blocos de script que não são tomados pelo parâmetro Processar.
Este parâmetro foi introduzido no Windows PowerShell 3.0.
Especifica o número de blocos de script que em paralelo. Os objectos de entrada são bloqueados até que a contagem de blocos de script em execução caia abaixo do ThrottleLimit. O valor por defeito é 5
.
Este parâmetro foi introduzido no PowerShell 7.0.
Type: | Int32 |
Posição: | Nomeado |
Valor por defeito: | 5 |
Conceito de entrada do gasoduto: | False |
Aceitar caracteres wildcard: | False |
Especifica o número de segundos para esperar que toda a entrada seja processada em paralelo. Após este tempo limite especificado, todos os scripts em execução são interrompidos. E quaisquer objectos de entrada restantes a serem beprocessados são ignorados. Valor por defeito de 0
desactiva o timeout, e ForEach-Object -Parallel
canrun indefinidamente. Ao digitar Ctrl+C na linha de comando pára uma execuçãoForEach-Object -Parallel
comando. Este parâmetro não pode ser usado juntamente com o AsJobparameter.
Este parâmetro foi introduzido no PowerShell 7.0.
Type: | Int32 |
Posição: | Nomeado |
Valor por defeito: | 0 |
Recceptar entrada de gasoduto: | False |
False |
Mostra o que aconteceria se o cmdlet funcionasse. O cmdlet não é executado.
Type: | SwitchParameter |
wi | |
Position: | Named |
Valor por defeito: | False |
Aceitar entrada de gasodutos: | False |
Aceitar caracteres wildcard: | False |
Inputs
PSObject
Pode canalizar qualquer objecto para este cmdlet.
Entradas
PSObject
Este cmdlet devolve objectos que são determinados pela entrada.
Notas
- p> O
ForEach-Object
cmdlet funciona muito como a declaração Foreach, excepto que não se pode canalizar a entrada para uma declaração Foreach. Para mais informações sobre a declaração de Foreach, ver sobre_Foreach. -
Iniciar em PowerShell 4.0,
Where
eForEach
foram adicionados métodos para utilização com colecções. Pode ler mais sobre estes novos métodos aqui sobre_arrays -
O conjunto de parâmetros
ForEach-Object -Parallel
utiliza o API interno do PowerShell para executar cada bloco de script. Isto é significativamente mais sobrecarregado do que correrForEach-Object
normalmente com processamento sequencial. É importante utilizar Paralelo onde a sobrecarga de correr em paralelo é pequena, para trabalhar o bloco de script executa. Por exemplo:- Compute scripts intensivos em máquinas multi-core
- Scripts que passam tempo à espera de resultados ou a fazer operações de ficheiro
Usar o parâmetro Paralelo pode fazer com que os scripts sejam executados muito mais lentamente do que o normal. Especialmente se os scripts paralelos forem triviais. Experimente com Paralelo para descobrir onde pode bebereneficial.
Importante
O parâmetro
ForEach-Object -Parallel
executa blocos de scripts em paralelo em procstreads separados. O$using:
palavra-chave permite passar referências variáveis da invocação cmdlet para cada linha de bloco de script em execução. Uma vez que os blocos de script rodam em diferentes threads, as variáveis do objecto passadas por referência devem ser utilizadas com segurança. Geralmente é seguro ler a partir de objectos referenciados que não mudam. Mas se o estado do objecto estiver a ser modificado, então deve utilizar objectos seguros de threads, tais como .Net System.Collection.Concurrent types (Ver Exemplo 11).
- Compare-Objecto
- Where-Objecto
- Grupo-Objecto
- Measure-Objecto
- Novo-Objecto
- Select-Objecto
- Sort-Objecto
- Tee-Objecto