Windows PowerShell com o WPF

Segredos para criar um aplicativo do WPF no Windows PowerShell

Doug Finke

Baixar o código de exemplo

O Windows PowerShell oferece uma nova classe de automação de tarefas. Ele não substitui as tecnologias antigas, mas as expande. Usar o Windows PowerShell (doravante, simplesmente PowerShell, para fins de brevidade) não significa que você terá que refazer seu aplicativo para aproveitar suas vantagens. Em vez disso, você pode usar o PowerShell para expandir e integrar-se de maneira contínua àquilo que você já tem.

O PowerShell é uma tecnologia de automação apresentada como uma interface de linha de comando (CLI), linguagem de criação de scripts e API.

Neste artigo, vou analisar importantes técnicas do PowerShell e apresentar uma calculadora de valor presente (bit.ly/7oEij1) com uma GUI do Windows Presentation Foundation (WPF) (consulte a Figura 1).

The PowerShell Present Value Calculator

Figura 1 A calculadora de valor presente do PowerShell

Apresentarei vários elementos-chave do PowerShell: o WPF PowerShell Kit (WPK); o pipeline de objeto; funções; PSObjects com propriedades; integração perfeita com o Microsoft .NET Framework; módulos e muito mais.

O PowerShell é criado no .NET Framework, permitindo que você acesse de maneira tranquila a estrutura, da mesma maneira que o faria a partir de outras linguagens .NET. Além disso, você tem acesso ao restante do sistema operacional Windows e de seus componentes, como serviços, processos e Windows Management Instrumentation (WMI), e acesso a servidores remotos (que também têm o PowerShell versão 2 e o Windows Remote Management habilitados).

Tudo isso é obtido com a nova linguagem de script exposta pelo PowerShell. Tudo que é preciso é o Bloco de Notas e alguns cmdlets do PowerShell (pronuncia-se “command-lets”, um cmdlet é um comando simples, usado no ambiente do PowerShell). A boa notícia é que eles estão prontos para ser usados. Os cmdlets são incorporados ao PowerShell, e o Bloco de Notas vem com o Windows. Os três principais cmdlets são: Get-Help, que exibe informações sobre os comandos e conceitos do PowerShell; Get-Command, que obtém informações básicas sobre cmdlets e outros elementos dos comandos do PowerShell; e Get-Member, que obtém os “membros” (propriedades e métodos) dos objetos.

Tudo é uma questão de descoberta, e esses cmdlets o ajudam a navegar por essa nova plataforma de automação de tarefas.

Vamos começar

Pergunta: Quantas linhas de código são necessárias para se criar um aplicativo do WPF com um rótulo dizendo “Olá, Mundo”?

Resposta: Duas, se você estiver usando o PowerShell e o WPK, como mostrado na Figura 2.

A Two-Line PowerShell WPF Application

Figura 2 Um aplicativo PowerShell do WPF de duas linhas

Este é um aplicativo do WPF completo, escrito em duas linhas do PowerShell. Linha 1, Import-Module WPK, importa o pacote WPK, que contém um conjunto de cmdlets do PowerShell que encapsulam o WPF. Curiosamente, você não precisa do Visual Studio, do XAML, nem do C# para fazer isso funcionar. No entanto, você precisa sim instalar o WPK (consulte a próxima seção).

O PowerShell versão 2 encontra-se disponível pronto para uso com o Windows 7 e com o Windows Server 2008 R2 (e pode-se descarregá-lo para sistemas Windows mais antigos). Ao mesmo tempo em que os sistemas operacionais para cliente e servidor foram lançados, foi lançado o pacote PowerShell (como um download separado), incluindo o WPK. É um reconhecimento à popular ferramenta de scripts do Unix, a Tcl/Tk.

Vou começar criando um aplicativo a partir de um conjunto simples de variáveis do PowerShell para um aplicativo interativo do WPF. Usarei o Ambiente de script integrado do PowerShell (ISE).

Quer me acompanhar?

Se você tem o Windows 7, está quase pronto para começar (lembre-se de que o PowerShell vem incorporado).

Se não estiver executando o Windows 7, descarregue e instale o PowerShell para sistemas operacionais antigos. Certifique-se de selecionar o download para o sistema operacional correto. Consulte o pacote do Windows Management Framework Core (bit.ly/9POYjq).

Qualquer que seja sua versão de sistema operacional, será necessário baixar e instalar o WPK (bit.ly/dFVpfL). Parte do Windows 7 Resource Kit contém outros nove módulos do PowerShell, inclusive um pacote ISE para uso com o PowerShell ISE. O ISE encontra-se disponível pronto para uso com o PowerShell versão 2. O pacote ISE é também um excelente recurso de aprendizado, mostrando como personalizar o ISE em vários níveis.

Uma vez inicializado o PowerShell, execute este cmdlet: Set-ExecutionPolicy RemoteSigned. Para uso imediato, o PowerShell é configurado para não executar scripts; este é um recurso de segurança, e os usuários do PowerShell precisam substituí-lo. Para que Set-ExecutionPolicy funcione, você precisa ter direitos de administrador e executar o PowerShell explicitamente como um administrador, clicando com o botão direito no arquivo de programa do PowerShell e selecionando “Executar como Administrador”.

Baixe e descompacte os scripts do código para download que acompanha este artigo. O modo mais simples de executar o aplicativo é fazê-lo no ISE. No Windows 7, você pode clicar em Iniciar e digitar ISE. (observação: você não pode executar scripts do PowerShell — que tenham uma extensão de arquivo .ps1 — clicando duas vezes sobre eles. A maneira mais fácil de executar scripts de exemplo é inicializar o ISE e usar Arquivo | Abrir para abrir o arquivo do script.)

PowerShell 101

Vou criar uma calculadora de valor presente; esta é uma fórmula simples, mostrada na Figura 3.

Present Value Calculation

Figura 3 Cálculo do valor presente

Variáveis no PowerShell começam com um $. Na linha 7, eu uso o .NET Framework diretamente, chamando o método estático Pow no namespace System.Math. O método Pow retorna um número especificado elevado à potência especificada. A sintaxe necessária para chamar um método static .NET é colocar a classe entre colchetes, seguida por dois-pontos duplos e, então, o nome do método. [System.Math]::Pow(2,3). Se você estiver executando isso no ISE, pressione F5 (ou clique no botão Executar) para ver os resultados no painel de saída. Você pode também copiar e colar esse código no console de linha de comando do PowerShell; ele será executado e imprimirá o resultado.

Este é um excelente começo, mas não muito reutilizável. Eu poderia continuar digitando novos valores e executando esse script, mas quero chamá-lo a partir de outros scripts. Vou adicionar a palavra-chave Function e tornar as variáveis em parâmetros, de modo a poder variar o resultado e tornar o script interativo (veja a linha 2 na Figura 4).

Creating a PowerShell Function

Figura 4 Criando uma função no PowerShell

Adicionando a palavra-chave Function

Vou chamar a função de Get-PresentValue. Uma prática recomendada é seguir a convenção verbo-substantivo do PowerShell ao nomear funções — este é um conceito fundamental ao usar e desenvolver para o PowerShell. Há verbos predefinidos, como Get, Invoke, New e Remove (digite Get-Verb para ver a lista completa). Tente digitar Get-Command; isso faz retornar todos os cmdlets (e mais) definidos em sua sessão do PowerShell, e isso consiste em uma lista enorme.

Criar uma função é tão fácil quanto digitar function Get-PresentValue {}. Daqui, vou criar parâmetros com valores padrão e o corpo da função, como mostra a Figura 4.

Comparando a Figura 3 com a Figura 4, transportei as variáveis — tanto seus nomes quanto os valores — para uma linha única e separei-as por vírgulas, coloquei-as entre parênteses e coloquei-as após o nome da função, tornando-as parâmetros da função. Esses parâmetros agora têm valores padrão. Mantive o cálculo do valor presente em sua forma original. Um princípio importante do PowerShell é “digitar pouco”. Na linha 3 da Figura 4, eu poderia ter usado a instrução Return. Não fazer isso nos trará o mesmo resultado, embora haja momentos em que desejamos usar a instrução return para interromper o fluxo da lógica.

Neste exemplo, eu mostro algumas maneiras de se chamar a função Get-PresentValue. Primeiro, sem parâmetros, todos os parâmetros são padronizados. Parâmetros podem ser supridos por posição (veja a linha 8 na Figura 4) ou nomeados (veja a linha 9). Recomendo a leitura sobre parâmetros do PowerShell; O PowerShell dá suporte a um poderoso mecanismo de associação de parâmetros.

A seguir: vamos alterar a função Get-PresentValue para que retorne um objeto .NET em vez de um texto simples.

O PowerShell baseia-se no .NET

Uma importante inovação do PowerShell é sua capacidade de passar dados como objetos completamente tipados. A Figura 5 introduz o conceito de criação de um objeto do PowerShell, de definição de propriedades, de retorno do objeto e de utilização do mecanismo do PowerShell para imprimi-lo.

Return Fully Typed Objects from PowerShell Functions

Figura 5 Retornando objetos completamente tipados a partir de funções do PowerShell

 Na linha 6, eu uso o cmdlet New-Object, que cria uma instância de um objeto do .NET Framework. Informo a ele o tipo do objeto a ser criado, um PSObject, o que permite uma exibição consistente de qualquer objeto dentro do ambiente do PowerShell. Também, na linha 6, uso o parâmetro –Property, que usa uma tabela de hash. Uma sintaxe abreviada para tabelas de hash no PowerShell é @{}. Os pares chave/valor definidos na tabela de hash — e passados no parâmetro –Property — são transformados em propriedades e valores no novo PSObject.

Por último, na linha 15, chamo a função, e os resultados podem ser vistos no painel de saída (sombreados em azul no ISE). Observe que o PowerShell “sabe” como imprimir o objeto. Eu não preciso refletir sobre que propriedades devem ser impressas ou como devo imprimi-las — uma importante qualidade do PowerShell.

Intervalos e pipelines do PowerShell

Em seguida, vou usar pipelines do PowerShell e apresentar mais dois de seus cmdlets: ForEach-Object e Format-Table (consulte a Figura 6).

PowerShell Ranges and Pipelines

Figura 6 Intervalos e pipelines do PowerShell

A linha 13 é um bom exemplo e nos fornece uma visão das qualidades flexíveis e de composição do PowerShell. Há três seções e dois pipes definidos aqui. A primeira seção mostra o operador de intervalo (consistindo em dois períodos), a segunda seção é o ForEach e a última seção contém a Format-Table. Vamos discutir cada uma delas.

A primeira seção, 1000..10101000..1010 representa uma matriz de inteiros de 1000 a 1010, inclusive. Agora, o PowerShell começará a enviar uma de cada vez através do pipeline, assim que uma delas estiver disponível. O PowerShell, assim como shells baseados em Unix/Linux, implementa um pipeline que permite que a saída de um cmdlet seja inserida como entrada para outro cmdlet. No PowerShell, o pipeline consiste em objetos .NET. O uso de objetos elimina a necessidade de se analisar a saída em texto arbitrário de um comando para extrair dados, uma vez que todos os dados exportam uma interface consistente (consulte bit.ly/lVJarT).

Segunda seção, ForEach { Get-PresentValue $_ } Esta seção usa ForEach (também tendo % como alias), que usa um scriptblock. Imagine um scriptblock como sendo um método anônimo (algumas vezes chamado de expressões lambda em outras linguagens). Para obter mais informações sobre esse assunto, consulte o livro “PowerShell in Action, Second Edition”, de Bruce Payette (Manning Publications, 2011).

 $_ é uma variável automática do PowerShell e contém o objeto atual no pipeline. O resultado final, uma matriz de dez inteiros, é passado, um inteiro por vez, para Get-PresentValue. Como não estamos nomeando o parâmetro, eu o passo como um parâmetro posicional para $Amount, como visto no painel de saída na Figura 6.

Última seção, Format-Table Format-Table faz o que seu nome indica; formata o resultado como uma tabela. Eu uso o parâmetro -AutoSize porque ele ajusta o tamanho da coluna baseado na largura dos dados.

Observe que eu não estou gerenciando a iteração na coleção e que o PowerShell “sabe” como e o que imprimir em relação ao objeto que está sendo transmitido pelo pipeline. Isso resulta na escrita de menos linhas de código, o que significa menos linhas a serem depuradas. Como eu gasto noventa por cento de meu tempo depurando e os outros dez por cento escrevendo bugs, no final saio-me muito bem.

É a vez da GUI – primeiro tempo

É hora de usar o WPK. O script na Figura 7 produz a GUI da Figura 8. Acrescentei informações sobre tipo aos parâmetros da função Get-PresentValue (consulte a linha 1 na Figura 7). Isso ajuda outros que estejam usando essa função a facilmente detectar se passaram dados errados — por exemplo, cadeias de caracteres em vez de dados numéricos.

The WPK New-ListView

Figura 7 A New-ListView do WPK

Viewing the GUI

Figura 8 Exibindo a GUI

A essência do código original na Figura 6 foi mantida, e a chamada de Get-PresentValue foi adicionada a DataContext da ListView, que é um controle do WPF que fornece a infraestrutura para exibição de um conjunto de itens de dados. O restante das partes do WPK integra-se à vinculação de dados do WPF e configura a exibição na ListView de modo que os dados possam ser exibidos.

O WPK segue o princípio fundamental do PowerShell, usando o par verbo-substantivo. Então, se eu quiser criar uma Window, Grid, Canvas ou ListBox, simplesmente acrescento “New-” a eles — New-Window, New-Grid, New-Canvas ou New-ListBox — e esses elementos estruturais estarão prontos para serem usados.

Import-Module

Um módulo é um pacote que contém membros — como cmdlets, scripts, funções, variáveis e outras ferramentas e arquivos — que podem ser usados no PowerShell. Após a importação de um módulo, você poderá usar seus membros em sua sessão. Conforme observado anteriormente, o WPK faz parte do pacote do PowerShell e contém mais de 700 funções do PowerShell que simplificam a colocação de uma GUI do WPF sobre o PowerShell.

Do ponto de vista tradicional do WPF, as linhas 17 e 18 na Figura 7 podem parecer incomuns. O WPK dá suporte à vinculação de dados faceando dois parâmetros: DataContext e DataBinding. O parâmetro DataContext assume um scriptblock, então aqui eu passo uma linha de código do PowerShell que cria dez objetos de valor presente que eu tinha na linha 13 da Figura 6. Em seguida, configuro a propriedade ItemsSource da ListView para ser vinculada à linha 18. O parâmetro DataBinding assume uma tabela de hash (observe o @{}). As chaves são os nomes das propriedades do objeto GUI ao qual você deseja vincular.

O WPK o ajuda a escrever menos código. A função New-GridViewColumn assume uma cadeia de caracteres — por exemplo, Amount (que é o nome de uma propriedade no objeto emitido a partir da função Get-PresentValue) — configura-a como o cabeçalho e automaticamente executa a vinculação de dados para você.

Eu comecei com uma função simples, Get-PresentValue, e terminei com a saída mostrada na Figura 8 adicionando parâmetros para torná-la reutilizável, emitindo um PSObject do .NET PowerShell e aproveitando o pipeline de objeto e operador de intervalo do PowerShell para gerar itens de valor presente. Em seguida, importei o WPK, injetando objetos do PowerShell no DataContext de um controle ListView do WPF, vinculando o parâmetro ItemsSource e criando a exibição ListView com nomes de colunas que correspondem aos nomes das propriedades do objeto injetado. No fim, tenho um aplicativo simples de valor presente do PowerShell/WPK. Isso é ótimo, mas é inserido em código.

Em seguida, eu quero interagir com este aplicativo de modo a ver o que acontece com meu investimento, alterando a quantia, os juros e outros parâmetros.

É a vez da GUI – segundo tempo

O script atual do PowerShell/WPK exige que eu altere os parâmetros, salve o arquivo e execute o script novamente, o que não é muito ágil.

Vou retrabalhá-lo de modo a poder ajustar cinco parâmetros da GUI e exibir novos valores em ListView.

Função New-Range Primeiro, eu quero adicionar uma função chamada New-Range (consulte a Figura 9).

The New-Range Function

Figura 9 A função New-Range

O operador de intervalo fornecido pelo PowerShell não permite que se varie o tamanho do incremento. Em outras palavras, eu não posso especificar (1..10 por 2). A função New-Range me permite especificar meu próprio incremento, de modo que “New-Range 1 10 2” imprima 1 3 5 7 9.

Em seguida, vou elaborar a GUI do WPK, envolvendo New-ListView em uma função New-Window. Ao usar a New-ListView por si só, o WPK irá envolver em uma janela para você. Especificar New-Window me dá um maior controle (consulte a Figura 10).

The New-Window Function

Figura 10 A função New-Window

Também elevei o DataContext da ListView ao escopo de Window e apliquei a nova função New-Range. Agora, desejo adicionar cinco caixas de texto, rótulos e um botão. Isso me permitirá manter o aplicativo em execução e ajustar a saída de Get-PresentValue. Vou usar as funções WPK New-Grid, New-Label, New-TextBox e New-Button para criar os controles de que necessito. Usar New-Grid para criar um controle de grade me dá flexibilidade para redimensionar a janela e controlar o posicionamento.

Para formatar a GUI, vou aninhar grades dentro de grades, assim como controles. Estou ainda usando as funções New-Range e Get-PresentValue em DataContext, como mostra a linha 2 da Figura 11.

The New-Grid Function
(clique para ampliar)

Figura 11 A função New-Grid

Também, New-ListView ainda está lá na Figura 11, nas linhas 30 a 37. Adicionei dois novos parâmetros à linha 30, –Row e –Column, que informam a ListView em que linha e coluna deveria estar localizado, na New-Grid definida na linha 5. A New-Grid definida na linha 5 usa linhas e colunas para fazer o layout de uma grade. Quero duas colunas com largura de 75 pixels e três linhas com altura de 35 pixels cada. O asterisco após o segundo 75 no parâmetro Rows indica que ela ocupará todo o espaço disponível.

Agora, coloco cinco pares de rótulos e caixas de texto na janela, informando aos controles em que quadrante da grade eles devem ser ancorados, por meio dos parâmetros Row e Column. E também nomeio a caixa de texto, para que possa acessá-la mais tarde, dou-lhe um valor padrão por meio do parâmetro –Text e enfeito os controles com os parâmetros Margin e HorizontalAlignment.

Por fim, coloco um botão na grade, com a função New-Button. Observe que eu coloco um sublinhado antes de Calculate. Isso me permite acessar o botão pressionando Alt-C.

A calculadora de valor presente está quase pronta.Eu preciso conectar o evento de clique a algum código do PowerShell, ler os valores nas caixas de texto, passá-los como parâmetros a Get-PresentValue e vinculá-lo a ListView.

Função Do-Calculation

Vou adicionar uma função Do-Calculation que assume um único parâmetro, o $window (consulte a Figura 12).

The Do-Calculation Function

Figura 12 A função Do-Calculation

Vou chamar Do-Calculation a partir da propriedade -On-Click em New-Button, aquela que contém “_Calculate.”

Do-Calculation é bem simples. Ela obtém as informações de todas as caixas de texto, define-as como variáveis do PowerShell e as passa como parâmetros para as funções New-Range e Get-PresentValue. Eu passo o parâmetro $window (consulte a linha 2 na Figura 13), que contém uma referência a New-Window criada na Figura 10. Usando isso, posso chegar a todas as propriedades da janela, assim como aos controles filho, especificamente as caixas de texto. Como nomeei cada um dos controles de caixa de texto, posso canalizar $window para Get-ChildControl, passando o nome do controle e recuperando o texto por meio da propriedade .Text (consulte as linhas de 3 a 7 na Figura 12).

Completed Grid
(clique para ampliar)

Figura 13 Grade concluída

Ao coletar todos os detalhes das caixas de texto, eu defino $window.DataContext como resultado de New-Range que está sendo enviado a Get-PresentValue, o qual gera uma matriz de objetos do PowerShell contendo os resultados dos cálculos de PresentValue (consulte as linhas de 9 a 12 na Figura 12).

A Figura 13 mostra como conectar os eventos de clique do botão Calculate para chamar a função Do-Calculation e passar a variável $window (consulte as linhas 28 e 29). Adicionei o parâmetro -On_Click, que assume um ScriptBlock. Lá, eu chamo a função Do-Calculation, passando a variável $window que é criada para mim quando uso a função New-Window. Todas as vezes que eu clicar no botão, a tela recalculará. Observe que eu também alterei a linha 2 na Figura 13 para que também chame a função Do-Calculation.

Baixe o aplicativo concluído nos exemplos de código-fonte que acompanham este artigo para ver todo o script.

Um aplicativo do WPF simples e interativo

Apresentei aqui um script com menos de 75 linhas de código, que resulta em um aplicativo interativo do WPF, colocado sobre a plataforma de automação da Microsoft, o PowerShell. O PowerShell se manifesta tanto como uma linguagem de script quanto um console de linha de comando. Sua plena integração com o .NET Framework e com o Windows permite interessantes oportunidades de automação. Claro que isso significa que deve-se investir tempo para aprender esta nova plataforma. A boa notícia é: você pode se envolver com a parte mais fácil, para se tornar mais produtivo, e depois, quando precisar, pode pesquisar em detalhes a enorme quantidade de oportunidades de automação oferecidas pelo PowerShell, tanto através da Microsoft quanto da comunidade do PowerShell em geral.

O modelo de desenvolvimento ad hoc e a origem do Windows PowerShell

O artigo de Doug Finke é um excelente exemplo do modelo de desenvolvimento ad hoc. O PowerShell diferencia-se de outras tecnologias de programação de várias maneiras: sua ênfase em abstrações de alto nível e orientadas a tarefas; seu sistema de tipo adaptável que normaliza sistemas de tipos diferentes (.NET, Windows Management Instrumentation [WMI], XML, ADSI, ADO e outros) e permite a adição de membros a tipos e instâncias; seu mecanismo de fluxo de dados que elimina muito da incompatibilidade de impedância de API que os desenvolvedores de código precisam escrever; e seu suporte ao modelo de desenvolvimento ad hoc.

O modelo ad hoc é o que permite começar a resolver um problema usando técnicas informais. Ao decidir usá-lo mais, você o converte em um script informal e, se compartilhá-lo, você o torna mais formal. Como desenvolvedores de ferramentas, frequentemente desenvolvemos ferramentas para pessoas de diferentes formações, de modo que é importante satisfazer as necessidades e expectativas de todos os públicos. Isso, frequentemente, significa fornecer uma GUI.

O artigo de Doug começa com um script rígido e sem nome para produzir o valor presente de uma certa quantia de dinheiro, uma taxa de juros fixa e tempo. Em seguida, ele o transforma em uma função com parâmetros nomeados e valores iniciais que retornam um único valor. Depois, ele retorna um objeto que pode ser manipulado por outras ferramentas. E, finalmente, ele o transforma em uma GUI simples e, depois, em uma mais sofisticada. Ele só investe o que é preciso, e cada script adiciona pequenos incrementos ao anterior. Finalmente, Doug compartilha seu script, permitindo que outras pessoas usem sua ferramenta e também ofereçam sugestões para melhorá-la (como, quando sugerido, ele “tipificou” seus parâmetros de modo que sua ferramenta não engasgasse se alguém passasse cadeias de caracteres). Todos nós nos beneficiamos do compartilhamento. Eu consegui uma ferramenta legal e sou muito grato a Doug. Paguei parcialmente minha dívida revisando seu código e oferecendo sugestões. Eu conheço bem o PowerShell, mas, mesmo assim, beneficio-me muito de todas as sugestões que a comunidade faz aos meus scripts. [Snover é o inventor do Windows PowerShell e um dos principais designers, juntamente com Bruce Payette e James Truher; consulte bit.ly/696Jor.—Ed.]

O modelo de desenvolvimento ad hoc vem do objetivo do PowerShell de ser tanto um excelente shell quanto uma excelente linguagem de script. Bruce Payette, um dos designers da linguagem, disse uma vez que a vida útil de 99 por cento dos scripts do PowerShell começa com um prompt de comando e termina com o retorno de carro. O PowerShell dá suporte a uma ampla gama de estilos de script, começando por aqueles interativos de uma só linha em um prompt de comando e indo até funções de estilo vigoroso usando $args, e a scripts mais formais onde parâmetros são nomeados, tipados e decorados com atributos de validação, de vinculação de dados e de ajuda. A razão pela qual seguimos essa abordagem vem de muitos anos como um desenvolvedor em Unix, quando escrevi uma enorme quantidade de scripts para shell. À medida que as pessoas usavam meus scripts e solicitavam mais recursos, acabei jogando-os fora e reescrevendo-os em Tcl ou Perl. Frequentemente, eu acabava por jogar aqueles fora também e reescrevê-los em C. Até que me dei conta de que problemas diferentes exigiam diferentes níveis de formalidade e desempenho, mas que não fazia sentido não haver uma única ferramenta que pudesse cobrir essa ampla gama de necessidades de script. Assim, as pessoas poderiam investir em se tornarem especializadas naquela ferramenta em vez de serem meio competentes em um conjunto enorme de ferramentas. Levou tempo, mas finalmente consegui produzir uma ferramenta que fizesse exatamente isso. Espero que você aproveite o PowerShell.

— Jeffrey Snover, Engenheiro conceituado e arquiteto líder do Windows Server

Doug Finke*, Microsoft MVP para o Windows PowerShell, é desenvolvedor de software na Lab49, uma empresa que cria aplicativos avançados para a indústria de serviços financeiros. Nos últimos 20 anos, Doug trabalhou como desenvolvedor e autor abrangendo inúmeras tecnologias. Você poderá acompanhá-lo em seu blog, Desenvolvimento em um piscar de olhos, em dougfinke.com/blog.*

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: James Brundage, Sal Mangano, Sivabalan Muthukumar, Marco Shaw, Jeffrey Snover e Sylvain Whissell