Criando objetos .NET e COM

Este exemplo só é executado em plataformas Windows.

Existem componentes de software com as interfaces .NET Framework e COM que permitem executar muitas tarefas de administração do sistema. O PowerShell permite usar esses componentes para que você não fique limitado a tarefas que podem ser executadas usando cmdlets. Muitos dos cmdlets na versão inicial do PowerShell não funcionam em computadores remotos. Demonstraremos como contornar essa limitação gerenciando logs de eventos usando a classe System.Diagnostics.EventLog do .NET Framework diretamente do PowerShell.

Uso de New-Object para acesso ao log de eventos

A Biblioteca de Classes do .NET Framework inclui uma classe chamada System.Diagnostics.EventLog que pode ser usada para gerenciar logs de eventos. Você pode criar uma nova instância de uma classe do .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:

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 nenhum dado. isso ocorre porque não especificamos um log de eventos específico. Como obter um log de eventos real?

Uso de construtores com New-Object

Para consultar um log de eventos específico, é necessário especificar o nome do log. New-Object tem um parâmetro ArgumentList. Os argumentos que você passa 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 ele é usado para construir o objeto. Por exemplo, para obter uma referência para o Log do aplicativo, especifique a cadeia de caracteres “Application” (Aplicativo) como um argumento:

New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
Max(K) Retain OverflowAction        Entries Name
------ ------ --------------        ------- ----
16,384      7 OverwriteOlder          2,160 Application

Observação

Como a maioria das classes .NET está contida no namespace System, o PowerShell tenta localizar automaticamente as classes que você especifica no namespace System se não encontrar uma correspondência para o nome de tipo especificado. Isso significa que você pode especificar Diagnostics.EventLog em vez de System.Diagnostics.EventLog.

Armazenar objetos em variáveis

Pode ser útil armazenar uma referência a um objeto para que você pode usá-lo no shell atual. Embora o PowerShell permita fazer grande parte do trabalho com pipelines, reduzindo a necessidade de variáveis, às vezes armazenar as referências a objetos em variáveis torna mais conveniente a tarefa de manipular esses objetos.

A saída de qualquer comando válido do PowerShell pode ser armazenada em uma variável. Nomes de variáveis sempre começam com $. Se você deseja armazenar a referência de log do aplicativo em uma variável chamada $AppLog, digite o nome da variável, seguido por um sinal de igual e, em seguida, digite o comando usado para criar o objeto do log do aplicativo:

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

Se você digitar $AppLog, poderá ver que ele contém o log do aplicativo:

$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 usados na seção anterior destinam-se ao computador local. O cmdlet Get-EventLog pode fazer isso. Para acessar o log do aplicativo em um computador remoto, você deve fornecer tanto o nome do log quanto um nome do computador (ou endereço IP) como argumentos.

$RemoteAppLog = New-Object -TypeName System.Diagnostics.EventLog Application, 192.168.1.81
$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, quais tarefas que podemos realizar nela?

Limpar um log de eventos com métodos de objeto

Objetos geralmente têm métodos que podem ser chamados para executar tarefas. Você pode usar Get-Member para exibir os métodos associados a um objeto. O seguinte comando e a saída selecionada mostram alguns métodos da classe EventLog:

$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. Ao chamar um método, você sempre deverá acrescentar parênteses ao fim do nome do método, mesmo que ele não exija argumentos. Isso permite que o PowerShell faça distinção entre o método e uma propriedade em potencial com o mesmo nome. Digite o seguinte para chamar o método Clear:

$RemoteAppLog.Clear()
$RemoteAppLog
  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
     512      7 OverwriteOlder              0 Application

Observe que o log de eventos foi limpo e agora tem 0 entradas em vez de 262.

Criação de objetos COM usando New-Object

Você pode usar New-Object para trabalhar com componentes COM (Component Object Model). Os componentes variam desde as várias bibliotecas incluídas no WSH (Windows Script Host) até aplicativos de ActiveX como o Internet Explorer que estão instalados na maioria dos sistemas.

New-Object usa Runtime Callable Wrappers do .NET Framework para criar objetos COM, portanto, ele tem as mesmas limitações que o .NET Framework ao chamar objetos COM. Para criar um objeto COM, você precisa especificar o parâmetro ComObject com o identificador programático ou ProgId da classe COM que você deseja usar. Uma discussão completa sobre as limitações de uso de COM e como determinar quais ProgIds estão disponíveis em um sistema está além do escopo deste guia do usuário, mas a maioria dos objetos bem conhecidos de ambientes como WSH podem ser usados no PowerShell.

Você pode criar objetos WSH especificando essas 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 a maioria das funcionalidades dessas classes seja disponibilizada de outras maneiras no Windows PowerShell, algumas tarefas, como a criação de atalhos, são ainda mais fáceis de executar usando as classes WSH.

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

Uma tarefa que pode ser executada rapidamente um objeto COM é a criação de um atalho. Suponha que você deseja criar um atalho na área de trabalho que a vincula a pasta base ao PowerShell. Você precisa primeiro 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 e, portanto, é possível explorar os membros do objeto digitando:

$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 InputObject opcional que você pode usar em vez de redirecionar para fornecer entrada para Get-Member. Você deverá obter a mesma saída mostrada acima se usar o comando Get-Member -InputObject $WshShell. Se você usar InputObject, ele tratará seu argumento 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:

$a = 1,2,"three"
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. Podemos pode digitar o caminho completo para a área de trabalho, mas há uma maneira mais fácil. A área de trabalho normalmente é representada por uma pasta chamada Área de Trabalho dentro da pasta base do usuário atual. O Windows PowerShell tem uma variável $HOME que contém o caminho para esta pasta. Podemos especificar o caminho para a pasta base usando essa variável e, em seguida, adicione o nome da pasta da Área de Trabalho e o nome do atalho a ser criado digitando:

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

Quando você usa algo parecido com um nome de variável entre aspas duplas, o PowerShell tenta substituir por um valor correspondente. Se você usar aspas simples, o PowerShell não tentará substituir o valor da variável. Por exemplo, tente digitar os seguintes comandos:

"$HOME\Desktop\PSHome.lnk"
C:\Documents and Settings\aka\Desktop\PSHome.lnk
'$HOME\Desktop\PSHome.lnk'
$HOME\Desktop\PSHome.lnk

Agora temos uma variável chamada $lnk que contém uma nova referência de atalho. Se quiser ver seus membros, você poderá direcioná-lo para Get-Member. A saída abaixo mostra os membros que precisamos usar para terminar de criar o atalho:

$lnk | Get-Member
TypeName: System.__ComObject#{f935dc23-1cf0-11d0-adb9-00c04fd58a0b}
Name             MemberType   Definition
----             ----------   ----------
...
Save             Method       void Save ()
...
TargetPath       Property     string TargetPath () {get} {set}

É necessário especificar o TargetPath, que é a pasta do aplicativo para o PowerShell e salvar o atalho chamando o método Save. O caminho da pasta de aplicativo do PowerShell é armazenado na variável $PSHome, então podemos fazer isso digitando:

$lnk.TargetPath = $PSHome
$lnk.Save()

Uso do Internet Explorer via PowerShell

Muitos aplicativos, incluindo a família de aplicativos Microsoft Office e o Internet Explorer, podem ser automatizados usando COM. Os exemplos a seguir ilustram algumas das técnicas e problemas típicos envolvidos no trabalho com aplicativos baseados em COM.

Você pode criar uma instância do Internet Explorer especificando a 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, verá que um processo chamado iexplore está em execução. Na verdade, se você sair do PowerShell, este processo continuará em execução. Você deve reinicializar o computador ou usar uma ferramenta como o Gerenciador de Tarefas para encerrar o processo iexplore.

Observação

Objetos COM que iniciam como processos separados, normalmente chamados de executáveis do 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 migra para a área de trabalho do Windows. Você deve tornar a janela visível para interagir com ela.

Digitando $ie | Get-Member, você pode exibir as propriedades e os métodos do Internet Explorer. Para ver a janela do Internet Explorer, defina a propriedade Visible para $true digitando:

$ie.Visible = $true

Você pode navegar até um endereço Web específico usando o método Navigate:

$ie.Navigate("https://devblogs.microsoft.com/scripting/")

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

$ie.Document.Body.InnerText

Para fechar o Internet Explorer de dentro do PowerShell, chame o método Quit():

$ie.Quit()

A variável $ie não contém uma referência válida, mesmo parecendo ser um objeto COM. Se você tentar usá-la, o PowerShell retornará um erro de automação:

$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 <<<<

É possível remover a referência restante com um comando como $ie = $null ou remover por completo a variável digitando:

Remove-Variable ie

Observação

não há um padrão comum para se executáveis do ActiveX fecham ou continuam em execução quando você remove uma referência deles. Dependendo das circunstâncias, tal como se o aplicativo estiver visível, se um documento editado está em execução e até mesmo se o PowerShell ainda está em execução, o aplicativo pode ser encerrado ou não. Por esse motivo, você deve testar o comportamento de encerramento para cada executável do ActiveX que você deseja usar no PowerShell.

Obtenção de avisos sobre objetos COM encapsulados por .NET Framework

Em alguns casos, um objeto COM pode ter um RCW (Runtime Callable Wrapper) do .NET Framework associado que é 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 para avisar sobre o acesso ao RCW. Se você especificar o parâmetro Strict e criar um objeto COM que usa um RCW, receberá uma mensagem de aviso:

$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 interop assembly. If
this type exposes different members than the IDispatch members , scripts written to work with this
object might not work if the primary interop assembly isn't installed. At line:1 char:17 + $xl =
New-Object <<<< -ComObject Excel.Application -Strict

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