Existem componentes de software com interfaces do .NET Framework e COM que permitem que você execute muitas tarefas de administração do sistema. O Windows PowerShell permite que você utilize esses componentes, para que não fique limitado às tarefas que podem ser executadas com os cmdlets. Muitos dos cmdlets da versão inicial do Windows PowerShell não funcionam em computadores remotos. Demonstraremos como podemos contornar essa limitação quando estivermos gerenciando logs de eventos com a classe .NET Framework System.Diagnostics.EventLog diretamente do Windows PowerShell.

Usando New-Object para obter acesso ao log de eventos

A .NET Framework Class Library inclui uma classe chamada System.Diagnostics.EventLog que pode ser usada no gerenciamento de logs de eventos. Você pode criar uma nova instância de uma classe .NET Framework usando o cmdlet New-Object com o parâmetro TypeName. Por exemplo, o comando a seguir cria uma referência de log de eventos:

PS> New-Object -TypeName System.Diagnostics.EventLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----

Embora o comando tenha criado uma instância da classe EventLog, ela não inclui dado algum. Isso aconteceu porque não especificamos um log de eventos específico. Como você pode obter um log de eventos real?

Usando construtores com New-Object

Para fazer referência a um log de eventos, você precisa especificar o seu nome. New-Object tem um parâmetro ArgumentList. Os argumentos passados como valores para esse parâmetro são usados por um método especial de inicialização do objeto. O método é chamado de construtor porque é usado para construir o objeto. Por exemplo, para obter uma referência ao log Aplicativo, especifique a cadeia de caracteres 'Application' como um argumento:

PS> New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application

Max(K) Retain OverflowAction        Entries Name
------ ------ --------------        ------- ----
16,384      7 OverwriteOlder          2,160 Application
Observação:

Uma vez que a maioria das classes do núcleo do .NET Framework está contida no namespace System, o Windows PowerShell tentará encontrar automaticamente classes especificadas por você no namespace System se não puder encontrar uma correspondência para o nome do tipo especificado. Isso significa que você pode especificar Diagnostics.EventLog em vez de System.Diagnostics.EventLog.

Armazenando objetos em variáveis

Convém armazenar uma referência a um objeto para que você possa usá-la no shell atual. Embora o Windows PowerShell permita que você faça muita coisa com os pipelines, diminuindo o uso de variáveis, algumas vezes o armazenamento de referências a objetos em variáveis torna sua manipulação mais conveniente.

O Windows PowerShell permite que você crie variáveis que sejam, essencialmente, objetos nomeados. A saída de qualquer comando válido do Windows PowerShell pode ser armazenada em uma variável. Os nomes de variável sempre começam com $. Se você quiser armazenar a referência ao log Aplicativo em uma variável chamada $AppLog, digite o nome da variável seguido por um sinal de igual e então digite o comando utilizado na criação do objeto do log Aplicativo:

PS> $AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application

Se então você digitar $AppLog, poderá ver que ela contém o log Aplicativo:

PS> $AppLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
  16,384      7 OverwriteOlder          2,160 Application

Acessando um log de eventos remoto com New-Object

Os comandos utilizados na seção anterior têm como alvo o computador local; o cmdlet Get-EventLog pode fazer isso. Para acessar o log Aplicativo de um computador remoto, você deve fornecer o nome do log e um nome de computador (ou endereço IP) como argumentos.

PS> $RemoteAppLog = New-Object -TypeName System.Diagnostics.EventLog Application,192.168.1.81
PS> $RemoteAppLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
     512      7 OverwriteOlder            262 Application

Agora que temos uma referência a um log de eventos armazenado na variável $RemoteAppLog, que tarefas podemos executar com ela?

Limpando um log de eventos com métodos de objeto

Quase sempre, os objetos possuem métodos que podem ser chamados para a execução de tarefas. Você pode usar Get-Member para exibir os métodos associados a um objeto. O comando a seguir e a saída selecionada mostram alguns dos métodos da classe EventLog:

PS> $RemoteAppLog | Get-Member -MemberType Method


   TypeName: System.Diagnostics.EventLog

Name                      MemberType Definition
----                      ---------- ----------
...
Clear                     Method     System.Void Clear()
Close                     Method     System.Void Close()
...
GetType                   Method     System.Type GetType()
...
ModifyOverflowPolicy      Method     System.Void ModifyOverflowPolicy(Overfl...
RegisterDisplayName       Method     System.Void RegisterDisplayName(String ...
...
ToString                  Method     System.String ToString()
WriteEntry                Method     System.Void WriteEntry(String message),...
WriteEvent                Method     System.Void WriteEvent(EventInstance in...

O método Clear() pode ser usado para limpar o log de eventos. Sempre coloque parênteses após o nome do método quando o chamar, mesmo se ele não exigir argumentos. Isso permite que o Windows PowerShell faça a distinção entre o método e uma propriedade que possivelmente tenha o mesmo nome. Para chamar o método Clear, digite:

PS> $RemoteAppLog.Clear()

Digite o código a seguir para exibir o log. Você verá que o log de eventos foi limpo e agora há 0 entradas em vez de 262:

PS> $RemoteAppLog

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
     512      7 OverwriteOlder              0 Application

Criando objetos COM com New-Object

Você pode usar New-Object para trabalhar com componentes COM (Component Object Model). Os componentes podem variar de muitas bibliotecas incluídas no Windows Script Host (WSH) a aplicativos ActiveX, como o Internet Explorer, instalados na maioria dos sistemas.

New-Object usa RCWs (Runtime Callable Wrappers) do .NET Framework para criar objetos COM e, portanto, tem as mesmas limitações do .NET Framework quando chama esses objetos. Para criar um objeto COM, você precisa especificar o parâmetro ComObject com o Identificador Programático, ou ProgId, da classe COM que deseja utilizar. Uma descrição completa sobre as limitações do uso de COM e sobre como determinar quais ProgIds estão disponíveis em um sistema estão além do escopo deste guia do usuário, mas a maioria dos objetos conhecidos de ambientes como WSH pode ser usada no Windows PowerShell.

Você pode criar os objetos do WSH especificando estes progids: WScript.Shell, WScript.Network, Scripting.Dictionary e Scripting.FileSystemObject. Os comandos a seguir criam esses objetos:

New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject

Embora quase toda a funcionalidade dessas classes esteja disponível de outras formas no Windows PowerShell, algumas tarefas como a criação de atalhos são mais fáceis de executar usando as classes do WSH.

Criando um atalho da área de trabalho com WScript.Shell

Uma tarefa que pode ser executada rapidamente com um objeto COM é a criação de um atalho. Suponha que você queira criar um atalho em sua área de trabalho que leve até à página inicial do Windows PowerShell. Primeiro você precisa criar uma referência a WScript.Shell, que armazenaremos em uma variável chamada $WshShell:

$WshShell = New-Object -ComObject WScript.Shell

Get-Member trabalha com objetos COM. Desse modo, você pode explorar os membros do objeto digitando:

PS> $WshShell | Get-Member


   TypeName: System.__ComObject#{41904400-be18-11d3-a28b-00104bd35090}

Name                     MemberType            Definition
----                     ----------            ----------
AppActivate              Method                bool AppActivate (Variant, Va...
CreateShortcut           Method                IDispatch CreateShortcut (str...
...

Get-Member tem um parâmetro opcional InputObject que pode ser usado no lugar do pipeline para fornecer uma entrada para Get-Member. Você obteria a mesma saída mostrada anteriormente se usasse o comando Get-Member -InputObject $WshShell. Se você usar InputObject, ele tratará seus argumentos como um único item. Isso significa que, se você tiver vários objetos em uma variável, Get-Member os tratará como uma matriz de objetos. Por exemplo:

PS> $a = 1,2,"three"
PS> Get-Member -InputObject $a
TypeName: System.Object[]
Name               MemberType    Definition
----               ----------    ----------
Count              AliasProperty Count = Length
...

O método WScript.Shell CreateShortcut aceita um único argumento, o caminho para o arquivo de atalho a ser criado. Poderíamos digitar o caminho completo até a área de trabalho, mas há uma maneira mais fácil. A área de trabalho é normalmente representada por uma pasta chamada Desktop, na pasta inicial do usuário atual. O Windows PowerShell tem uma variável $Home que contém o caminho até essa pasta. Podemos especificar o caminho até a pasta inicial usando essa variável e então adicionamos o nome da pasta Desktop e o nome do atalho a ser criado, digitando:

$lnk = $WshShell.CreateShortcut("$Home\Desktop\PSHome.lnk")

Quando você utiliza algo que se parece com um nome de variável entre aspas, o Windows PowerShell tenta substituí-lo por um valor equivalente. Se você utilizar aspas simples, o Windows PowerShell não tentará substituir o valor da variável. Por exemplo, experimente digitar os comandos a seguir:

PS> "$Home\Desktop\PSHome.lnk"
C:\Documents and Settings\aka\Desktop\PSHome.lnk
PS> '$Home\Desktop\PSHome.lnk'
$Home\Desktop\PSHome.lnk

Agora existe uma variável chamada $lnk que contém uma nova referência ao atalho. Se você quiser exibir seus membros, envie-a para Get-Member pelo pipeline. A saída a seguir mostra os membros que precisamos usar para finalizarmos a criação do nosso atalho:

PS> $lnk | Get-Member

TypeName: System.__ComObject#{f935dc23-1cf0-11d0-adb9-00c04fd58a0b}

Name MemberType Definition

---- ---------- ----------

...

Save Method void Save ()

...

TargetPath Property string TargetPath () {get} {set}

...

Precisamos especificar o TargetPath, que é a pasta de aplicativos do Windows PowerShell, e salvar o atalho $lnk chamando o método Save. Como o caminho da pasta de aplicativos do Windows PowerShell está armazenado na variável $PSHome, podemos fazer isso digitando:

$lnk.TargetPath = $PSHome

$lnk.Save()

Usando o Internet Explorer a partir do Windows PowerShell

Muitos aplicativos (incluindo a família Microsoft Office e o Internet Explorer) podem ser automatizados com COM. O Internet Explorer ilustra algumas das técnicas e problemas mais comuns envolvidos no trabalho com aplicativos baseados em COM.

Você pode criar uma instância do Internet Explorer especificando o ProgId do Internet Explorer, InternetExplorer.Application:

$ie = New-Object -ComObject InternetExplorer.Application

Esse comando inicia o Internet Explorer, mas não o torna visível. Se você digitar Get-Process, poderá ver que um processo chamado iexplore está em execução. Na verdade, se você sair do Windows PowerShell, o processo continuará em execução. É preciso reiniciar o computador ou usar uma ferramenta como o Gerenciador de tarefas para encerrar o processo iexplore.

Observação:

Os objetos COM iniciados como processos separados, comumente chamados de executáveis ActiveX, podem ou não exibir uma janela de interface do usuário quando são iniciados. Se eles criarem uma janela mas não a tornarem visível, como o Internet Explorer, o foco geralmente será movido para a área de trabalho do Windows, e você deverá torná-la visível para interagir com ela.

Se você digitar $ie | Get-Member, poderá ver propriedades e métodos do Internet Explorer. Para exibir a janela do Internet Explorer, defina a propriedade Visible como $true, digitando:

$ie.Visible = $true

Será possível então navegar até um endereço Web específico usando o método Navigate:

$ie.Navigate("http://www.microsoft.com/technet/scriptcenter/default.mspx")

Utilizando outros membros do modelo de objeto do Internet Explorer, é possível recuperar conteúdo de texto da página da Web. O comando a seguir exibirá o texto HTML no corpo da página da Web atual:

$ie.Document.Body.InnerText

Para fechar o Internet Explorer a partir do Windows PowerShell, chame o seu método Quit():

$ie.Quit()

Isso o forçará a fechar. A variável $ie não contém mais uma referência válida, mesmo que ainda aparente ser um objeto COM. Caso você tente usá-la, obterá um erro de automação:

PS> $ie | Get-Member
Get-Member : Exception retrieving the string representation for property "Appli
cation" : "The object invoked has disconnected from its clients. (Exception fro
m HRESULT: 0x80010108 (RPC_E_DISCONNECTED))"
At line:1 char:16
+ $ie | Get-Member <<<<

Você pode remover a referência restante com um comando como $ie = $null ou remover completamente a variável, digitando:

Remove-Variable ie
Observação:

Não há um padrão comum para a forma como os executáveis ActiveX são fechados ou continuam a ser executados quando você remove uma referência para um deles. Dependendo das circunstâncias, como por exemplo se o aplicativo está visível, se um documento editado está sendo executado nele ou até mesmo se o Windows PowerShell ainda está em execução, o aplicativo pode ou não ser encerrado. Por esse motivo, você deve testar o comportamento de fechamento de cada executável ActiveX que deseja utilizar no Windows PowerShell.

Obtendo avisos sobre objetos COM encapsulados do .NET Framework

Em alguns casos, um objeto COM pode ter um RCW (Runtime-Callable Wrapper) associado do .NET Framework e ele será usado por New-Object. Como o comportamento do RCW pode ser diferente do comportamento do objeto COM normal, New-Object tem um parâmetro Strict que o avisa sobre o acesso do RCW. Se você especificar o parâmetro Strict e criar um objeto COM que usa um RCW, obterá uma mensagem de aviso:

PS> $xl = New-Object -ComObject Excel.Application -Strict
New-Object : The object written to the pipeline is an instance of the type "Mic
rosoft.Office.Interop.Excel.ApplicationClass" from the component's primary inte
rop assembly. If this type exposes different members than the IDispatch members
, scripts written to work with this object might not work if the primary intero
p assembly is not installed.
At line:1 char:17
+ $xl = New-Object  <<<< -ComObject Excel.Application -Strict

Embora o objeto seja criado mesmo assim, você será avisado de que ele não é um objeto COM padrão.




Sumário