Você está na página 1de 46

Simplificando tarefas usando PowerShell

Quem ainda no conhece ou nunca trabalhou com PowerShell? Agora, com certeza vai comear a usar. Vamos reunir aqui nos artigos da comunidade WinINFO uma sesso de dicas de uso do PowerShell, apresentando claro, os scripts que podem ajudar a voc (administrador/usurios) automatizar e acelerar tarefas dirias, principalmente as tarefas que so repetidas constantemente. O PowerShell evoluiu para melhorar e reforar sua performance. J est inclusive, disponvel para download a verso do 2.0 do PowerShell para Windows XP, Vista, 2003 e 2008. Agora, apresentando a sesso simplificando tarefas com PowerShell, foram criados 3 scripts para demosntrar na prtica como o PowerShell pode ajudar voc:

1. start-service.ps1
Iniciar determinado servio # Modelo de uso: .\start-service name_machine name_service param($name , $serv ) gwmi win32_service -comp $name -filter "name like '$serv'" | % {$_.startservice()} |select returnValue #Fim do arquivo

2. check-service.ps1
Checar status de um servio # Modelo de uso: .\check-service name_machine name_service param($name , $serv ) gwmi win32_service -comp $name -filter "name like '$serv'" | select name,startmode,state,status #Fim do arquivo

3. stop-service.ps1
Parar determinado Servio # Modelo de uso: .\stop-service name_machine name_service param($name , $serv )

gwmi win32_service -comp $name -filter "name like '$serv'" | % {$_.stopservice()} |select returnValue #Fim do arquivo

4. space-Disk.ps1
Script para verificar espao em disco: # Modelo de uso: .\space-Disk.ps1 nome_maquina function Get-DiskSpace($comp) { $disks = Get-WmiObject Win32_logicaldisk -computer $comp | Where-Object {$_.DriveType -eq 3} | Select-Object Name,@{Name="Size";Expression={"{0:f} GB" -f ($_.Size/1GB)}},@{Name="FreeSpace";Expression={"{0:f} GB" -f ($_.FreeSpace/1GB)}} $disks } if ($args[0] -ne $null) { Get-DiskSpace $args[0] | fl }

5. check-bios.ps1
Script para verificar a verso da bios do seu computador ou outros computadores, dependendo do seu ambiente. Primeiro crie a lista: lista_checkbios.txt, dentro desse arquivo .txt coloque o nome_da_mquina que voc deseja verificar. Exemplo: 'localhost'. Execute o comando: # Modelo de uso: .\check-bios.ps1 gwmi win32_bios -cn (gc lista_checkbios.txt) |select __server, SMBIOSBIOSVersion, Manufacturer, Name, SerialNumber, version

6. Get-LastBootTime.ps1
Esse script verifica o ltimo boot da sua mquina, dependendo do seu ambiente de outras mquinas tambm. # Modelo de uso: .\Get-LastBootTime.ps1 name_machine

param($comp='', [switch]$relative) if (-not $comp) { $comp = $input } if (-not $comp) { throw "Servidor no especificado!" } $now = Get-Date foreach ($comp in $comp) { $wmi = Get-WmiObject -class win32_operatingsystem -namespace root\cimv2 ` -computername $comp $lastBootTime = $wmi.ConvertToDateTime($wmi.LastBootUpTime) if ($relative) { "$comp- $($now - $lastBootTime)" } else { "$comp - $lastBootTime" } } Se quiser obter o resultado de outras mquinas, basta acresentar no modelo de uso as demais mquinas que voc possui no seu ambiente, exemplo: .\Get-LastBootTime.ps1 name_machine1, name_machine2, name_machine3 Sendo assim, voc ter um relatrio completo e sem fazer esforo. Esses Scripts tem como objetivo facilitar e automatizar diversas tarefas, como essa.

Do Windows PowerShell: Curso rpido de scripts


Esta abrangente coluna sobre o Windows PowerShell o introduzir a essa poderosa tecnologia.

Don Jones
Mais de vocs so acostumar Windows PowerShell e concretizar suas vantagens. Com isso em mente, coluna deste ms vai ser um longo. Esta uma viso geral sobre lightning Windows PowerShell script, incluindo como criar scripts com parmetros. Nos prximos meses, falarei sobre tpicos especficos que se baseiam nessa base. Se voc no esteja habituado a executar os comandos de Windows PowerShell no console, voc pode encontrar essa muito avanada, mas tentar vasculhar assim mesmo. Voc deve

ter uma compreenso completa dos recursos de segurana Windows PowerShell. Voc j deve saber sobre a diretiva de execuo e saber qual configurao voc est usando. Se voc ainda no saiba a diferena entre "RemoteSigned" e "AllSigned" e por que um pode ser melhor do que o outro, voc talvez no esteja pronta para o material a seguir. Voc tambm deve saber como executar scripts no shell e deve se lembrar de que voc sempre deve fornecer um caminho e nome de arquivo para executar um script. Finalmente, voc tambm deve saber a diferena entre executar um script no Integrated Scripting Environment (ISE) e no console. No ISE, os scripts so executados no escopo global. No console do shell normal, os scripts de obtm seu prprio escopo. Vamos analisar escopo, mas voc j deve ter uma idia do que significa e como funciona. Se voc no se bastante deleite, dar uma olhada no meu livro, "Saiba de Windows PowerShell em um ms de almoos" (Manning Publications, 2011) e o companion Web site da e veja se esses recursos podem ajud-lo a construir uma base melhor. Tente acompanh-lo enquanto voc l essa coluna. Testar os exemplos. Se voc digitar (ou copie e cole) os exemplos de script em Windows PowerShell ISE comeando na linha 1, seus nmeros de linha ir corresponder com os nmeros de linha nas descries.

Arquivos de Script Windows PowerShell


Um arquivo de script Windows PowerShell nada mais que um arquivo de texto sem formatao que tenha um.Extenso de nome de arquivo ps1. O "1" no se refere a verso do Windows PowerShell, mas em vez disso, a verso do mecanismo do idioma. Windows PowerShell verso 1 e 2 use engine verso 1 do idioma. por isso que as duas verses do shell so instalados em uma pasta de verso 1.0 em \Windows\System32\WindowsPowerShell. Um script de Windows PowerShell no exatamente como um arquivo em lotes de linha de comando e executar um script no precisamente a mesma que executar os mesmos comandos na mesma seqncia. Por exemplo, abra uma janela de console e execute o seguinte, pressionando Enter aps cada linha (Lembre-se no digite os nmeros de linha):
Get-Service Get-Process

Agora digite essas mesmas linhas exatas em um arquivo de script ou o script ISE, painel de edio e execute o script. Voc obter resultados de busca diferentes. Cada vez que voc pressione a tecla Enter em Windows PowerShell, que voc iniciar um novo pipeline. Quaisquer comandos que voc digitou so executados desse pipeline nico. No final do pipeline, o Windows PowerShell converte seu contedo em uma exibio de texto. Quando voc executar os dois comandos no console do normal, tiver feito isso em duas tubulaes distintas. Windows PowerShell foi possvel construir uma exibio exclusiva para cada conjunto de sada. Quando inserido em um script, no entanto, ambos os comandos executados no mesmo pipeline. O Windows PowerShell sistema de formatao no seja sofisticada o

suficiente para construir a mesma exclusivo sada para dois conjuntos diferentes de resultados. Tente executar isso no console:
Get-Service;Get-Process

Esses resultados devem parecer igual, da mesma forma que quando voc executou o script que contm esses dois comandos. Nesse caso, ambos os comandos executados em uma tubulao nica. Isso o que aconteceu quando voc executou o script. O upshot prtico de todos os isso que um script deve produzir apenas um tipo de sada. uma m idia devido em grande parte das limitaes de sistema de formatao. Existem outras consideraes. Voc no quer um script despejando vrios tipos de coisas no pipeline, ao mesmo tempo. Concentrar nela como uma regra para tudo, que vamos abordar. Um script deve gerar um e somente um tipo de sada. A nica exceo seria se ele um script que est sendo usado como um repositrio para vrias funes. Nesse caso, cada funo deve gerar um e somente um tipo de sada.

Variveis
Pense em variveis como uma caixa. Voc pode colocar um ou mais itens, at mesmo coisas diferentes, nessa caixa. A caixa tem um nome e Windows PowerShell esse nome pode incluir em praticamente qualquer coisa. "Var" pode ser um nome de varivel, como can "{minha varivel}". No segundo exemplo, as primeiras chaves coloque um nome de varivel que contm espaos, que bastante feio. Como uma boa prtica, siga os nomes de variveis que incluem letras, nmeros e sublinhados. Usando o nome de uma varivel faz referncia a toda a "caixa". Se voc deseja referenciar o contedo da caixa, adicionar um sinal de cifro: $ var. Voc ver com freqncia precedidas do sinal de dlar porque o objetivo de usar um obter o contedo de variveis de Windows PowerShell. importante lembrar, no entanto, que o cifro no parte do nome da varivel. Ele simplesmente uma indicao para informar ao Windows PowerShell que voc deseja que o contedo, em vez da prpria caixa. Por exemplo:
$var = 'hello' $number = 1 $numbers = 1,2,3,4,5,6,7,8,9

Esses exemplos mostram como colocar itens em uma varivel usando o operador de atribuio (=). Esse ltimo exemplo cria uma matriz, porque Windows PowerShell interpreta todas as listas separadas por ponto-e-vrgula como uma matriz ou coleo, de itens. O primeiro exemplo atribui a um objeto de seqncia de caracteres, com os caracteres na seqncia de caracteres entre aspas. H um aspecto de Windows PowerShell que pode confundir os novatos. Windows PowerShell no "compreender" qualquer significado, que voc pode associar um nome de

varivel. Uma varivel como nome_do_computador $ no "informa" shell do que a varivel ir conter um nome de computador. Da mesma forma, os nmeros de $ no "informam" shell do que uma varivel ir conter mais de um nmero. O shell no se importa se voc usar um nome de varivel no plural. A instruo
$numbers = 1

igualmente vlida para o shell, como est


$numbers = 'fred.'

Quando uma varivel contm vrios valores, no entanto, voc pode usar uma sintaxe especial para acessar apenas uma nica delas. Voc usaria os nmeros de $[0] como o primeiro item, nmeros de $[1] o segundo, nmeros de $-[1] a ltima, nmeros de $-[2] o ltimo segundo e assim por diante.

Aspas
Como prtica recomendada, use aspas para delimitar uma varivel, a menos que tenha um motivo especfico para fazer o contrrio. Existem trs instncias especficas em que voc desejaria usar aspas duplas. A primeira quando voc precisa inserir o contedo de uma varivel em uma seqncia de caracteres. Aspas duplas apenas, Windows PowerShell ir procurar o $ e supondo que tudo que vier depois $, at o primeiro caractere que ilegal em um nome de varivel, um nome de varivel. O contedo dessa varivel ir substituir o nome da varivel e o $:
$name = 'Don' $prompt = "My name is $name"

O prompt $ agora conter "meu nome Don" porque o nome de $ ser substitudo com o contedo da varivel. Esta uma excelente dica para combinar seqncias de caracteres sem precisar concaten-las. Aspas duplas, Windows PowerShell tambm procure seu caractere de escape, o backtick ou o acento e age de acordo. Aqui esto alguns exemplos:
$debug = "`$computer contains $computer" $head = "Column`tColumn`tColumn"

No primeiro exemplo, o primeiro $ est sendo "perdida." Que remove seu significado especial como um acessador de varivel. Se o computador de $ contido 'Servidor' em seguida, depurao de $ conteria "computador $ contm SERVER".

No segundo exemplo, ' t representa um caractere de tabulao horizontal, para que Windows PowerShell colocar uma guia entre cada coluna. Voc pode ler sobre outros caracteres de escape especiais no shell do HYPERLINK "http://technet.microsoft.com/library/dd347662.aspx"about_escape_characters tpico da Ajuda. Por fim, use aspas duplas quando uma cadeia de caracteres deve conter aspas simples:
$filter1 = "name='BITS'" $computer = 'BITS' $filter2 = "name='$computer'"

Neste exemplo, a seqncia de caracteres literal o nome = 'BITS'. As aspas duplas contm todo o contedo. US $Filtro1 e US $Filtro2 acabam contendo exatamente a mesma coisa, mas a US $Filtro2 de chegar l, usando o truque de substituio de varivel de aspas duplas. Observe que apenas o conjunto mais externo de cotaes, na verdade, importante. As aspas simples dentro da seqncia no importam para Windows PowerShell. As aspas simples so caracteres literais apenas. Windows PowerShell no interpret-los.

Variveis e objetos membros


Tudo o que Windows PowerShell um objeto. At mesmo uma seqncia de caracteres simple como, por exemplo, "nome" um objeto, do tipo System. String. Voc pode canalizar qualquer objeto para Get-Member para ver seu nome de tipo (ou seja, o tipo de objeto que ele ), bem como seus membros, que inclui suas propriedades e mtodos:
$var = 'Hello' $var | Get-Member

Use um perodo aps um nome de varivel para informar o shell, "eu no quero acessar o objeto inteiro dentro dessa varivel. Quero apenas uma das suas propriedades ou mtodos de acesso." Aps o perodo, fornea o nome de propriedade ou mtodo. Nomes de mtodo so sempre seguidos de um conjunto de parnteses. Alguns mtodos aceitam argumentos de entrada e aqueles v dentro dos parnteses em uma lista separada por vrgulas. Outros mtodos no requerem nenhum argumento, e ento os parnteses vazios, mas no se esquea dos parnteses:
$svc = Get-Service $svc[0]. name $name = $svc[1]. name $name.length $name.ToUpper()

Observe a linha dois. Ele iniciado, acessando o primeiro item na varivel $svc. O meio perodo, "eu no quero que todo o objeto. Queria apenas uma propriedade ou mtodo." Isso acessa a propriedade de nome. A linha cinco ilustra como acessar um mtodo, fornecendo seu nome aps um perodo, seguido de parnteses. Um perodo normalmente um caractere invlido dentro de um nome de varivel, porque o perodo significa que desejamos acessar uma propriedade ou mtodo. Isso significa que a linha dois no exemplo a seguir no funciona da maneira que voc poderia esperar:
$service = 'bits' $name = "Service is $service.ToUpper()" $upper = $name.ToUpper() $name = "Service is $upper"

Na linha dois, $nome conter "o servio de BITS.ToUpper()" enquanto na linha quatro $nome conter "O servio BITS".

Parnteses
Alm de seu uso com os mtodos do objeto, parnteses tambm atuam como um marcador de ordem de execuo, de Windows PowerShell, assim como em lgebra. Em outras palavras, os parnteses informam o shell "executar este primeiro". Toda a expresso entre parnteses substituda por tudo o que produz dessa expresso. Eis alguns exemplos de mind-bending:
$name = (Get-Service)[0]. name Get-Service -computerName (Get-Content names.txt)

Na linha um, $nome conter o nome do primeiro servio do sistema. Lendo este artigo leva um pouco de esforo. Comece com a expresso entre parnteses. Isso o que Windows PowerShell comear com tambm. "Get-Service" resolve para uma coleo ou matriz, dos servios. A [0] acessa o primeiro item em uma matriz, para que seja o primeiro servio. Porque ele seguido por um ponto, ns sabemos que estamos acessando uma propriedade ou mtodo de servio, em vez do objeto de todo o servio. Por fim, podemos extrair apenas o nome do servio. Na linha dois, a expresso entre parnteses est lendo o contedo de um arquivo de texto. Supondo que o arquivo contm um nome de computador por linha, "Get-Content" "ir retornar uma matriz de nomes de computador. Aqueles alimenta o parmetro " ComputerName" de "Get-Service". Nesse caso, o shell pode alimentar qualquer expresso entre parnteses que retorna uma matriz de seqncias de caracteres para o o parmetro " ComputerName", porque o parmetro foi projetado para aceitar a matrizes de seqncias.

Escopo
O escopo um conceito de programao que atua como um sistema de containerization. Coisas como variveis, aliases, PSDrives e outros elementos de Windows PowerShell so armazenadas em um escopo. O shell mantm uma hierarquia de escopos e tem um conjunto de regras que determinam como os escopos possam interagir e compartilhar informaes entre si. O prprio shell um nico escopo, chamado de escopo global. Quando voc executa um script, ele constri um novo escopo e o script executado dentro do que. Qualquer texto criado por script, como, por exemplo, uma nova varivel, armazenado dentro do escopo do script. Ele no est acessvel pelo shell de nvel superior. Quando o script terminar a execuo, seu escopo descartado e nada criados dentro desse escopo desaparece. Por exemplo, criar um script que contm o seguinte (no se esquea no digite os nmeros de linha), e execute esse script a partir da janela do console:
Dir SYS: New-PSDrive -PSProviderFileSystem -Root C:\ -Name Sys

Depois de executar o script, execute manualmente "Dir SYS:" e voc ver um erro. Isso ocorre porque o SYS: unidade foi criada no script. Depois que o script foi feito, tudo o que ele criou foi descartado. O SYS: unidade no existe mais. Nem tudo no shell do escopo definido. Itens como mdulos so manipuladas globalmente em todas as ocasies. Um script pode carregar um mdulo e o mdulo permanecer carregado aps o script feito. Se um escopo tenta acessar algo que no tenha sido criado dentro desse escopo, Windows PowerShell procura ao escopo mais alto seguinte (o escopo de "pai"). por isso que o Dir trabalhou alias que voc acabou de script inserido. Embora o Dir no existia no escopo do script, ele existisse no escopo da mais alto seguinte: escopo global. Um escopo livre para criar um item que tem o mesmo nome de um item de um escopo de nvel mais alto, porm. Este outro script tentar:
Dir New-Alias Dir Get-Alias Dir

Que pode parecer estranho, mas na primeira vez que ele foi executado "Dir", ele no existe no escopo do script. Ele usado o alias de Dir de nvel mais alto. Alias aponta para GetChildItem, portanto, exibido uma listagem de diretrio familiar. Em seguida, o script cria um novo alias nomeado dir. Isso aponta para o Alias de Get. Isso o que foi executado pela segunda vez. Nada disso afetado o alias de Dir de nvel superior. Tente executar o Dir no shell depois de executar o script anterior, e voc ainda ter uma listagem de diretrio. Escopo pode ser bastante confuso quando se trata de variveis. Como regra, um determinado escopo nunca deveria acessar itens fora do escopo, especialmente as variveis. H uma sintaxe para faz-lo, como o uso de $global: var forosamente acessar a varivel do

escopo global $var, mas essa uma prtica ruim, exceto em circunstncias muito especficas.

Linguagem de script Windows PowerShell


Windows PowerShell contm uma linguagem de script muito simples de palavras-chave de menos de duas dzias. um contraste perfeito para uma linguagem de programao completa, como VBScript, que contm mais de 300 palavras-chave. O idioma de Windows PowerShell simplificado embora, mais do que suficiente para fazer o trabalho. Vamos analisar suas principais construes scripts agora, embora voc sempre pode obter mais ajuda sobre estes lendo o "tpico dentro do shell sobre" apropriado. Por exemplo, about_switchcontains informaes de ajuda sobre a construo de Switch, enquanto about_if de Ajuda contm informaes sobre a se construir. Executar a Ajuda sobre * para obter uma lista de todos os "tpicos sobre". Se construir Esta a construo de tomada de deciso principal Windows PowerShell. Em sua forma completa, ele semelhante a:
If ($this -eq $that) { # commands } elseif ($those -ne $them) { # commands } elseif ($we -gt $they) { # commands } else { # commands }

A palavra-chave "If" uma parte obrigatria para essa construo. Uma expresso entre parnteses segue que deve ser avaliada como True ou False. Windows PowerShell sempre interpretaro o zero como False e qualquer valor diferente de zero como True. Windows PowerShell tambm reconhece as variveis internas $True e False $ como que representa os valores booleanos. Se a expresso entre parnteses gostar como True, os comandos no seguinte conjunto de chaves sero executado. Se a expresso for falso, os comandos no ir executar. Isso realmente tudo o que voc precisa vlido, se construir. Voc pode ir um pouco alm, fornecendo uma ou mais sees de "ElseIf". Essas funcionam da mesma forma como a se construir. Eles obtm sua prpria expresso entre parnteses. Se for verdadeiro, os comandos dentro dos colchetes chaves seguintes sero executados. Caso contrrio, eles no. Voc pode resumir com um bloco Else, que ser executado se nenhum dos blocos precedentes executar. Apenas o bloco associado com a primeira expresso verdadeira ser executada. Por exemplo, se $isso no ser igual a $, e $aqueles no igual $-los, em seguida, os comandos na linha quatro seriam executado e nada mais. Windows PowerShell ainda no avalia a segunda expresso elseif na linha de cinco.

O caractere # um caractere de comentrio, tornando Windows PowerShell essencialmente ignorar qualquer coisa a partir da at um carro retorno. Observe tambm o cuidado com os quais essas construes foram formatadas. Voc tambm pode ver a formatao como esse de alguns caras: No importa onde voc pode colocar as chaves. No entanto, o que faz a diferena que voc seja consistente na sua colocao para que seus scripts sejam mais fceis de ler. Tambm importante recuar, no mesmo nvel exato, cada linha dentro de chaves. O ISE de Windows PowerShell permite que voc use a tecla Tab para essa finalidade e o padro ser um recuo de quatro caracteres. Recuo do seu cdigo uma prtica recomendada de ncleo. Caso contrrio, voc ter um tempo difcil correspondncia corretamente abrindo e fechando chaves em scripts complexos. Alm disso, todas as outras crianas Windows PowerShell far com que voc diverso. Considere este script mal formatado:
function mine { if ($this -eq $that){ get-service }}

Isso muito mais difceis de ler, depurar, solucionar problemas e manter. Enquanto o espao aps os parnteses de fechamento no necessrio, ele tornam mais fcil ler seu script. O cdigo recuado no necessrio, mas ela facilita o script a seguir. Considere isso:
function mine { if ($this -eq $that){ get-service }

Colocar um colchete de fechamento em uma linha por si s no necessrio para o shell, mas ele apreciado pelo olho humano. Ser um formatador organizado, e voc ter menos problemas em seus scripts. A construo, enquanto Esta uma construo de loop em Windows PowerShell. Ele foi projetado para repetir um bloco de comandos desde que alguma condio for verdadeira, ou at que uma condio for verdadeira. Aqui est o uso bsico:
Do { # commands } While ($this -eq $that)

Nesta variao da construo, os comandos dentro dos colchetes curvas sempre sero executado pelo menos uma vez. While condio no avaliada at que a primeira

execuo. Voc pode mover While, caso em que os comandos sero executados somente se a condio for verdadeira em primeiro lugar:
While (Test-Path $path) { # commands }

O segundo exemplo de aviso no usa um operador de comparao, como - EQ. Isso ocorre porque o cmdlet Test-Path acontece retornar verdadeiro ou falso inicial. No necessrio para comparar que como True ou False para que a expresso trabalhar. A expresso entre parnteses, usada com essas construes scripts simplesmente precisa simplificar para True ou False. Se voc estiver usando um comando como, por exemplo, Test-Path, que sempre retorna VERDADEIRO ou falso, que tudo o que voc precisa. Como sempre, h um tpico "sobre" no shell que demonstra a outras formas de usar essa construo. A construo ForEach Essa construo semelhante em operao para o cmdlet ForEach-Object. Ele difere somente em sua sintaxe. A finalidade de ForEach pegar uma matriz (ou coleo, que o mesmo que uma matriz em Windows PowerShell) e enumerar os objetos no array, para que voc possa trabalhar com um de cada vez:
$services = Get-Service ForEach ($service in $services) { $service.Stop() }

fcil para principiantes overthink essa construo. Tenha em mente que a palavra em ingls no plural "servios" no significa nada para Windows PowerShell. Nome da varivel usada para lembrar-nos de que ele contm um ou mais servios. S porque ele plural no faz o shell a se comportar de maneira especial. A palavra-"in" chave na linha dois parte da sintaxe ForEach. Varivel $service composto por. Isso poderia ter sido facilmente $fred ou $caf e ele seriam funcionavam da mesma maneira. Windows PowerShell se repetir os comandos da construo aqueles contidos entre chaves uma vez para cada objeto na segunda varivel (servios de $). Cada vez, ele ir levar a um nico objeto a partir da segunda varivel (servios de $) e coloc-lo na primeira varivel (servio$). Dentro deste construtor, use a primeira varivel (servio$) para trabalhar com um objeto individual. Na linha de trs, indica o perodo de "eu no quero trabalhar com o objeto inteiro, apenas um dos seus membros o mtodo Stop." H momentos em uso de ForEach inevitvel e desejveis. No entanto, se voc tiver um pouco de programao ou scripts de experincia, s vezes pode leap usando ForEach

quando no for a melhor abordagem. O exemplo anterior no um bom motivo para usar ForEach. Isso seria mais fcil:
Get-Service | Stop-Service

O ponto aqui avaliar o uso de ForEach. Certificar-se de que esta a nica maneira de realizar a tarefa mo. Aqui esto algumas instncias onde ForEach provavelmente a nica maneira de ir: Quando voc precisar executar um mtodo contra um monte de objetos e houver um cmdlet que executa a ao equivalente. Quando voc possui um monte de objetos e precisa executar vrias aes consecutivas em relao a cada um. Quando voc tem uma ao que s pode ser executada em relao a um objeto ao mesmo tempo, mas o script pode estar trabalhando com um ou mais objetos e voc tem uma maneira de saber antecipadamente. Outras construes Windows PowerShell tem vrias outras construes de scripts, incluindo o Switch, para, e assim por diante. Todos esses so documentados em "sobre" tpicos da Ajuda dentro do shell. s vezes, voc pode usar as construes abordadas aqui para substituir essas outras construes. Por exemplo, voc pode substituir o Switch com uma instruo If construo que utiliza vrias sees ElseIf. Voc pode substituir para com ForEach, ou mesmo com o cmdlet ForEach-Object. Por exemplo, com um loop que ser executado exatamente dez vezes:
1..10 | ForEach-Object -process { # code here will repeat 10 times # use $_ to access the current iteration # number

Cabe a voc selecionar a melhor construo para realizar o trabalho. Se voc estiver navegando na Internet para scripts, esteja preparado para ser executado em qualquer e todas as variaes.

Funes
Uma funo um tipo especial de construo usada para conter um grupo de comandos relacionados que realizam uma tarefa nica e especfica. Em termos gerais, voc pode assumir qualquer script Windows PowerShell e "empacot-lo" dentro de uma funo:
function Mine { Get-Service Get-Process } Mine

Isso define uma nova funo chamada "Meus". Que basicamente transforma as minhas em um comando, o que significa que voc pode executar a funo simplesmente inserindo seu nome. Isso o que cinco faz de linha. Ele executa a funo. Normalmente, as funes esto contidas dentro de um arquivo de script. Um nico script pode conter vrias funes. Funes podem-se at mesmo conter outras funes. No entanto, as funes so itens com escopo. Isso significa que voc s pode usar uma funo dentro do mesmo escopo no qual ele foi criado. Se voc coloca uma funo em um script e, em seguida, execute esse script, possvel que a funo s estar disponvel dentro do script e somente para a durao do script. Quando o script termina a execuo, a funo como tudo no escopo do script desaparecer. Aqui est um exemplo:
function One { function Two { Dir } Two } One Two

Suponha que voc insira isso em um nico arquivo de script e executar esse script. Linha sete executa a funo a um, que comea na linha de um. A linha cinco executa uma funo denominada dois, que comea na linha dois. Para que o resultado ser uma listagem de diretrio, que est na linha de trs dentro da funo dois. Entretanto, a prxima linha a ser executada ser a linha oito, e isso resultar em erro. O script no contm uma funo chamada dois. Funo dois includa dentro da funo de um. Como resultado, que existe dentro da funo de um escopo. Apenas outras coisas dentro de funo, um podem ver dois. Tentando chamar dois a partir de outra anyplace resultar em erro.

Adicionando parmetros a um Script


raro para criar um script destinado a fazer exatamente a mesma coisa, sempre que ele for executado. Com mais freqncia, voc ter de scripts que contm algum tipo de dados da varivel ou o comportamento da varivel. Voc pode acomodar essas variaes com parmetros. Parmetros so definidos de maneira especial na parte superior do script. Voc pode preceder a essa definio com comentrios, mas caso contrrio, ele deve ser as primeiras linhas de executveis do cdigo dentro do script. Dentro da rea de definio do parmetro, cada parmetro separado do prximo por uma vrgula. Acompanhando a idia de formatao organizada, ele ajuda a colocar cada parmetro em uma linha prpria. Veja um exemplo:
param (

[string]$computername, [string]$logfile, [int]$attemptcount = 5 )

Este exemplo define trs parmetros. Dentro do script, eles so simplesmente usados como qualquer outra varivel. Voc observar que na linha quatro, eu atribudo um valor padro para o parmetro de attemptcount $. O padro ser substitudo por qualquer parmetro de entrada, mas ser usado se o script executado sem que o parmetro especificado. Aqui esto vrias maneiras em que o script pode ser executado, supondo que salvei como Test. ps1:
./test ./test ./test ./test ./test -computername SERVER -comp SERVER -log err.txt -attempt 2 SERVER err.txt 2 SERVER 2 -log err.txt -attempt 2 -comp SERVER

O script aceita parmetros, bem como qualquer cmdlet. Nomes de variveis so usados como os nomes de parmetro especificados com o trao usual que precede a todos os nomes de parmetro na Windows PowerShell. Aqui est uma anlise detalhada de como ele funciona: Na linha um, eu estou apenas especificando um dos parmetros $ logfile, portanto, estar vazio e $attemptcount ir conter 5, o padro. Na linha dois, eu estou especificando trs parmetros, embora eu estou fazendo, de forma usando nomes de parmetro de reduzido. Assim como acontece com os cmdlets, voc s precisar digitar suficiente do nome do parmetro Windows PowerShell saber qual delas voc est falando. A linha trs me mostra novamente todos os trs parmetros, embora eu estou fazendo isso por posio, sem usar nomes de parmetro. Desde que eu me lembro fornecer os valores na ordem exata em que os parmetros esto listados no script, isso funcionar bem. Linha quatro mostra o que acontece se voc no for cuidadoso. Aqui, nome_do_computador $ conter 'Servidor' e $logfile conter 2, enquanto $attemptcount ir conter 5. que provavelmente no pretendo. Quando voc no usar nomes de parmetro, mais difcil ser flexvel. Tambm mais difcil para algum para decodificar o que voc entende, que torna mais difcil para que eles possam solucionar quaisquer problemas. Linha de cinco um exemplo melhor. Aqui, especifiquei parmetros fora de ordem, mas bem porque eu usado nomes de parmetro. Como regra geral, eu sempre use nomes de parmetro para o maior grau de flexibilidade. Eu no preciso lembrar-se a ordem na qual eles vieram.

Scripts avanados
Windows PowerShell oferece suporte a uma tcnica para especificar informaes adicionais sobre parmetros. Isso permite que voc declarar um parmetro como obrigatria, aceitar a entrada do pipeline e assim por diante. Essa tcnica chamada de ligao do Cmdlet. Ele no altera o modo como o script usa parmetros. Ele simplesmente apresenta o shell um pouco mais informaes sobre os parmetros. Voc encontrar essa tcnica mais comumente usada em uma funo, mas a sintaxe vlida dentro de um script bem. Este um exemplo simples:
[CmdletBinding()] param ( [Parameter(Mandatory=$True)] [string]$computername, [Parameter(Mandatory=$True)] [string]$logfile, ) [int]$attemptcount = 5

Tudo o que eu adicionei era a instruo [CmdletBinding()], como a primeira linha executvel do cdigo dentro do script. Ele est correto para comentrios deve preceder isso, mas nada mais. Tambm adicionei uma instruo de [Parameter()] a dois dos meus parmetros. Dentro dessa instruo [Paramater()], indiquei que esses parmetros so obrigatrios. Agora, se algum tentar executar o script sem especificar esses parmetros, Windows PowerShell ir solicit-los para obter as informaes. Observe que o ltimo parmetro no tem quaisquer instrues especiais e todos os trs parmetros ainda aparecem em uma lista separada por vrgulas (o que significa que os dois primeiros parmetros so seguidos por vrgulas). H uma tonelada de outras instrues, voc pode especificar para um parmetro que voc possa ler sobre o HYPERLINK "http://technet.microsoft.com/library/dd347600.aspx"about_functions_advanced_parameter s tpico da Ajuda. Essa foi uma reviso estonteante de alguns conceitos-chave de Windows PowerShell relacionados a scripts. Espero que voc aprender algo novo. Ser capaz de criar scripts com parmetros especialmente til, pois voc poder fazer scripts que paream e se comportam como cmdlets nativos do Windows PowerShell.

Amplie o Windows PowerShell com comandos personalizados


Como provvel que voc j tenha descoberto, o Windows PowerShellTM uma ferramenta eficiente e flexvel. Mas talvez voc ainda no saiba que possvel ampliar o Windows PowerShell escrevendo seus prprios cmdlets. Neste artigo, mostrarei como criar

seus prprios cmdlets, escrevendo trs cmdlets personalizados que lhe permitiro interagir com o IsolatedStorage. Escolhi o IsolatedStorage para esses exemplos porque ainda no vi outros cmdlets relacionados ao IsolatedStorage e imaginei que sua funcionalidade seria til, por oferecer um local para manter dados sem conflitos com outros aplicativos. Resumindo, o namespace System.IO.IsolatedStorage permite criar e utilizar armazenamentos isolados. Voc pode ler e gravar dados que no seriam acessados por um cdigo menos confivel, impedindo a exposio de informaes confidenciais. Basicamente, os dados ficam disponveis somente para o usurio atual ou para o assembly onde existe o cdigo (podendo ser tambm isolados por domnio). Ao utilizar o IsolatedStorage nesses exemplos, salvarei um par de chaves/valores como cadeias de caracteres. O IsolatedStorage pode armazenar qualquer tipo de dados necessrio; contudo, me limitarei s cadeias de caracteres para os fins deste artigo. Lembre-se de que o artigo trata, na verdade, de cmdlets. O IsolatedStorage serve apenas como exemplo de trabalho. Lembre-se tambm de que fornecerei apenas um ponto de partida aqui. Quando estiver pronto para aprofundar-se na criao dos seus cmdlets personalizados, consulte a SDK do Windows PowerShell. Uma viso geral dos cmdlets Quando a Microsoft criou o Windows PowerShell, ele se destinava a facilitar a criao de outras ferramentas de linha de comando capazes de oferecer a mesma consistncia e confiabilidade daquelas fornecidas como parte do Windows PowerShell. Isso possvel, em grande parte, porque o shell tem um nico analisador para todos os cmdlets. Ou seja, esse modelo permite equipe de desenvolvimento ter certeza de que todos os procedimentos de anlise de argumentos, tratamento de erros e assim por diante sero realizados de forma semelhante para todas as aes que um usurio possa executar. Como resultado, h algumas diferenas bastante significativas entre um cmdlet do Windows PowerShell e os comandos de outros ambientes autnomos de shell. Por exemplo, um cmdlet uma instncia de uma classe do Microsoft .NET Framework, e no um executvel autnomo. Em geral, os cmdlets geram objetos como sada, em vez de texto, e no devem formatar sua sada. Um cmdlet processa seus objetos de entrada a partir de um pipeline de objetos, e no a partir de um fluxo de texto. Um cmdlet no deve analisar seus prprios argumentos nem especificar uma apresentao para os erros. Por fim, os cmdlets so orientados a registros e, em geral, processam um nico objeto por vez. Os cmdlets tm uma estrutura especfica; eles precisam ser atribudos de determinada forma e tm de ser derivados de uma classe base especfica. Se determinado cmdlet oferece suporte a parmetros, esses parmetros tambm precisam ser atribudos de forma especfica e o cmdlet tem de fornecer as implementaes de alguns mtodos especficos. Se voc est se perguntando o que significa tudo isso, no se preocupe. Explicarei cada um desses requisitos em detalhes. Atributo dos cmdlets Para declarar uma classe .NET como um cmdlet, preciso atribuir a classe com o atributo CmdletAttribute (o nico atributo obrigatrio para qualquer cmdlet). Quando voc especifica o atributo CmdletAttribute, precisa tambm especificar um par de termos constitudo por um verbo e um substantivo, que ser usado como nome do cmdlet. Esse nome deve descrever o que o cmdlet faz e com que tipo de recurso ele trabalha.

Observe que o atributo CmdletAttribute em si uma classe .NET. As propriedades da classe correspondem aos parmetros disponveis ao utilizar o cmdlet. A parte do nome do cmdlet constituda por um substantivo permite diferenciar seu cmdlet personalizado de outros cmdlets. O substantivo especifica os recursos sobre os quais o cmdlet atua. O ideal que o substantivo usado na nomeao do cmdlet seja bastante especfico; caso tenha um termo genrico, voc deve us-lo como sufixo do cmdlet. Por exemplo, se voc criar um cmdlet get-server para o seu banco de dados SQL, deve usar "New-SQLDatabase" em vez de "New-Database". A combinao de um verbo e um substantivo especficos torna mais fcil para o usurio detectar cmdlets com rapidez e prever sua funcionalidade. Lembre-se de que as palavras tm de ser facilmente reconhecidas. Ento, voc no deve utilizar pontuao reservada (barras, colchetes e assim por diante) nem caracteres curinga nos nomes dos seus cmdlets. Como estou criando cmdlets que funcionem com o IsolatedStorage do Windows, tomarei isso como base para meu substantivo. Pode ser um pouco longo mas, quando se trata de nomes de cmdlets, quanto mais especfico melhor. H algumas diretrizes bastante objetivas quanto aos verbos que devem ser usados como nomes. Lembre-se de que a consistncia importante no Windows PowerShell. Por isso, use sempre os verbos adequados. Ao utilizar um dos verbos predefinidos para nomes, voc aumenta a consistncia entre os seus cmdlets personalizados, os includos e os criados por outros usurios. Por exemplo, para recuperar dados deve-se usar Get, em vez de Retrieve ou Acquire. Entre os verbos normalmente usados no Windows PowerShell esto: Add, Clear, Copy, Get, Join, Lock, Move, New, Remove, Rename, Select, Set, Split e Unlock. possvel saber qual o uso de cada cmdlet a partir do nome. Neste artigo, criarei trs cmdlets: um para definir o contedo de dados do IsolatedStorage, um para recuperar o contedo e outro para remover o arquivo do IsolatedStorage. Assim sendo, criarei trs cmdlets: SetIsolatedStorageData, Get-IsolatedStorageData e Remove-IsolatedStorageFile. Definio da classe dos cmdlets Agora, preciso criar o cdigo que implementar meus cmdlets, comeando por SetIsolatedStorageData. Primeiro, declaro a classe do cmdlet:
[Cmdlet(VerbsCommon.Set , "IsolatedStorage", SupportsShouldProcess=true)]

public class SetIsolatedStorageCommand : PSCmdlet

Observe que estou usando a combinao de maisculas e minsculas de Pascal e que o nome da classe inclui o nome formado por verbo e substantivo do cmdlet. Isso no estritamente necessrio, mas facilita muito a leitura do cdigo. A atribuio do cmdlet indica que estou usando um verbo comum, nesse caso Set. Caso seja possvel, voc deve sempre usar verbos comuns ao criar cmdlets. Definir SupportsShouldProcess como True indica que o cmdlet oferece suporte a chamadas para o mtodo ShouldProcess, que permite ao cmdlet solicitar a verificao do usurio antes de realizar uma ao que modifique o sistema. Se esse atributo no estiver presente ou estiver definido como False (que o valor padro), indicar que o cmdlet no oferece suporte a chamadas para o mtodo ShouldProcess. Todos os cmdlets que alteram recursos fora do Windows PowerShell devem ter a propriedade SupportsShouldProcess definida como true quando for declarado o atributo

CmdletAttribute. Isso permitir que o cmdlet chame o mtodo ShouldProcess antes de executar sua ao. Se a chamada para ShouldProcess retornar false, a ao no ser executada (para obter mais informaes sobre as solicitaes de confirmao geradas pela chamada para ShouldProcess, consulte a documentao do MSDN em msdn2.microsoft.com/ bb204629). Os parmetros de cmdlet Confirm e WhatIf somente esto disponveis para cmdlets que oferecem suporte a chamadas para ShouldProcess. A ltima parte declara a classe e usa PSCmdlet como a classe base. Isso significa que terei todos os comportamentos estendidos associados a um cmdlet do Windows PowerShell. O Windows PowerShell oferece suporte a cmdlets derivados de duas classes base diferentes: PSCmdlet e Cmdlet. Um cmdlet derivado de PSCmdlet fornece acesso ao runtime do Windows PowerShell. Isso habilita chamadas a outros scripts e permite acesso aos provedores do Windows PowerShell para trabalhar com o estado de sesso. PSCmdlet tambm fornece acesso aos recursos de login do Windows PowerShell, embora, em contrapartida, seja um pouco maior e crie uma dependncia em relao ao runtime do Windows PowerShell. Os cmdlets derivados da classe Cmdlet geram o mnimo de dependncias em relao ao runtime do Windows PowerShell. Isso traz alguns benefcios: esses cmdlets so um pouco menores, por terem menos funcionalidade, e h menor probabilidade de encontrar problemas devido a alteraes no Windows PowerShell ao longo do tempo. Alm disso, fcil incluir esses cmdlets em outros aplicativos sem o runtime do Windows PowerShell. Se voc planeja criar um cmdlet que sempre far parte do ambiente do Windows PowerShell, deve usar PSCmdlet como classe base. No entanto, se acredita que seu cdigo no ser utilizado apenas no Windows PowerShell, deve usar Cmdlet como classe base. Nos meus exemplos, fao a derivao de PSCmdlet. Quando voc criar seu prprio cmdlet, precisar fazer referncia a System.Management.Automation.dll, que pode ser difcil de encontrar, pois est somente no GAC (cache de assembly global), mas logo em seguida ensinarei um truque para ajud-lo com isso. Definio de parmetros Em seguida, preciso avaliar os parmetros a serem usados no meu cmdlet. Os parmetros permitem ao usurio fornecer entradas ao cmdlet. Os nomes de parmetros do cmdlet devem ser consistentes em todo o design do cmdlet. O SDK do Windows PowerShell traz sugestes detalhadas de nomes de parmetros e de como us-los em seu cmdlet para garantir a consistncia com os outros cmdlets que voc pode encontrar. Para declarar parmetros para um cmdlet, preciso primeiro definir as propriedades que representam os parmetros. Para informar ao runtime do Windows PowerShell que uma propriedade um parmetro de cmdlet, necessrio adicionar um atributo ParameterAttribute definio da propriedade. Os parmetros tm de ser marcados explicitamente como pblicos; os que no tm essa marcao tornam-se internos por padro e no so encontrados pelo runtime do Windows PowerShell. Isso pode causar uma certa confuso quando voc tentar descobrir por que seu cmdlet no tem os parmetros que deveria ter. No meu exemplo, sei que todos os cmdlets precisaro de um nome que designe o nome real do arquivo do IsolatedStorage. Ento, eis aqui a declarao de parmetro um parmetro Name:
private string _name = "PowerShellIsolatedStore";

/// <summary>name of store</summary> [Parameter] public string Name { get { return _name; } set { _name = value; } }

Quando voc cria um parmetro, deve escolher se ele ser posicional ou nomeado. No caso de um parmetro posicional, no preciso fornecer o nome, apenas o valor:
PS> cd c:\windows

Ao definir Position=num como parte do atributo, voc designa a posio usada para o parmetro. Se o parmetro no for posicional, deixe de fora o atributo Position e use o nome do parmetro na linha de comando para fornecer um valor. A documentao recomenda que, sempre que possvel, voc torne posicionais os parmetros usados com freqncia. O nico problema dessa diretriz que, se voc tiver vrios parmetros, talvez seja difcil lembrar-se de todos. Mas claro que, mesmo quando um parmetro posicional, seu nome ainda pode ser usado na linha de comando. Os parmetros de cmdlets podem ser definidos como obrigatrios, ou seja, precisam ter um valor atribudo antes que o runtime do Windows PowerShell invoque o cmdlet. A alternativa defini-los como opcionais. Todos os parmetros so definidos como opcionais por padro. Ento, para definir um parmetro como opcional, basta omitir a propriedade Mandatory na declarao do atributo. Como armazenarei uma chave e um valor no armazenamento isolado, precisarei criar parmetros para coletar esses valores (veja a Figura 1). Figure 1 Parmetros necessrios para coletar chave e valor
private string _key = null; [Parameter( Mandatory=true, Position=1, ValueFromPipelineByPropertyName=true )] public string Key { get { return _key; } set { _key = value; } } private string _value = null; /// <summary>the value to store</summary> [Parameter( Mandatory=true, Position=2, ValueFromPipelineByPropertyName=true )] public string Value { get { return _value; } set { _value = value; } }

Os parmetros de cmdlets tambm podem ter aliases. Para informar ao Windows PowerShell que um parmetro tem um alias, necessrio adicionar um atributo AliasAttribute definio da propriedade. A sintaxe bsica para declarar o atributo [Alias("alias")]. No meu exemplo, eu crio um alias denominado Filename que se aplica ao parmetro Name da seguinte forma:
private string _name = "PowerShellIsolatedStore"; /// <summary>name of store</summary> [Alias("Filename")] [Parameter] public string Name { get { return _name; } set { _name = value; } }

Parmetros Common O Windows PowerShell reserva alguns nomes de parmetros, conhecidos como parmetros Common, que voc no pode utilizar: WhatIf, Confirm, Verbose, Debug, ErrorAction, ErrorVariable, OutVariable e OutBuffer. Alm disso, os seguintes aliases para esses nomes de parmetros so reservados: vb, db, ea, ev, ov e ob. Parmetros ShouldProcess Os parmetros de outro grupo, o ShouldProcess, esto presentes somente quando o cmdlet especifica a palavra-chave SupportsShouldProcess em seu atributo CmdletAttribute. Quando o seu cmdlet oferece suporte a ShouldProcess, voc tem acesso aos seguintes parmetros em runtime: Confirm e WhatIf. Confirm especifica se a confirmao do usurio necessria antes que um cmdlet execute uma ao que modifique o sistema. True indica que a confirmao necessria; false indica que no. WhatIf especifica se um cmdlet deve informar ao usurio as alteraes que seriam feitas se a ao fosse executada, sem que a ao tenha ocorrido. True indica que o usurio ser informado sem que a ao tenha ocorrido e False indica que a ao precisa ocorrer. Quando SupportsShouldProcess for especificado, os cmdlets que tentarem declarar esses parmetros falharo ao tentar registrar o cmdlet. Voc no deve definir esses parmetros diretamente no seu cmdlet. Em vez disso, inclua SupportsShouldProcess quando usar o atributo [Cmdlet(...)]. Conjuntos de parmetros O Windows PowerShell adota o conceito de conjuntos de parmetros. Isso permite a voc escrever um nico cmdlet que exponha diferentes conjuntos de parmetros ao usurio e retorne informaes distintas com base nos parmetros especificados pelo usurio. O cmdlet Get-EventLog (incorporado no Windows PowerShell), por exemplo, retorna informaes distintas quando o usurio especifica os parmetros List ou LogName. Quando LogName especificado, o cmdlet retorna informaes sobre os eventos em determinado log de eventos. Contudo, quando List especificado, o cmdlet retorna informaes sobre os

arquivos de log propriamente ditos (e no as informaes sobre eventos contidas neles). Nesse caso, List e LogName identificam dois conjuntos de parmetros distintos. Quando so definidos vrios conjuntos de parmetros, o cmdlet pode indicar qual o conjunto a ser utilizado se o Windows PowerShell no tiver informaes suficientes para fazer essa determinao. O conjunto de parmetros usado nesse caso chamado de conjunto de parmetros padro e especificado com o uso da palavra-chave DefaultParameterSet da declarao CmdletAttribute. Observe que no utilizo conjuntos de parmetros nos meus cmdlets de exemplo. Substituies de mtodos A classe Cmdlet fornece mtodos virtuais, mostrados na Figura 2, que podem ser usados para processar registros. preciso substituir um ou mais desses mtodos por todas as classes de cmdlets derivados. Figure 2 Mtodos virtuais Mtodo Finalidade BeginProcessing Proporciona ao cmdlet uma funcionalidade opcional nica de prprocessamento. ProcessRecord Proporciona ao cmdlet uma funcionalidade de processamento registropor-registro. Pode ser chamado qualquer nmero de vezes ou no ser chamado, dependendo da entrada do cmdlet. EndProcessing Proporciona ao cmdlet uma funcionalidade opcional nica de psprocessamento. StopProcessing Interrompe o processamento quando o usurio interrompe o cmdlet de forma assncrona; por exemplo, digitando a combinao de teclas Ctrl+C. Como os meus cmdlets lidam com arquivos, utilizarei o mtodo BeginProcessing para implementar o cdigo usado para abrir os arquivos do IsolatedStorage, conforme mostrado na Figura 3. Vale a pena observar alguns detalhes. Em primeiro lugar, estou abrindo os arquivos no modo de criao, o que representa uma alterao no sistema, ento preciso encapsular o cdigo em um bloco ShouldProcess. Isso significa que terei a oportunidade de avisar ao usurio sobre o que farei antes de realmente faz-lo (isso ocorre quando o usurio utiliza os argumentos Confirm ou WhatIf). Observe tambm que vou capturar excees e encapsul-las com ThrowTerminatingError. Neste exemplo, se algo der errado, no ter prosseguimento, porque a abertura do arquivo ter falhado. Em geral, no convm capturar todas as excees; mas, como vou encapsul-las com ThrowTerminatingError, poderei fornecer algumas informaes adicionais em caso de falha. Figure 3 Usando o mtodo BeginProcessing
protected override void BeginProcessing() { try { if ( ShouldProcess( Name )) { WriteVerbose("Opening Isolated Storage: " + Name); isoStore = this.GetMyStore(); fs = new IsolatedStorageFileStream( Name, FileMode.OpenOrCreate|FileMode.Append,

FileAccess.Write, isoStore ); sw = new StreamWriter(fs); WriteDebug("Stream encoding: " + sw.Encoding); } }

catch ( Exception e ) { this.closeStreams(); ThrowTerminatingError( new ErrorRecord( e, "OpenIsolatedStorage", ErrorCategory.NotSpecified, Name ) );

} }

Na minha implementao, utilizarei ProcessRecord para o trabalho de criar novas entradas de dados no armazenamento isolado (veja a Figura 4). Observe o uso das instrues try/catch, a fim de adicionar mais informaes caso ocorra um erro. Neste caso, estou usando WriteError em vez de ThrowTerminatingError, pois no preciso interromper o pipeline no caso de uma falha de gravao. Figure 4 Usado ProcessRecord em Set-IsolatedStorageData
protected override void ProcessRecord() { try { // Remember ShouldProcess may not have opened the file if(sw != null ) { WriteVerbose("Setting " + Key + " = " + Value); sw.WriteLine(Key + "=" + Value); } } catch ( Exception e ) { WriteError( new ErrorRecord( e, "SetIsolatedStorageValue", ErrorCategory.NotSpecified, Name ) ); } }

Como abri o armazenamento isolado a partir de BeginProcessing, usarei o mtodo EndProcessing para fechar os arquivos. No estou lendo ou gravando no arquivo do armazenamento isolado em Remove-IsolatedStorageFile; portanto, usarei EndProcessing para remover o arquivo desse cmdlet. Eis aqui a aparncia do cdigo de EndProcessing nos cmdlets Get-IsolatedStorageData e Set-IsolatedStorageData:
protected override void EndProcessing() { if (sw != null ) { sw.Close(); } if (fs != null ) { fs.Close(); } if (isoStore != null ) { isoStore.Close(); } }

O cdigo de Remove-IsolatedStorageFile um pouco mais complicado. Nesse cmdlet, eu excluo o arquivo propriamente dito usando os mtodos adequados a partir do objeto IsolatedStorage:
if(ShouldProcess("Remove Isolated Storage")) { WriteVerbose("Deleting Isolated Storage: " + Name); isoStore = this.GetMyStore(); isoStore.DeleteFile(Name); }

Observe que utilizo ShouldProcess novamente. Como vou fazer uma alterao no sistema, preciso notificar o usurio sobre o que estou prestes a fazer, caso ele queira essa informao. Emitindo resultados O objetivo do Windows PowerShell produzir resultados, mas preciso encontrar um equilbrio na maneira de fornecer esses resultados. Faz parte desse equilbrio a certeza de retornar o mximo possvel de informaes sem causar muito impacto sobre o desempenho (como o uso excessivo de memria, o tempo de execuo longo demais e assim por diante). Vou salvar texto em um arquivo e poderia, simplesmente, retornar apenas o texto em si. Embora isso fosse suficiente, eu gostaria de demonstrar algo melhor. Por isso, fornecerei a chave e o valor. Quando estava aprendendo a usar o IsolatedStorage, percebi que difcil encontrar o arquivo efetivamente usado para o armazenamento. Ento, quero incluir essa informao nos meus resultados. Isso os tornar mais teis. Retornando a chave, o valor e o caminho para os dados, meu objeto ter a seguinte aparncia:
public class IsolatedStorageData { public string Key; // The Key public string Value; // The Value public string FullName; // The path to the storage }

Tambm preciso avaliar que tipo de cadeia de caracteres o mtodo ToString do objeto deve retornar. Por padro, a maioria dos objetos .NET retorna apenas o nome do tipo, o que no muito til. Ento, farei com que o mtodo ToString retorne o Value, em vez do nome do tipo.

Para obter o valor do nome de arquivo real do membro FullName, preciso fazer uma certa reflexo, porque essa informao no aparece como parte das informaes sobre o IsolatedStorage. Assim, a implementao do objeto que utilizarei para os resultados ter a aparncia mostrada na Figura 5. Figure 5 Objeto usado para os resultados
public class IsolatedStorageData { public string Key; // The Key public string Value; // The Value public string FullName; // The path to the storage public override string ToString() { return Value; } public IsolatedStorageData( string _key, string _value, IsolatedStorageFileStream _fs ) { Key = _key; Value = _value; FullName = _fs.GetType() . GetField("m_FullPath", BindingFlags.Instance|BindingFlags.NonPublic ) . GetValue(_fs).ToString(); } }

Mais uma vez, lembre-se de que, para proporcionar consistncia entre todos os cmdlets, os cmdlets do Windows PowerShell retornam objetos em um pipeline, e no texto em um fluxo. WriteObject usado pelo cmdlet para emitir os resultados. Aps recuperar os dados no arquivo do IsolatedStorage, eu os converto em uma instncia de um tipo IsolatedStorageData e uso WriteObject para emitir os resultados no pipeline. Emitindo relatrios sobre condies de erro Ao executar o cdigo, haver momentos em que nem tudo funcionar como voc deseja e ocorrer algum tipo de erro. O Windows PowerShell conta com alguns comportamentos relativamente sofisticados para essas circunstncias, e seus recursos de emisso de relatrios sobre erros permitem um controle bastante refinado sobre os acontecimentos. Nem sempre a ocorrncia de um erro algo catastrfico. Por exemplo, se voc quer remover milhares de arquivos em um diretrio, a falha em remover um ou dois desses arquivos no invalida todas as demais excluses. Os erros desse tipo so considerados nofatais, ou seja, embora sejam erros, no faro com que voc precise interromper o que estiver fazendo. Voc pode continuar a remover os arquivos removveis. No entanto, h operaes das quais no possvel recuperar-se. Suponha que voc precisa criar um arquivo temporrio para manter alguns dados que usar mais tarde. Se no conseguir criar e usar o arquivo temporrio, no haver sentido em prosseguir com o restante da operao, pois os dados necessrios no estaro disponveis. Isso se qualifica como um TerminatingError. No Windows PowerShell, dois mtodos de cmdlet diferentes WriteError e ThrowTerminatingError permitem fazer essa distino.

WriteError usado sempre que ocorre alguma circunstncia excepcional na execuo do cmdlet, mas que no fatal para a operao geral do cmdlet. O mtodo adota uma instncia de um ErrorRecord como argumento, permitindo que voc inclua mais do que apenas a exceo (a causa do erro). Voc no deve lanar uma exceo em um cmdlet. Em vez disso, ThrowTerminatingError permite interromper a execuo do pipeline e fornecer muito mais informaes do que seria possvel com uma exceo. Voc perceber no cdigo dos meus cmdlets que uso ThrowTerminatingError em BeginProcessing, mas ento uso WriteError nos mtodos ProcessRecord. Isso ocorre porque, se eu no obtiver acesso ao IsolatedStorage, no serei capaz de fazer muito no que diz respeito operao do cmdlet em geral. Contudo, se eu encontrar um erro na leitura do arquivo, talvez consiga recuperar-me e continuar. Solucionando problemas em mensagens O Windows PowerShell oferece vrias formas de comunicao com o usurio. H trs mtodos que podem ser utilizados para notificar o usurio quando voc deseja comunicar algo que no resultado de um erro. Voc deve saber que, quando utiliza esses mtodos, no pode redirecionar as mensagens que sero enviadas, mas pode suprimi-las definindo algumas preferncias no shell. Esses mtodos se comunicam diretamente com o aplicativo host, nesse caso PowerShell.exe, escrevendo, por sua vez, na janela do console. As variveis de preferncias oferecem uma grande variedade de comportamentos, que vo desde no escrever nada at perguntar se a mensagem deve ser escrita antes de continuar. Eu uso esses mtodos nos meus cmdlets de exemplo um pouco mais do que voc provavelmente usar, pois quero mostrar como podem ser teis. Se voc tem um cdigo complicado que precisa de algo mais do que apenas erros ou resultados, utilize os mtodos disponveis. A ltima coisa que voc deseja usar algo como System.Console.WriteLine em um cmdlet. Em primeiro lugar, por tratar-se de uma prtica inadequada; em segundo lugar, porque voc no deve depender do aplicativo host, j que talvez o console nem mesmo esteja presente. Voc deve usar WriteVerbose caso tenha informaes extras fora de banda que deseja transmitir ao usurio. Isso no se destina a mensagens do desenvolvedor; serve para permitir que o usurio saiba o que est acontecendo nos bastidores. A interface muito simples. Eis aqui um exemplo do meu Remove-IsolatedStorageFile, que utiliza WriteVerbose para gerar uma sada informando que est prestes a remover o arquivo do IsolatedStorage:
if(ShouldProcess("Remove Isolated Storage")) { WriteVerbose("Deleting Isolated Storage: " + Name); isoStore = this.GetMyStore(); isoStore.DeleteFile(Name); }

Use WriteDebug quando quiser comunicar-se com os desenvolvedores, dando-lhes a chance de solucionar problemas de comportamento errneo no seu cmdlet. Normalmente, voc anexaria um depurador ao sistema, mas nem sempre isso possvel em campo. WriteDebug ajudar nessas situaes. WriteWarning mais uma forma de comunicao com o usurio, fornecendo informaes sobre a execuo do seu cmdlet (no usei esse mtodo nos meus cmdlets de exemplo). Um

bom exemplo do uso de WriteWarning quando voc deseja alterar o comportamento de um cmdlet ao longo do tempo. Voc pode usar WriteWarning se for descartar um parmetro e quiser informar ao usurio que pare de utiliz-lo e adote em seu lugar um novo parmetro. Grupos de cmdlets Os meus trs cmdlets tm relao com o IsolatedStorage, portanto todos os substantivos tm a mesma raiz: IsolatedStorage. Dois cmdlets se destinam a trabalhar com os dados em si (Set-IsolatedStorageData e Get-IsolatedStorageData) e o outro, a remover o arquivo (Remove-IsolatedStorageFile). Como todos esses cmdlets tm um parmetro em comum (o nome do arquivo que ser efetivamente utilizado), no preciso implementar o mesmo parmetro em todos os cmdlets. Em vez disso, posso criar uma classe base, IsolatedStorageBase, derivada de PSCmdlet, e os cmdlets sero derivados de IsolatedStorageBase (veja a Figura 6). Essa uma boa forma de garantir a consistncia entre os seus cmdlets. Figure 6 Classe base IsolatedStorageBase
public class IsolatedStorageBase : PSCmdlet { [Parameter] public string Name ... } [Cmdlet(VerbsCommon.Set, "IsolatedStorageData",SupportsShouldProcess = true)] public class SetIsolatedStorageDataCommand: IsolatedStorageBase { ... } [Cmdlet(VerbsCommon.Get, "IsolatedStorageData")] public class GetIsolatedStorageDataCommand: IsolatedStorageBase { ... } [Cmdlet(VerbsCommon.Remove,"IsolatedStorageFile",SupportsShouldProcess = true)] public class RemoveIsolatedStorageFileCommand: IsolatedStorageBase { ... }

Criando um snap-in Para usar esses novos cmdlets, voc precisar adicion-los ao ambiente do Windows PowerShell. O Windows PowerShell tem a capacidade de adicionar cmdlets dinamicamente sesso por meio de um snap-in. Para evitar a possvel confuso com os snap-ins do MMC, um snap-in do Windows PowerShell chamado de PSSnapIn. Para criar um PSSnapIn, preciso escrever um pouco de cdigo para executar duas tarefas. Em primeiro lugar, fornecer identificao ao seu snap-in, permitindo distingui-lo de outros snap-ins instalados no sistema. Em segundo lugar, fornecer informaes para a instalao

adequada do snap-in e para a criao das entradas adequadas no Registro, permitindo ao Windows PowerShell localizar o assembly. H dois tipos de snap-ins do Windows PowerShell no namespace System.Management.Automation: PSSnapIn e CustomPSSnapIn. Use PSSnapIn quando quiser registrar automaticamente todos os cmdlets e provedores em um assembly. CustomPSSnapIn deve ser usado quando voc quiser registrar um subconjunto dos cmdlets e provedores em um assembly, ou ento quando quiser registrar cmdlets e provedores em diferentes assemblies. O cdigo do meu snap-in mostrado na Figura 7. bem simples. Eu apenas substituo os membros adequados e j est praticamente pronto. Figure 7 Snap-in para os meus cmdlets personalizados
// This class defines the properties of a snapin [RunInstaller(true)] public class IsolatedStorageCmdlets : PSSnapIn { /// <summary>Creates an instance of DemoSnapin class.</summary> public IsolatedStorageCmdlets() : base() { } ///<summary>The snap-in name that is used for registration</summary> public override string Name { get { return "IsolatedStorageCmdlets"; } } /// <summary>Gets vendor of the snap-in.</summary> public override string Vendor { get { return "James W. Truher"; } } /// <summary>Gets description of the snap-in. </summary> public override string Description { get { return "Isolated Storage Cmdlets"; } } /// <summary>The format file for the snap-in. </summary> private string[] _formats = { "IsolatedStorage.Format.ps1xml" }; public override string[] Formats { get { return _formats ; } } }

Formatando Observe na Figura 7 que h um valor para o membro Formats do snap-in. Isso permite criar diretivas de formatao para os objetos emitidos pelos cmdlets. Neste caso, tenho um objeto simples, mas no quero apresentar todos os membros por padro. Quero ter certeza de imprimir apenas as informaes teis, que neste caso so a chave e o valor. A criao desses arquivos de formato, por si s, j seria suficiente para produzir um artigo inteiro, e o assunto vai alm do escopo deste artigo. A Figura 8 apresenta um cdigo de exemplo que cria um formato de tabela com as duas colunas nas quais tenho interesse: a chave e o valor do objeto IsolatedStorageData. Para os fins deste exemplo, voc pode

simplesmente criar um arquivo denominado IsolatedStorage.Format.ps1xml no mesmo diretrio do assembly e, quando o snap-in for carregado, no ver nenhum erro. Figure 8 Arquivo de formato de exemplo
<Configuration> <ViewDefinitions> <View> <Name>IsolatedStorage</Name> <ViewSelectedBy> <TypeName>IsolatedStorageSnapin.IsolatedStorageData</TypeName> </ViewSelectedBy> <TableControl> <TableHeaders> <TableColumnHeader> <Label>Key</Label> <Width>12</Width> </TableColumnHeader> <TableColumnHeader /> </TableHeaders> <TableRowEntries> <TableRowEntry> <TableColumnItems> <TableColumnItem> <PropertyName>Key</PropertyName> </TableColumnItem> <TableColumnItem> <PropertyName>Value</PropertyName> </TableColumnItem> </TableColumnItems> </TableRowEntry> </TableRowEntries> </TableControl> </View> </ViewDefinitions> </Configuration>

Instalando e carregando um PSSnapIn muito fcil instalar um snap-in. Basta executar Installutil.exe com o caminho do seu assembly. Quando esse utilitrio executado, cria algumas entradas no Registro em HKLM\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapins\<snapinname>. Quando o Windows PowerShell carrega um snap-in, essas entradas so usadas para carregar o assembly e localizar os diversos arquivos de configurao. Tambm vale a pena mencionar que Installutil.exe o mtodo de instalao recomendado somente durante o desenvolvimento, uma vez que as aes do utilitrio no registram adequadamente suas dependncias de desinstalao. Para a instalao em ambientes de produo, configure diretamente as entradas no Registro. Tambm fcil carregar o snap-in. Os principais cmdlets que voc utilizar so AddPSSnapIn, Remove-PSSnapIn e Get-PSSnapIn. Como era de se esperar, add-PSSnapIn adiciona um ou mais snap-ins do Windows PowerShell sesso atual. Remove-PSSnapIn remove snap-ins da sesso atual. E Get-PSSnapIn recupera os snap-ins do Windows PowerShell no computador.

Observe que, na verdade, Remove-PSSnapIn no descarrega o assembly. Ele apenas remove os cmdlets e provedores das listas que o Windows PowerShell utiliza para localizar cmdlets e provedores de acesso. Juntando as peas Depois de fazer tudo o que acabo de descrever, estou pronto para comear a usar meus novos cmdlets personalizados. Logicamente, estou fazendo tudo isso a partir da linha de comando. Primeiro, preciso compilar o cdigo dos cmdlets e do snap-in. Lembra-se de que eu disse que precisaria compilar esse cdigo com uma referncia a System.Management.Automation.dll? Essa DLL pode ser encontrada no SDK e no GAC; mas, se voc no tiver o SDK instalado, no se preocupe. Este pequeno script pode criar facilmente o assembly Snap-In. Primeiro, preciso criar um alias para o compilador C#. Quando estiver estabelecido, localizo System.Management.Automation.dll e fao a compilao do assembly:
New-Alias csc "${V2Framework}\csc.exe" $SMADLL = [PSObject].Assembly.Location csc /target:library IsolatedStorageSnapin.cs /r:$SMADLL

Agora que j compilei o assembly, posso usar Installutil.exe para registrar meu novo snapin, conforme mostrado na Figura 9. Quando a instalao for concluda com xito, poderei localizar o novo PSSnapIn: Figura 9 Registrando o snap-in (Clique na imagem para aumentar a exibio)
PS> get-PSSnapIn -reg iso* Name : IsolatedStorageCmdlets PSVersion : 1.0 Description : Isolated Storage Cmdlets

Ento, adiciono o snap-in minha sesso:


PS> add-PSSnapIn IsolatedStorageCmdlets

E agora posso usar os cmdlets, conforme mostrado na Figura 10! Figura 10 Usando os cmdlets (Clique na imagem para aumentar a exibio)

Criando Grupos Locais Com Powershell


Neste post vou mostrar (Novamente) um script Powershell para gerenciar grupos locais, batendo novamente na mesma tecla, sobre quo poderoso o Powershell pode ser Vamos ao script: $GrupoLocal = $null $ComputadorLocal = [adsi]WinNT://localhost,computer [array]$grupos_list = grupo1,grupo2,grupo3,Administradores foreach($grupo in $grupos_list){ if([ADSI]::Exists(WinNT://localhost/$grupo,group)){ write-host existe } else {

write-host vai criar $GrupoLocal = $ComputadorLocal.Create(group,$grupo) $GrupoLocal.SetInfo() } } Agora as explicaes, Iniciamos o script criando um objeto de conexo com o computador local, $ComputadorLocal = [adsi]WinNT://localhost,computer, onde passamos o nome do computador e o tipo de objeto a qual estamos nos conectando. Aps isso temos uma Array (simplificando para quem no entende: Um grupo de strings.) que tem o nome dos grupos que quero verificar se existem no meu computador, [array] $grupos_list = grupo1,grupo2,grupo3,Administradores , utilizamos essa Array para efetuar um foreach (para cada) grupo na array, onde ele vai verificar se o grupo existe, caso o grupo exista if (se), ele no faz nada, caso o grupo no exista else (se no), criamos um novo objeto que ser o grupo utilizando a conexo que j havamos estipulado antes. Por fim efetuamos a criao do grupo utilizando o mtodo SetInfo() no objeto que criamos para ser o grupo.

Powershell para desenvolvedores Parte 1 Conhecendo


Ol pessoal, tudo certo? Sempre senti falta de um bom Shell em ambientes Microsoft. Quem usa Windows sempre careceu de uma alternativa interessante que pudesse ser, pelo menos minimamente, comparada com o Bash dos sistemas Unix-like. Ao meu ver, esta alternativa o Powershell! H quem considere o Powershell demasiadamente vervboso. H quem no goste do Powershell por sua dependncia com o .NET Framework. Eu gosto do Powershell por essas mesmas duas razes. Nessa nova srie pretendo demonstrar boas funcionalidades do Powershell para desenvolvedores. No post de hoje, mostro alguns conceitos fundamentais.

O que o Powershell?
Windows Powershell a promessa (ainda?!) da Microsoft para revolucionar o mundo da gesto de sistemas por meio de shells baseados em linha de comando. Atravs de pipelines baseadas em objetos, do ponto de vista de administradores de sistema, Powershell constitui um enorme salto em produtividade e potencialidade.

Powershell mais que uma verso aprimorada do Prompt de Comandos do Windows. Powershell voltado a scripts e parte integrande do Windows em verses posteriores ao 2008. Se o seu Windows no possui Powershell, baixe-o aqui.

Consideraes importantes para o Powershell


Alguns aspectos do Powershell so muito relevantes para quem est comeando. Considere: Powershell funciona muito bem com comandos e aplicaes padres do Windows. Isso significa que no necessrio descartar qualquer conhecimento que voc j possua sobre como utilizar o Prompt de Comandos do Windows; Powershell apresenta um tipo interiramente novo de comandos: os cmdlets. Esses comandos obedecem uma sintaxe padro baseada em Verbo-Substntivo fcil de lembrar; Powershell entende e consegue manipular objetos. Na prtica, podemos instanciar e manipular objetos .NET diretamente no shell; Powershell auto-explicativo. Com apenas trs comandos o usurio consegue obter informaes sobre como utilizar e o funcionamento das funcionalidades que o Powershell oferece; Powershell facilita a construo de scripts permitindo a automao de tarefas simples; Powershell tem suporte nativo para muitas tecnologias. Com ele fcil trabalhar com .NET, COM, WMI, XML, AD, ; Powershell simplifica a utilizao de depsitos de dados. Um mesmo modelo de trabalho utilizado para manipular, por exemplo, o registro do windows e a estrutura de arquivos e pastas.

Iniciando o Powershell
Carregar o Powershell muito fcil. Na prtica, basta iniciar o Powershell.exe no lugar de cmd.exe. Voc tambm encontra o Powershell em Iniciar > Todos os Programas > Acessrios > Windows Powershell.

Alm dessa verso (simples), h um ambiente mais carregado: Windows Powershell ISE: Pessoalmente, recomendaria comear com o prompt mais simples.

Primeiros passos (diretrios)


Considere a seguinte listagem:
1 2 3 4 PS PS PS PS C:\Users\Elemar> pushd C:\Users\Elemar> cd \ C:\> popd C:\Users\Elemar>

J aqui, podemos comear a observar o poder do powershell. Observe:

Na linha 1, podemos observar um novo comando do Powershell: pushd (que um alias para o comando Push-Location). O que ele faz? Salva o diretrio atual em uma pilha. Na linha 2, mudamos o diretrio atual. Na linha 3, o comando que complementa pushd: popd (que um alias para PopLocation). O que ele faz? Retira o diretrio armazenado no topo da pilha tornando-o atual. Para que serve? Bem, podemos mudar o diretrio atual facilitando a utilizao de comandos subsequentes, podendo voltar ao diretrio que era atual no incio das operaes rapidamente e sem traumas.

Conhecendo os Cmdlets (comandos estruturados do Powershell)


Alm dos aplicativos (executveis) suportados nativamente, Powershell apresenta um novo tipo, mais poderoso, de comandos conhecidos comando cmdlet (pronuncia-se CommandLet). Todos os cmdlets esto nomeados obedecendo ao padro Verbo-Substantivo, como GetProcess, Get-Content,, Stop-Process. Observe:
1 2 3 4 5 6 7 8 9 10 PS >Start-Process notepad PS >Get-Process notepad Handles ------56 56 PS > NPM(K) -----8 7 PM(K) ----2512 2212 WS(K) VM(M) ----- ----7176 74 6812 73 CPU(s) -----0,05 0,11 Id -7888 10416 ProcessName ----------notepad notepad

O que ocorreu? Na linha 1, iniciamos um processo (Sim, poderia ter digitado notepad diretamente). Na linha 2, obtive a lista de todos os processos com nome Notepad. O padro adotado pelo Powershell, embora verboso, simplifica a compreenso e o aprendizado. Uma vez que voc se familiarize com o trabalho realizado por alguns verbos (como, por exemplo: Get, Set, Start e Stop), fica mais fcil entender como operar alguns novos substantivos. Alm disso, no necessrio lembrar, ou escrever, o nome completo de todos os Cmdlets. Podemos utilizar a tecla TAB para auto-completar os nomes dos comandos e de seus argumentos (Get-Pro<TAB> notepad !!) Os mais conservadores podem dizer que, mesmo com o TAB, digita-se muito no Powershell. Para ajudar a melhorar a eficincia: Powershell define aliases para todos os comandos mais comuns; Permite que o usurio defina os seus prprios aliases; Totalmente case-insensitive. Isso significa que voc pode usar Get-Process, getprocess, GET-PROCESS (whatever) ;

Suporte nativo a objetos


Powershell possui suporte rico a objetos. Observe:
1 2 3 4 5 6 7 8 PS >"Hello World" Hello World PS >"Hello World".Length 11 PS >notepad PS >$notepad = Get-Process notepad PS >$notepad.kill() PS >

Comecemos pela linha 1. Basicamente, criamos um objeto string. Entendido? O bacana que esse objeto string o mesmo que voc j conhece do .NET Isso fica evidente nas linhas 3 e 4. Na linha 5, abro um notepad. Na linha 6, recupero o processo com nome notepad (espero que haja somente um) e o armazeno em uma varivel chamada $notepad (todas as variveis em Powershell devem iniciar com um $). Na linha 7 disparo uma chamada ao mtodo Kill ($notepad tem um objeto do tipo Process) fechando o notepad.

Uma caluladora interativa


O Powershell uma calculadora nativa. Observe:
1 2 3 4 5 6 7 PS >2+2 4 PS >1mb 1048576 PS >6gb/650mb 9,45230769230769 PS >

Podemos realizar operaes simples (como na linha 1). Quantos bytes h em um MB? Resposta solicitada e obtida nas linhas 3 e 4. Quandos CDs preciso para guardar 6 gigabytes? Respostas nas linhas 5 e 6.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 PS >[DateTime]::Now segunda-feira, 31 de janeiro de 2011 19:28:01 PS >[DateTime] "09/06/1979" quinta-feira, 6 de setembro de 1979 00:00:00 PS >$howOld = [DateTime]::Now - [DateTime]"06/09/1979" PS >$howOld Days Hours Minutes : 11559 : 19 : 29

18 19 20 21 22 23 24 25 26 27 28 29 30

Seconds Milliseconds Ticks TotalDays TotalHours TotalMinutes TotalSeconds TotalMilliseconds PS >$howOld.Days 11559 PS >

: : : : : : : :

54 949 9987497949490640 11559,6041082068 277430,498596962 16645829,9158177 998749794,949064 998749794949,064

Mais funcionalidades? Observe que consigo acessar um tipo do .NET colocando seu nome entre colchetes. Para acessar um membro esttico, utilizo a notao com dois dois pontos (linha 1). Que dia hoje? Linha 1 pergunta e linha 3 responde. Powershell tambm oferece Cast simples. Que dia da semana eu nasci? Linha 6 pergunta, linha 8 responde. Que idade eu tenho? Linha 11 pergunta, linhas 12 a 25 respondem. Observe na linha 28 que acessar propriedades do objeto muito simples.

Combinando Comandos
Sempre que um comando gerar uma sada, podemos usar um pipe para passar esse resultado como entrada para outro comando. Se o segundo comando entender os objetos produzidos pelo primeiro comando, podera operar com os resultados. Considere o seguinte comando (para fins de clareza, em vrias linhas):
1 PS >Get-Process | 2 Sort-Object -desc WorkingSet | 3 Select-Object -First 10 | 4 Format-Table ProcessName, WorkingSet -auto

O cmdlet da linha 1 carrega a lista de todos os processos executando na mquina. Observe que a sada uma coleo de objetos Process (que herdam de object), logo, so acessveis para um comando que espera objetos. Na linha 2, utilizo um cmdlet para ordenao. Por causa da pipe, esse cmdlet recebe a lista completa de objetos Process. Especifico que desejo que a sada seja esses objetos em sequncia ordenada descendente pelo tamanho do workingset. Na linha 3, utilizo um cmdlet para seleo. Por causa da pipe, esse cmdlet recebe uma lista de objetos Process ordenada. Especifico que desejo apenas os 10 primeiros elementos. Na linha 4, utilizo um cmdlet para apresentao. Por causa da pipe, esse cmdlet recebe a lista com os 10 processes com maior workingset. Fao com que a sada seja uma tabela apenas com o nome do processo e o WorkingSet.

Obtendo ajuda em 3 comandos: Aprendendo Cmdlets


Na hora de trabalhar com uma nova tecnologia que a coisa pega. Por sorte, Powershell ajuda a entender o sistema. Considere:
1 2 3 4 5 6 7 8 PS >Get-Command Format-* CommandType ----------Cmdlet Cmdlet Cmdlet Cmdlet Name ---Format-Custom Format-List Format-Table Format-Wide

Na linha 1, solicitei a lista de comandos com nomes compatveis com a mscara especificada. Para saber detalhes de funcionamento de um comando, utilizamos o cmdlet Get-Help. Observe:
1 2 3 4 5 6 7 8 9 PS >Get-Help Format-Table NOME Format-Table

SINOPSE Formata a sada como uma tabela. .. (continua)

Se temos um objeto, e desejamos saber o que podemos fazer com ele, usamos Get-Member. Observe:
1 PS >$notepad = Get-Process notepad 2 PS >$notepad | Get-Member 3 4 5 TypeName: System.Diagnostics.Process 6 7 Name MemberType 8 ------------9 Handles AliasProperty 10 Name AliasProperty 11 NPM AliasProperty NonpagedSystemMemorySize 12 PM AliasProperty 13 VM AliasProperty 14 WS AliasProperty 15 .. (continua)

Definition ---------Handles = Handlecount Name = ProcessName NPM = PM = PagedMemorySize VM = VirtualMemorySize WS = WorkingSet

Scripting
Powerhell trata comandos digitados diretamente pelo usurio da mesma forma que os trataria em scripts. Observe:
1 PS >$ws = 0

2 3 4 5

PS >foreach ($process in Get-Process) {$ws+=$process.WorkingSet} PS >$ws 3222622208 PS >

Crio uma varivel (chamada $ws) para acomodar o total de a soma dos workingsets de todos os processos. Utilizo o comando foreach (na linha 2) para percorrer todos os processos abertos somando seus workingsets em $ws. Outro bom exemplo:
1 2 3 4 5 6 7 8 9 PS >$wc = New-Object System.Net.WebClient PS >$feed = $wc.DownloadString("http://elemarjr.net/rss") PS >$feed <?xml version="1.0" encoding="UTF-8"?><rss version="0.92"> <channel> <title>Elemar DEV</title> <link>http://elemarjr.net</link> <description>Tecnologia e desenvolvimento .net</description> ... (continua)

Na linha 1, crio um WebClient, depois, fao o download do RSS do meu blog. Observe que fao tudo isso de forma interativa. Agora, observe:
1 2 3 4 5 6 7 PS PS PS PS PS PS PS >Clear-History >$wc = New-Object System.Net.WebClient >$feed = $wc.DownloadString("http://elemarjr.net/rss") >Get-History | ForEach-Object {$_.CommandLine} > c:\temp\getfeed.ps1 >notepad c:\temp\getfeed.ps1 >c:\temp\getfeed.ps1 >

Comeo limpando o histrico de comandos (linha 1). Depois, executo, de forma interativa, os comandos que desejo incluir em meu script. Por fim (linha 4), salvo a sequncia de comandos em um arquivo de scripts (geralmente extenso .ps1). Na linha 5, abro o notepad para fazer eventuais retoques (como retirar o cmdlet Clear-History da primeira linha).

Suporte nativo a tipos especiais


Como j foi dito, Powershell oferece suporte nativo a diversas tecnologias. Entre elas, XML. Observe:
1 2 3 4 5 6 7 8 9 10 11 12 13 PS PS PS PS >$wc = New-Object System.Net.WebClient >$content = $wc.DownloadString("http://elemarjr.net/rss") >$xml = [xml]$content >$xml rss --rss

xml --version="1.0" encoding="UTF-8" PS >$xml.rss.channel.item | select Title title -----

14 MSBuild 101 - Parte 4 - Simple Conditions 15 Escrevendo um Engine para Xadrez - Parte 11 - Mais Bitboards, Xeques e Escapadas 16 MSBuild 101 - Parte 3 -Items 17 Escrevendo um Engine para Xadrez - Parte 10 - PieceSet, Side, AttackMoves, Rays e 18 MSBuild 101 - Parte 2 - Conhecendo Tasks, Targets e Properties 19 Escrevendo um Engine para Xadrez - Parte 9 - Refactoring e Redesign 20 Sudoku - Backtracking e Pruning 21 Feedback para Desenvolvedores 22 Escrevendo um Engine para Xadrez - Parte 8 - Bispo e Dama 23 Escrevendo um Engine para Xadrez - Parte 7 - O movimento da torre 24 25 26 PS >

Na linha 3, declaro para o Powershell que o contedo da varivel $content xml. Depois disso, cada nodo tratado pelo powershell como uma propriedade. Veja como, no exemplo, recupero os ttulos de meus posts providos por RSS de maneira fcil e transparente. Outro exemplo bacana, a navegao pelo registro. Observe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 PS >Set-Location HKLM:\Software PS >Get-ChildItem Hive: HKEY_LOCAL_MACHINE\Software SKC --2 1 1 1 2 0 312 8 2 1 1 1 1 1 1 7 1 1 8 4 192 VC -0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 Name ---Alps Apple Computer, Inc. ATI Technologies Axalto BioAPI BROADCOM Classes Clients Creative Tech Cyberlink Debug Dell Dell Computer Corporation DeviceVM GEAR Software IDT IM Providers InstalledOptions Intel JavaSoft Microsoft Property -------{} {} {} {} {} {HostStoragePath} {} {} {} {} {} {} {} {} {} {} {} {} {LogElapsedTime, GUISettings} {} {(default)}

Os cmdlets Set-Location e Get-ChildItem so usados, geralmente, para tratar do filesystem. Aqui, voc pode ver esses mesmos comandos navegando pelo registro do Windows. Observe os aliases para esses comandos em ao:
1 PS >cd HKLM:\Software

2 PS >dir

Powershell para desenvolvedores Parte 2 Operadores e funes


Ol pessoal, tudo certo? No primeiro post dessa srie, mostrei os elementos fundamentais para utilizao do Powershell. No post de hoje, pretendo mostrar elementos que agradam todo programador: Operadores e funes. Sem delongas

Operadores de comparao
Powershell oferece um conjunto rico de operadores de comparao. Pela natureza linha de comando, no encontramos os opradores em sua sintaxe usual, mas no h nada de realmente desafiador aqui. Os operadores de comparao ficaram assim:
1 2 3 4 5 6 7 8 9 10

-eq: igual a; -ne: diferente de; -ge: maior ou igual a; -gt: maior que; -le: menor ou igual a; -lt: menor que; -like -notlike -match Combina com expresso regular; -notmatch No combina com expresso regular; -contains -notcontains -is -isnot

Comecemos por um exemplo:


PS > (dir).Count 25 PS > (dir).Count -eq 25 True PS > (dir).Count -ne 25 False PS > (dir).Count -gt 10 True PS > (Get-Process).Count 142

11 PS > 1gb -eq 1mb * 1024 12 True

Nas linhas 1 e 2, evidencio que todo cmdlet que retorne uma lista de objetos somente isso: uma lista. Quantos arquivos tenho em meu diretrio atual? Pergunto na linha 1, respondo na linha 2. Quantos processos abertos? Linha 9 pergunta, linha 10 responde. Um gigabyte = 1024 mb? Conforme as linhas 11 e 12, sim! Nas linhas entre 3 e 8, realizo algumas comparaes simples. Outro exemplo:
1 PS > $result = .\curl http://elemarjr.net/feed/ 2 % Total % Received % Xferd Average Speed Time Current 3 Dload Upload Total Speed 4 100 577k 0 577k 0 0 221k 0 --:--:---:--:-- 237k 5 PS > $xml = [xml] $result 6 PS > ($xml.rss.channel.item).Count -gt 5 7 True Time Spent 0:00:02 Time Left

Logo na linha 1, uma operao bacana. Pego o resultado da operao de um aplicativo externo, o cURL (tema suficiente para um post inteiro), que um navegador web texto, e atributo a varivel $result. Na linha 5, utilizo o suporte nativo do Powershell para xml. Na linha 6, verifico se a quantidade de nodos Item, em rss.channel, maior que 10. Agora, um pouco de expresses regulares:
1 2 3 4 5 6 7 8 9 10 11 PS > $h PS > $h True PS > $h True PS > $h False PS > $h True PS > $h False = "Hello World" -match "H.*World" -match "Hello" -match "Hello$" -match "^Hello" -match "^ello"

Aqui, temos algumas comparaes realizadas com expresses regulares. Agora, considere o exemplo abaixo:
1 2 3 4 PS > "hello world" -eq "Hello World" True PS > "hello world" -ceq "Hello World" False

Pelas linha 1 e 2, percebemos que todos os operadores de comparao padro do Powershell so case-insensitive. Para comparaes case-sensitive, basta adicionar um c antes do nome do operador (linhas 3 e 4). Agora, uma idia dos operadores de lista:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

PS > 1..10 1 2 3 4 5 6 7 8 9 10 PS > 1..10 -contains 3 True PS > 1..10 -contains 9 True PS > 1..10 -contains 11 False

Compreendido? 1..10 gera uma lista com nmeros de 1 at 10. O contains verifica se um elemento est na lista. Alis, aproveitando a brincadeira, observe:
1 2 3 4 5 6 7 8 9 10 11 12 PS > foreach ($n in 1..10) {$n*$n} 1 4 9 16 25 36 49 64 81 100 PS >

Operadores de comparao
Os operadores lgicos so: -and -or -xor: ou exclusivo (True xor False = True; False xor True = True, falso para todos os outros casos. -not Observe:
1 2 3 4 5 PS > (2 -eq 2) -and (4 -gt 2) True PS > -not (2 -eq 2) False PS >

Auto-explicativo, no ?!

Where-Object: o rei dos filtros


Agora que j sabemos fazer comparaes, vejamos como construir filtros para nossas listas baseados em condies. Observe:
1 PS > Get-Process | Where-Object { $_.ProcessName -match "^W.*"} 2 3 Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName 4 ------- -------------- ----------- ----------5 152 13 30280 7908 103 0,09 6416 WebcamDell2 6 1128 160 151540 148552 463 116,69 9080 WindowsLiveWriter 7 81 10 1744 4664 47 0,08 528 wininit 8 132 10 3512 7824 53 0,27 756 winlogon 9 355 23 7188 15276 85 0,22 1708 wlanext 10 345 21 6808 15232 77 0,19 3500 WLIDSVC 11 59 6 1556 3608 33 0,00 3632 WLIDSVCM 12 442 34 33316 41760 175 9,03 1372 WmiPrvSE 13 355 15 12148 17152 61 9,13 3052 WmiPrvSE 14 124 12 5760 7704 38 0,45 4984 WmiPrvSE 15 142 12 4364 8172 36 0,66 5808 WmiPrvSE 16 593 48 42032 57860 208 79,25 8544 wmplayer 17 93 9 2228 6708 69 0,03 7048 wuauclt 18 200 10 1844 5132 34 0,03 1500 WUDFHost 19 20 21 PS > Get-Process | Where-Object 22 { $_.ProcessName -match "^W.*" -and $_.Handles -lt 100} 23 24 Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName 25 ------- -------------- ----------- ----------26 81 10 1744 4664 47 0,08 528 wininit 27 59 6 1556 3608 33 0,00 3632 WLIDSVCM 28 93 9 2228 6708 69 0,03 7048 wuauclt

Importante: O contedo das linhas 21 e 22 deve estar na mesma linha. Utilizei duas para respeitar o layout do blog. O cmdlet WhereObject espera uma expresso lgica (que retorne verdadeiro ou falso). O elemento da lista que est sendo avaliado representado pela varivel reservada $_.

Refactoring no Powershell Extract method (!?)


Powershell permite que definamos funes. Criando algumas funes utilitrias, podemos simplificar nossos scripts. Observe:
1 2 3 4 5 PS C:\Users\Elemar> function EhPar($n) {$n % 2 -eq 0} PS C:\Users\Elemar> EhPar(10) True PS C:\Users\Elemar> EhPar(5) False

Powershell para desenvolvedores Parte 3 Desvios condicionais e Loops


Ol pessoal, tudo certo?! Passado algum tempo, voltamos ao Powershell. No primeiro post, apresentei os primeiros passoas para utilizao dessa ferramenta. Na segundo post, falei sobre operadores e funes. Hoje, vou tratar de desvios condicionais e laos de petio. Sem mais delongas

Escrevendo scripts para Powershell


At aqui, todos os exemplos que foram apresentados eram comandos digitados um-porum no console. Na maioria dos casos suficiente, em outros tantos no . Scripts powershell so salvos em arquivos comuns com extenso .ps1. Voc pode criar scripts utilizando o Notepad, se preferir. Eu crio meus scripts usando o PowerShell ISE (que acompanha o Powershell 2). Veja o programa na figura: Como voc pode ver, essa janela dividida em trs painis: 1. painel de scripts onde voc cria seus arquivos de script; 2. painel de comando (no meio) onde voc pode digitar comandos powershell isoladamente, da mesma forma que faria no console; 3. painel de sada (o primeiro, de baixo para cima) onde so exibidos os resultados de execuo dos comandos ou scripts. Bacana! Repare que o painel para scripts do powershell suporta code-completing e colorcoding. Alm disso, na toolbar voc pode perceber algumas ferramentas para apoiar a execuo e depurao de scripts. Observe:

Desvios condicionais simples if .. elseif .. else


Em powershell, podemos usar desvios condicionais elaborados, semelhantes aos disponveis em nossas linguagens de programao. Observe: 01 02 03 04 05 if ($v -lt 5) { "Menor que 5." } elseif ($v -lt 15)

06 07 08 09 10 11 12 13 14 15 16

{ "Menor que 15." } elseif ($v -lt 40) { "Menor que 40." } else { "Whatever!" }

O conceito aqui simples. No vou explicar como funciona um if, j que essa srie direcionada para desenvolvedores. A nica diferena percebida (mesmo) so os operadores de comparao. Considere esse exemplo um pouco mais elaborado: 1 2 3 4 5 6 7 8 if(Get-Process | Where-Object { $_.Name -eq "calc" }) { "Windows calc is Running" } else { "Windows calc is Not Running" }

Esse pequeno script verifica se a calculadora est em execuo. Perceba que todo esse script poderia ser digitado em uma nica linha dispensando a criao de um arquivo de script. S para lembrar: Para executar um arquivo de script (no meu exemplo, if.ps1) necessrio fazer referncia ao diretrio em que esse arquivo est salvo, mesmo que seja corrente (ex: ./if.ps1).

Desvios condicionais com mltipla escolha Switch


Powershell tambm fornece suporte a desvios condicionais usando switch. Observe: 1 switch ($v) 2 { 3 {$v -lt 5} { "Menor que 5."; break } 4 {$v -lt 15} { "Menor que 15."; break }

5 6 7 8 }

{$v -lt 40} { "Menor que 40."; break } 40 { "40!"; break } default { "Whatever" }

Como voc pode observar, cada opo de escolha consiste de dois blocos.

Repetindo blocos de execuo for


O que voc acha de usar o bom e velho for do C# no Powershell? Voc pode! Observe: 1 for ($counter = 1; $counter -le 10; $counter ++) 2 { 3 "Loop number $counter" 4 } Veja como simples. A sintaxe bem parecida com a que estamos acostumados no C#. No acha?

Pecorrendo listas foreach e ForEach-Obejct


Se h for, deve haver foreach. Certo? Certo! Observe: 1 foreach ($file in dir) 2 { 3 "File length: " + $file.Length 4 } Como voc j deve saber, dir o alias para Get-ChildItem. H um cmdlet com a mesma funo de for, trata-se do ForEach-Object. Observe: 1 dir | ForEach-Object { "File length: " + $_.Length }

Repetindo Repetindo .. while / do..while / do..until


Outra semelhanca: Powershell suporta while. Observe: 1 2 3 4 5 $response = "" while ($response -ne "q") { $response = Read-Host "Type something (q to quit)" }

Tambm tem do..while. Observe: 1 2 3 4 5 $response = "" while ($response -ne "q") { $response = Read-Host "Type something (q to quit)" }

E vai alm: temos o do..until. Observe: 1 do 2 { 3 $response = Read-Host "Type something (q to quit)" 4 } until ($response -eq "q")

Você também pode gostar