Articles

ForEach and Where magic methods

ForEach and Where are two frequently used concepts that have been available in PowerShell since version 1 came out in 2006. ForEach tem estado disponível como uma declaração e um cmdlet (ForEach-Object), permitindo que você iterate através de uma coleção de objetos e tomar alguma ação uma vez para cada objeto nessa coleção. Onde está disponível como um cmdlet (onde-objeto), permitindo-lhe filtrar itens em uma coleção que não passam alguma condição, uma condição que pode ser avaliada usando as propriedades em objetos na coleção ou os próprios objetos que pertencem à coleção. A capacidade de tomar medidas em itens de uma coleção e a capacidade de filtrar uma coleção são recursos que são altamente úteis e estão incluídos em uma forma ou outra na lógica por trás de muitos scripts PowerShell, comandos e módulos, independentemente de que versão de PowerShell está sendo usada. Na verdade, eles são tão fortemente usados que eles têm sido uma área de foco para a melhoria do desempenho, funcionalidade e sintaxe nas versões PowerShell 3.0 e 4.0.

com o lançamento do Windows PowerShell 4.0, dois novos métodos “magic” foram introduzidos para tipos de coleção que fornecem uma nova sintaxe para acessar ForEach e onde as capacidades no Windows PowerShell. Estes métodos são apropriadamente chamados ForEach e onde. Eu chamo esses métodos de “magia” porque eles são bastante mágicos em como eles trabalham em PowerShell. Eles não aparecem na saída do Get-Member, mesmo que você aplique-Force E request-MemberType All. Se você arregaçar as mangas e escavar com reflexão, você pode encontrá-las; no entanto, isso requer uma pesquisa ampla, porque são métodos de extensão privada implementados em uma classe privada. No entanto, mesmo que eles não são descobríveis sem espreitar sob as capas, eles estão lá quando você precisa deles, eles são mais rápidos do que seus homólogos mais antigos, e eles incluem funcionalidade que não estava disponível em seus homólogos mais antigos, daí o sentimento “mágico” que eles deixam você com quando você usá-los em PowerShell. Infelizmente, esses métodos permanecem sem documentação até hoje, quase um ano desde que foram divulgados publicamente, tantas pessoas não percebem o poder que está disponível nesses métodos. Este artigo vai tentar corrigir isso, explicando onde eles podem ser usados e como eles funcionam para que você possa alavancar esta magia quando você usa PowerShell.

a note about PowerShell 3.0

Before I get into explaining how the ForEach and Where methods work, I need to mention something with respect to these two methods and PowerShell 3.0. Embora seja verdade que o ForEach e onde os métodos só foram disponibilizados em PowerShell 4.0 e versões posteriores, PowerShell 3.0 ainda é muito amplamente utilizado em muitos ambientes, e a menos que você esteja usando PowerShell em um ambiente que tenha padronizado em PowerShell 4.0 e mais tarde, você pode encontrar-se desejando que você poderia tirar proveito da sintaxe fornecida pelos novos métodos ao usar PowerShell 3.0. Senti que isso foi uma limitação que vale a pena abordar, assim como parte do TypePx módulo que eu recentemente publicado no GitHub e no PowerShell Galeria de Recurso (aka o PowerShellGet repositório público, atualmente em pré-visualização limitada), eu incluído ForEach e Onde métodos de script que são funcionalmente equivalentes aos métodos introduzidos no PowerShell 4.0 para que você possa aproveitar a nova sintaxe e funcionalidade, mesmo se você estiver usando o PowerShell 3.0. Há algumas deficiências nesta implementação, que irei destacar mais adiante neste artigo.

o método ForEach

ForEach é um método que lhe permite iterar rapidamente através de uma coleção de objetos e tomar alguma ação sobre cada objeto nessa coleção. Este método proporciona um desempenho mais rápido do que os seus homólogos mais antigos (a declaração foreach e o cmdlet ForEach-Object), e também simplifica algumas das acções mais comuns que você pode querer tomar sobre os objectos da colecção. Todos os objetos que são saída por este método são retornados em uma coleção genérica de Sistema de tipo.Coleccao.ObjectModel.Collection1.

Existem seis formas suportadas que você pode invocar este método, e cada uma delas será explicada em maior detalhe abaixo. Os argumentos suportados que podem ser usados ao invocar o método ForEach são os seguintes::

  • ForEach(scriptblock expressão)
  • ForEach(tipo convertToType)
  • ForEach(string propertyName)
  • ForEach(string propertyName, objeto newValue)
  • ForEach(string methodName)
  • ForEach(string methodName, object argumentos)
  • ForEach(scriptblock expressão, objeto de argumentos)

Note que estes são suportadas argumento emparelhamentos, e não em diferentes sobrecargas disponível para o método ForEach. Usando qualquer combinação de argumentos que não estes podem resultar em erros que não identificam claramente qual é o problema real.

ForEach(expressão de scriptblock) e ForEach (expressão de scriptblock, argumentos de objectos)

se passar uma expressão de bloco de script para o método ForEach, você é capaz de executar o mesmo tipo de tarefas que faria num bloco de script que você usaria com a declaração foreach ou com o cmdlet ForEach-Object. Além disso, como o cmdlet ForEach-Object, as variáveis $_ e $PSItem referenciam o item atual que está sendo processado. Quaisquer argumentos que você forneça para além do argumento do bloco de script inicial serão usados como argumentos para o bloco de script. Isto é exatamente como o parâmetro-ArgumentList funciona no cmdlet ForEach-Object. Aqui está um exemplo que demonstra como você pode usar isso para executar um bloco de script em cada item de uma coleção:

# Get a set of services$services = Get-Service c*# Display the names and display names of all services in the collection$services.foreach{"$($_.Name) ($($_.DisplayName))"}# Select a property name to expand using a script block argument$services.foreach({param($PropertyName); $_.$PropertyName}, 'DisplayName')

Você pode ter notado algo estranho sobre esta sintaxe, porque eu não enrole o bloco de script em si entre parênteses. Você pode embrulhá-lo entre parêntesis redondos, no entanto isso é opcional em PowerShell 4.0 ou mais tarde, porque o analisador PowerShell foi melhorado para permitir que os parêntesis sejam omitidos sempre que você estiver invocando um método que aceita um único argumento de bloco de script. Além disso, como a declaração foreach e o cmdlet ForEach-Object, o bloco de script que você fornece é invocado no escopo atual. Isso significa que todas as atribuições variáveis que você fizer dentro desse bloco de script Irão persistir depois que o método ForEach tiver terminado de executar.

ForEach (tipo converttótipo)

exclusivo para o método ForEach, pode passar um tipo para o método ForEach se quiser converter cada item de uma colecção para outro tipo. Por exemplo, imagine que você tem uma coleção de objetos e você quer converter esses objetos em seu equivalente string. Aqui está o que que seria parecido com o método ForEach:

# Get a collection of processes$processes = Get-Process# Convert the objects in that collection into their string equivalent$processes.foreach()

Você poderia ter realizado a mesma tarefa por typecasting a coleção em uma matriz de seqüência de caracteres de tipo (e.g. ]$processos), e typecasting a matriz é na verdade significativamente mais rápido, no entanto, há uma boa chance que você mesmo não iria notar a diferença no tempo de execução, a menos que você estava trabalhando com um número muito, muito grande coleção. Apesar da diferença de tempo, eu tenderei a preferir a sintaxe do método ForEach em certas situações, se me permite manter a elegância na implementação, evitando parênteses redondos extra nos scripts que escrevo.

ForEach(string propertyName)

No PowerShell 3.0 e posteriores, um segundo conjunto de parâmetros foi adicionado ao ForEach-Object para permitir que você para mais facilmente obter o valor de uma propriedade específica, passando simplesmente um nome de propriedade como o único parâmetro de valor para ForEach-Object. Esta conveniência foi oferecida no método ForEach também. Aqui está um exemplo que demonstra como você pode iterar através de uma coleção e de retorno de uma propriedade de coleção:

# Get all services whose name starts with "w"$services = Get-Service w*# Return the names of those services$services.foreach('Name')

claro, desde que a versão 3.0 do PowerShell, você pode simplesmente invocar $serviços.Nome para obter os nomes de todos os serviços, e que vai completar mais rápido do que o método ForEach alternativa (embora você só vai notar a diferença de desempenho em grandes coleções na ordem de centenas de milhares de objetos); no entanto, isso só funciona para propriedades que não estão na coleção em si, e é uma sintaxe com a qual alguns scripts não estão confortáveis devido à natureza implícita do que o comando faz. A nova sintaxe do método ForEach fornece-lhe uma alternativa mais explícita que tem o benefício adicional de ser um pouco mais auto-documentado também.

ForEach (string propertyName, object newValue)

não só pode obter uma propriedade numa colecção de objectos, como também pode definir uma propriedade numa colecção de objectos. Esta é uma funcionalidade que não está disponível no outro foreach’s, a menos que você explicitamente crie o bloco de script para fazê-lo. Para definir a propriedade, basta fornecer o nome da propriedade e o valor que você deseja usar ao definir essa propriedade, como este:

# Note, this is not a realistic example# This would be used more commonly on configuration data$services = Get-Service c*# Now change the display names of every service to some new value$services.foreach('DisplayName','Hello')

assim como as atribuições de que você faria usando o operador é igual, o PowerShell irá tentar converter o que você fornecer, como o novo valor para o tipo apropriado para a propriedade que está sendo atribuído.

ForEach(string methodName) e ForEach(string methodName, object argumentos)

Para chamar um método, basta fornecer o nome do método, como o primeiro argumento e, em seguida, os argumentos para o método como o segundo, terceiro, quarto, etc. argumento. Se o método não tomar quaisquer argumentos, você pode simplesmente passar no nome do método e ele será invocado sem quaisquer argumentos. Aqui está um exemplo mostrando como você poderia matar um monte de processos executando um programa específico:

# Get all processes running Chrome$processes = Get-Process -Name Chrome# Now kill all of those processes$processes.foreach('Kill')

Aqui está outro exemplo, desta vez usando um método com argumentos mostrando como você pôde verificar que os comandos são os seguintes melhores práticas através da utilização adequada nomes e apelidos para os parâmetros mais usados:

# Get all commands that have a ComputerName parameter$cmds = Get-Command -ParameterName ComputerName# Now show a table making sure the parameter names and aliases are consistent$cmds.foreach('ResolveParameter','ComputerName') | Format-Table Name,Aliases

Como você pode ver a partir desses resultados, há definitivamente algumas inconsistências na execução do ComputerName parâmetros que devem ser corrigidas.

Que abrange toda a funcionalidade que está atualmente disponível no método ForEach. Como você pode ver, não há muita funcionalidade nova oferecida neste método, mas as melhorias de sintaxe quando você está executando uma tarefa simples em uma coleção de objetos são agradáveis, e as melhorias de desempenho do método ForEach quando comparado com a declaração foreach equivalente para ForEach-objeto pipeline são definitivamente uma melhoria bem-vinda também. Com essa explicação fora do caminho, vamos avançar para o método de onde.

o método em que

Onde é um método que lhe permite filtrar uma colecção de objectos. Isto é muito parecido com o cmdlet onde-objeto, mas o método de onde também é como Selecionar-Objeto e Grupo-objeto, também, inclui várias características adicionais que o cmdlet onde-objeto não suporta nativamente por si só. Este método fornece um desempenho mais rápido do que onde-objeto em um comando simples e elegante. Como o método ForEach, quaisquer objetos que são saídos por este método são retornados em uma coleção genérica de Sistema de tipo.Coleccao.ObjectModel.Recolha 1.

Existe apenas uma versão deste método, que pode ser descrita da seguinte forma::

Where(scriptblock expression])

tal como indicado pelos parêntesis rectos, o bloco de expressões é obrigatório e a enumeração do modo e o argumento inteiro de retorno do número são opcionais, por isso você pode invocar este método usando 1, 2 ou 3 argumentos. Se você quiser usar um argumento particular, você deve fornecer todos os argumentos à esquerda desse argumento (ou seja, se você quiser fornecer um valor para a retenção de números, você deve fornecer valores para o modo e expressão também).

Where(scriptblock expression)

the most basic invocation of the Where method simply takes a script block expression as an argument. A expressão do bloco de script será avaliada uma vez para cada objeto na coleção que está sendo processada, e se ele retorna verdadeiro, o objeto será devolvido pelo método de onde. Este é o equivalente funcional de chamar o cmdlet onde-objeto e passá-lo um bloco de script. Como o cmdlet onde-Objeto, as variáveis $_ e $PSItem podem ser usadas para se referir ao item atual que está sendo processado dentro do bloco do script.

aqui está um exemplo muito simples, mostrando como você pode obter uma lista de serviços em execução.

# Get all services$services = Get-Service# Now filter out any services that are not running$services.where{$_.Status -eq 'Running'}

isto não oferece nenhuma funcionalidade nova, mas oferece um desempenho muito mais rápido do que onde-Object e a sintaxe é bastante fácil de seguir, por isso deverá considerar isto para os seus programas quando estiver a efectuar filtragem do lado do cliente das colecções que guardou numa variável.

Where (scriptblock expression, where Operatorselectionmode mode)

When you start looking at the optional parameters for the Where method, things start getting much more interesting. A versão 4.0 do Windows PowerShell incluiu uma nova enumeração com um nome de código do sistema.Gestao.Automacao.Onde é o código de selecção do operador. Note o sufixo desse nome escrito:”SelectionMode”. É usado para fornecer poderosas capacidades de seleção em uma sintaxe onde. Aqui estão os valores incluídos nesta enumeração, juntamente com suas definições:

por Omissão Filtro de coleção usando a expressão de bloco de script, para um máximo de contagem, se foi previsto ou padrão para todos os objetos na coleção, se não contagem máxima foi fornecida em numberToReturn.
Primeira Retornar o primeiro N objetos que passam a expressão bloco de script filtro, padronizando a apenas 1 objeto se uma contagem específica não foi solicitada em numberToReturn.
Last retorna o último N objetos que passam a expressão bloco de script filtro, padronizando a apenas 1 objeto se uma contagem específica não foi solicitada em numberToReturn.
SkipUntil Ignorar objetos na coleção até que um objeto passa a expressão de bloco de script filtro e, em seguida, retornar o primeiro N objetos, padrão para todos os objetos restantes se não contagem máxima foi fornecida em numberToReturn.
Até Retornar o primeiro N objetos em uma coleção até que um objeto passa a expressão de script filtro de bloqueio, padrão para todos os objetos que antecederam o primeiro objeto que o passado se não contagem máxima foi fornecida em numberToReturn.
Split Dividir a coleção em dois, colocando todos os objetos que passam a expressão bloco de script filtro para a primeira coleção, até um máximo de contagem se foi fornecida em numberToReturn, ou todos os objetos que passar se não contagem máxima foi fornecido, e a colocação de todos os outros objetos que não são colocadas na primeira coleção para a segunda coleta.

cada um destes oferece algum valor único quando você está processando coleções de dados, então eu vou fornecer mais detalhes de cada modo de seleção abaixo.

Default

Not surprisingly, the default value of the mode argument is ‘Default’. O modo de seleção padrão oferece a mesma funcionalidade que você obtém quando você não fornece um modo de seleção em tudo. Por exemplo, poderíamos ter escrito a última linha do nosso exemplo anterior como este:

# Now filter out any services that are not running$services.where({$_.Status -eq 'Running'},'Default')

neste exemplo, o argumento extra não é necessário, porém, porque ele faz exatamente a mesma coisa que ele faria se você não fornecer o argumento. Poderá também indicar o número máximo de objectos que deseja devolver ao usar o modo de selecção predefinido, usando o argumento de retorno de números, como este:

# Get the first 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'Default',10)

é importante notar que a funcionalidade exacta também está disponível ao usar o primeiro modo de selecção (de que falaremos num momento), por isso não é prático usar nenhum dos parâmetros opcionais quando estiver a usar o modo de selecção predefinido.

primeiro

como poderia ter adivinhado, o primeiro modo de selecção permite-lhe seleccionar o(s) Primeiro (s) objecto (s) na colecção que passa o filtro de expressão do bloco do programa. Quando você usar Primeiro sem um valor para o argumento de retorno de números, ou quando você usar primeiro com um valor de 0 para o argumento de retorno de números, apenas o primeiro objeto que passa o filtro será devolvido. Você pode opcionalmente especificar quantos objetos retornarão no argumento de retorno de números, caso em que muitos objetos serão retornados (assumindo que existem muitos objetos que passam pelo filtro).

Aqui estão alguns exemplos usando a nossa colecção de serviços que mostram o primeiro modo de selecção em acção:

# Get the first service in our collection that is running$services.where({$_.Status -eq 'Running'},'First')# Get the first service in our collection that is running$services.where({$_.Status -eq 'Running'},'First',1)# Get the first 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'First',10)

Note que o segundo comando nestes exemplos retorna os mesmos resultados como o primeiro comando, que é simplesmente explicitamente passando o valor padrão do numberToReturn argumento quando o Primeiro modo de seleção é usado.

Last

o último modo de selecção funciona muito como o primeiro modo de selecção, permitindo-lhe seleccionar os últimos objectos da colecção que passam pelo filtro de expressão do bloco de programas. Quando você usar o Último sem um valor para o numberToReturn argumento, ou quando você usar o Último, com um valor de 0 para a numberToReturn argumento, apenas o último objeto que passa o filtro será devolvido. Você pode opcionalmente especificar quantos objetos retornarão no argumento de retorno de números, caso em que muitos objetos serão retornados (assumindo que existem muitos objetos que passam pelo filtro).

Aqui estão alguns exemplos usando a nossa colecção de serviços que mostram o último modo de selecção em acção:

# Get the last service in our collection that is running$services.where({$_.Status -eq 'Running'},'Last')# Get the last service in our collection that is running$services.where({$_.Status -eq 'Running'},'Last',1)# Get the last 10 services in our collection that are running$services.where({$_.Status -eq 'Running'},'Last',10)

Também, como o Primeiro modo de seleção de exemplos, o segundo comando nestes exemplos retorna os mesmos resultados como o primeiro comando, que é simplesmente explicitamente passando o valor padrão do numberToReturn argumento quando o Último modo de seleção é usado.

SkipUntil

o modo de selecção do SkipUntil permite-lhe saltar todos os objectos numa colecção até encontrar um que passe o filtro de expressão do bloco do programa. Logo que encontre um objecto que passe o filtro, o modo SkipUntil irá devolver todos os objectos que restam na colecção se não tiver sido fornecido nenhum valor ou um valor de 0 ao argumento de retorno de números, ou irá devolver o primeiro N de objectos restantes na colecção se tiver sido fornecido um valor superior a zero ao argumento de retorno de números. Em ambos os casos, os resultados incluirão o primeiro objeto que passou pelo filtro.

Aqui estão alguns exemplos usando um subconjunto de nossa coleção de serviços para mostrar o modo de seleção SkipUntil em ação:

# Get a collection of services whose name starts with "c"$services = Get-Service c*# Skip all services until we find one with a status of "Running"$services.where({$_.Status -eq 'Running'},'SkipUntil')# Skip all services until we find one with a status of "Running", then# return the first 2$services.where({$_.Status -eq 'Running'},'SkipUntil',2)

até

o modo de selecção até que o modo de selecção forneça a funcionalidade oposta do modo de selecção do SkipUntil. Permite-lhe devolver objectos numa colecção até encontrar um que passe o filtro de expressão do bloco do programa. Uma vez que você encontrar um objeto que passa o filtro, o método de onde pára o processamento de objetos. Se você não fornecer um valor para o argumento de retorno de números, ou se você fornecer um valor de 0, o modo até a seleção irá retornar todos os objetos na coleção levando até o primeiro que passa o filtro de expressão de bloco de script. Se você fornecer um valor para o argumento de retorno de números que é maior que 0, o modo até que o modo de seleção irá retornar no máximo esse número de objetos, o que significa que ele pode nem mesmo encontrar um objeto que passa o filtro de expressão de bloco de script.

Aqui estão alguns exemplos usando um subconjunto diferente de nossa coleção de serviços para mostrar o modo até a seleção em ação:

# Get a collection of services whose name starts with "p"$services = Get-Service p*# Return all services until we find one with a status of "Stopped"$services.where({$_.Status -eq 'Stopped'},'Until')# Return the first 2 services unless we find one with a status of# "Stopped" first$services.where({$_.Status -eq 'Stopped'},'Until',2)

Split

Split selection mode is unique. Em vez de devolver um subconjunto da colecção com que começa numa nova colecção, devolve uma nova colecção que contém internamente duas colecções separadas. O que essas colecções aninhadas contêm depende da forma como usa o modo de selecção dividido. A divisão permite-lhe dividir uma colecção de objectos em dois. Por padrão, se você não fornecer um valor para o numberToReturn argumento ou se você fornecer um valor de 0 para a numberToReturn argumento, irá se Dividir coloque todos os objetos que passar o bloco de script expressão de filtro para o primeiro conjunto aninhado, e todos os outros objetos (aqueles que não passar o bloco de script expressão de filtro) para o segundo conjunto aninhado. Se você fornecer um valor superior a 0 para o argumento de retorno de números, a divisão irá limitar o tamanho da primeira coleção a essa quantidade máxima, e todos os objetos restantes na coleção, mesmo aqueles que correspondem ao filtro de expressão de bloco de script, serão colocados na segunda coleção.

Aqui estão alguns exemplos que mostram como o modo de selecção dividido pode ser usado para dividir uma colecção de objectos de diferentes formas:

# Get all services$services = Get-Service# Split the services into two groups: Running and not Running$running,$notRunning = $services.Where({$_.Status -eq 'Running'},'Split')# Show the Running services$running# Show the services that are not Running$notRunning# Split the services into the same two groups, but limit the Running group# to a maximum of 10 items$10running,$others = $services.Where({$_.Status -eq 'Running'},'Split',10)# Show the first 10 Running services$10running# Show all other services$others

como você pode ver a partir deste exemplo, Split é um modo de seleção bastante poderoso, fornecendo uma mistura de filtragem, agrupamento e seleção em uma única chamada de comando.

esta colecção de modos de selecção torna o método de onde rápido e elegante, mas ao mesmo tempo mais poderoso do que o objecto onde-objecto, Grupo-objecto e Select-objecto combinado numa única Conduta. O que há para não gostar disso?

deficiências no ForEach e quando os métodos de escrita em TypePx

como mencionei anteriormente neste artigo, escrevi extensões de tipo para PowerShell 3.0 e mais tarde e empacotá-los em um módulo chamado TypePx. TypePx é um módulo de script que foi escrito inteiramente em PowerShell, e é executado em PowerShell 3.0 ou mais tarde. Se você estiver usando PowerShell 3.0( e apenas se você estiver usando PowerShell 3.0), TypePx define ForEach e onde os métodos de script que imitam o comportamento do ForEach e onde os métodos em PowerShell 4.0 e mais tarde. Enquanto o sistema de tipo estendido em PowerShell torna possível imitar este comportamento, há algumas falhas devido à implementação estar em PowerShell que impactou o quão longe eu fui capaz de ir com essas extensões de tipo. Esta seção irá descrever algumas das diferenças e limitações que existem no ForEach e Onde métodos de script em TypePx que você pode querer estar ciente se você estiver usando o PowerShell 3.0.

Blocos de Script invocados a partir de um método de script executado em um escopo infantil

Ao contrário do ForEach e onde os métodos implementados como parte do PowerShell 4.0 ou mais tarde que invocam o bloco de script de expressão no escopo atual onde o método é chamado, o ForEach e onde os métodos de script implementados no PowerShell 3.0 invocam o bloco de script de expressão em um escopo-filho. Esta é uma limitação em PowerShell que tem estado lá desde o início (uma limitação, eu poderia acrescentar, que eu penso que é de longe a maior deficiência de PowerShell como uma língua).

devido a esta limitação, todas as variáveis que atribuir dentro de um bloco de script de expressão só serão modificadas no âmbito do filho. Isto tem implicações se o seu bloco de script de expressão pretende actualizar uma variável no âmbito em que invoca o ForEach ou onde. É improvável que isso causaria um problema ao usar onde, porque não é muito comum modificar variáveis em um bloco de script de expressão onde, mas em blocos de script ForEach isso pode ser um problema, então você precisa ter isso em mente se você usar essas extensões.

eu notar que eu gostaria de remover esta limitação completamente, e eu acredito que vai ser capaz de fazer isso, no entanto, no momento em que eu escrevi este artigo, eu ainda não implementou uma correcção para este.

a Maioria, mas não todas as coleções terão ForEach e que os métodos

No PowerShell 4.0 e posterior, o ForEach e que os métodos são magicamente disponibilizados para todos os tipos de implementar IEnumerable, exceto para a Cadeia, XmlNode, e tipos de implementar IDictionary. Em PowerShell, o sistema do tipo estendido não permite que Extensões sejam criadas para interfaces, apenas para tipos. Este é um desafio se você quiser criar uma extensão ampla como ForEach e onde. Na implementação atual dessas extensões em TypePx, o TypePx módulo encontra todos os tipos em todos os assemblies carregados no aplicativo atual domínio, e para todos os não-tipos genéricos que definem IEnumerable mas não IDictionary (excluindo Cadeia e XmlNode), além de para todos os tipos genéricos que definem IEnumerable mas não IDictionary genérico de coleções de PSObject, Object, String, Int32, ou Int64, ForEach e Onde métodos de script será criado.

isto cobre um grande número de tipos que no meu próprio teste foi suficiente, no entanto você pode correr em tipos onde você quer usar estes métodos e eles não estão disponíveis. Se for esse o caso, avise-me através do GitHub e verei o que posso fazer. Esta é também uma limitação que eu gostaria de remover, mas eu preciso de mais tempo para pesquisar como implementar a funcionalidade equivalente em um conjunto compilado onde eu posso ser capaz de defini-lo mais como ele é definido em PowerShell 4.0 e mais tarde.

scripts PowerShell não são tão rápidos quanto o código compilado

isto provavelmente vai sem dizer, mas quando você escreve algo em PowerShell, que é uma linguagem interpretada, ele não vai correr tão rapidamente quanto seria se você escreveu a lógica equivalente em uma linguagem como C#. Este é absolutamente o caso para o ForEach e onde métodos de script, que internamente usam ForEach-Object, Where-Object, e pipelining para imitar o comportamento do ForEach nativo e onde métodos. Neste caso, a vantagem de ter esses comandos vem da sintaxe elegante e funcionalidade que eles fornecem, além de ser capaz de usá-los em scripts para PowerShell 3.0 e 4.0. Os benefícios de desempenho em ForEach e Onde estão apenas na implementação nativa PowerShell 4.0.

PowerShell 3.0 requer parêntesis em torno de todos os parâmetros do método

mencionei nos exemplos acima que eu era capaz de invocar um método com um único parâmetro literal de bloco de script sem envolver esse bloco literal de script entre parêntesis adicionais. Essa capacidade existe apenas em PowerShell 4.0 ou mais tarde devido a melhorias que foram feitas para o analisador no lançamento. Em PowerShell 3.0, o analisador não suporta isso, então os parênteses são sempre necessários para o ForEach e onde os métodos de script para trabalhar com um único parâmetro literal de bloco de script nessa versão.

conclusão

Quando eu comecei a tentar imitar o comportamento do ForEach e onde os métodos mágicos em PowerShell 3.0, eu não percebi quanta funcionalidade eles forneceram. Escavar nos detalhes técnicos por trás destes métodos para que eu pudesse criar as extensões que eu queria no TypePx ajudou a descobrir todas as características escondidas nestes métodos muito poderosos, e eu estou muito feliz em compartilhar essas com você neste artigo. Espero que esta informação ajude a alavancar este maravilhoso novo conjunto de recursos em seu trabalho PowerShell, mesmo se você ainda está usando PowerShell 3.0. Feliz guião!