Microsoft Windows PowerShell

Introdução

O PowerShell é basicamente uma “linguagem” de scripting criada pela Microsoft para administradores de sistemas, a sua syntax é um misto de Perl, C++ e C#. O PowerShell é distribuído livremente e tem como grande objectivo a substituição de VBscript e batch scripting. Windows PowerShell é um “ambiente” para cmdlets, funções, filtros, executáveis e aliases.

O PowerShell é baseado na Framework .NET. Assim, tem como principal vantagem a integração quase directa de componentes .NET.

Enquadramento

Este pequeno artigo tem como principal objectivo ilustrar as potencialidades desta “linguagem”. Pessoalmente, já desde 2007 que tento influenciar todos aqueles administradores de sistemas ou helpdesks para usarem esta ferramenta, pois acho que é extremamente poderosa e de enorme valia.

Historicamente, o cmd da Microsoft sempre foi bastante limitado, isto deve-se ao facto da Microsoft definir como “target” do seu sistema operativo, o utilizador comum que acaba por não ser muito dotado tecnicamente. Grande parte dos esforços no desenvolvimento do Windows foram apontados para o interface e a sua usabilidade, em detrimento da criação de um ambiente mais orientado para profissionais. Em suma, o PowerShell veio colmatar a falha que existia na gestão do sistema operativo Windows por linha de comandos.

Instalação

Para instalar o PowerShell, necessitam da Framework 2.0 da Microsoft, e de fazer download do respectivo pacote PowerShell: http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx.

Após a instalação do PowerShell, devem aceder à consola do Windows PowerShell e executar o seguinte comando.

Set-Executionpolicy Unrestricted

Com este comando “vão” retirar todas as restrições de execução de scripts PowerShell na vossa máquina. O PowerShell possui um mecanismo de segurança que assenta em assinaturas de scripts e permissões de execução. Fica aqui um apanhado dos possíveis perfis:

Restricted
Não podem ser executadas scripts. O Windows PowerShell só pode ser usado através do PowerShell command mode.
AllSigned
Apenas scripts assinadas podem ser executadas
RemoteSigned
Downloaded Scripts têm que ser assinados para poderem ser executados.
Unrestricted
Sem qualquer restrição de execução.

Let’s Rock

Breve introdução

Façamos uma breve introdução à sintaxe da linguagem…

Variáveis

Têm que começar pelo símbolo $ .

$a=32

Pode ser escrito da seguinte forma para forçar o tipo de dados.

[int]$a=32
Arrays, hash’s
# Isto é um comentário
$a= 1,2,3,4,5  # Array
$a= @(1,2,3,4,5) # Array
 
 
$loc = @{"Braga" = "Portugal"; "Madrid" = "Espanha"} #Hash

Comandos Essenciais

Get-Help 
Get-Service
Get-Command

Criação de Instâncias

$d = New-Object -Type System.DateTime 2006,12,25 
$d.get_DayOfWeek()
Output para a consola
Write-Host $a –foregroundcolor “green”
$a
Capturar input
$a = Read-Host “Nome ?” 
Write-Host "Olá " $a
Quebra de linha
Get-Process | `
Select-Object ` 
name, ID Comments 
Ciclos, Loops
 
$a=1 
Do 
{$a; $a++} 
While ($a –lt 10)
 
$a=1 Do {$a; $a++} Until ($a –gt 10)
 
For ($a=1; $a –le 10; $a++) 
{$a}
 
Foreach ($i in Get-Childitem c:windows) 
{$i.name; $i.creationtime}
Controle If-Then-Else
$a = "white" 
if ($a -eq "red") {"Vermelho"} 
elseif ($a -eq "white") {"Branco"} else {"nao sei"}
 
$a = "red" switch ($a) { 
"red" {"vermelho"} 
"white"{"branco"} 
default{"nao sei"} }

Programming, Programming …

Ok, vamos lá ver qual a “velocidade que isto dá” ;-).

Nota: O conceito de pipe | está muito enraizado no uso do PowerShell!

  • Imprimir todos os processo da minha máquina.
   get-process | ForEach-Object { write-host $_.ProcessName $_.CPU}
 
   # Ordenando-os por tempo de CPU
   get-process |Sort-Object CPU
 
   #Guardando o resultado dos primeiros 10 numa variavel
   $P = get-process | Sort-Object CPU –descending | select-object –first 10
 
   #fazendo DUMP da variavel para um ficheiro
   $P > c:A4.txt

Façamos uma breve explicação do que foi feito no script anterior.

O cmdlet get-process retorna todos uma lista de processos em execução. No exemplo anterior, bastou redireccionar a saída (“output”) do comando para um loop foreach para ser possível “trabalhar” o resultado.

A variável interna $_ armazena a saída do |.

Como é que se sabe quais as propriedades que o objecto $_ possui? simples, usa-se o cmdlet get-member. Este cmdlet permite retornar todas as propriedades e métodos de um dado objecto.

Experimentem o seguinte:

get-process  | select-object -first 1 | get-member 

Se desejarem apenas saber quais as propriedades, basta filtrarem pelo -MemberType.

get-process  | select-object -first 1 | get-member -MemberType property 

Eis o “dump” do último comando …

NameMemberType
BasePriorityProperty
ContainerProperty
IdProperty
MachineNameProperty
MainModuleProperty
……….Property
……….Property
ThreadsProperty
TotalProcessorTimeProperty
UserProcessorTimeProperty
VirtualMemorySizeProperty
VirtualMemorySize64Property
WorkingSetProperty
WorkingSet64Property
  • Ver o tamanho do meu event log "System"
   get-eventlog -list | where-object {$_.logdisplayname -eq "System"}
  • Listar os últimos 3 eventos "System"
   get-eventlog system -newest 3
  • Listar os últimos 3 eventos "System", formatando-os
   get-eventlog system -newest 3 | format-list
  • Listar todos os ficheiros excepto os temporários, imprimindo o nome e o tamanho
  Get-childitem c:* –exclude *.tmp | select-object name, length
  • Listar todos os serviços e exportá-los para HTML
   get-service | convertto-html
 
   #exportá-los  para um ficheiro
   get-service | convertto-html > .a10.html
  • Algo mais elaborado… Listar todos os meus serviços, exportá-los para HTML, separando por cores os que estão a correr dos que estão parados.
  get-service | ConvertTo-Html -Property Name,Status | `
  foreach { if($_ -like "*<td>Running</td>*") {$_ -replace "<td>", "<tr bgcolor=green>"} `
  else {$_ -replace "<tr>", "<tr bgcolor=red>"}} >.get-service.html

Com estes pequenos exemplos verificamos as enormes potencialidades desta “linguagem”.

  • vamos lá carregar no acelerador :-P
# Todos os ficheiros, recursivamente, cujo tamanho seja maior que 20MB
get-childitem -recurse c:temp | where-object {$_.length –gt 2000000} 
 
# Todos os ficheiros *.Doc que não sejam readonly
get-childitem *.doc | foreach-object {$_.Isreadonly = 0}
 
# Ler um ficheiro
$a = Get-Content "c:servers.txt" 
foreach ($i in $a) {$i}
 
# Criar um ficheiro excel (2003) com os dados de um serviço.
$a = new-object -comobject excel.application 
$a.Visible = $True 
$b = $a.Workbooks.Add() 
$c = $b.Worksheets.Item(1) 
$c.Cells.Item(1,1) = "Nome Serviço" 
$c.Cells.Item(1,2) = "Estado" 
$i = 2 
get-service | foreach-object{ $c.cells.item($i,1) = $_.name; $c.cells.item($i,2) = $_.status; $i=$i+1} 
$b.SaveAs("c:Test.xls") 
$a.Quit()
 
# Who Am I
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name