Administração do Windows

Simplifique a administração da Diretiva de Grupo com o Windows PowerShell

Thorbjörn Sjövold

 

Visão geral:

  • O que é o Windows Powershell?
  • Como os GPOs eram gerenciados anteriormente
  • Migrando scripts para o Windows PowerShell

A tecnologia de Diretiva de Grupo da Microsoft não se difundiu da noite para o dia. Ela era um pouco difícil de entender e exigiu a adoção do Active Directory, um serviço novo e estranho que não se parecia em nada com os domínios de contas ou recursos que eram o padrão naquela época. Hoje em dia, a Diretiva de Grupo

é a espinha dorsal do gerenciamento de quase todas as organizações com uma infra-estrutura do Windows®. Tenho a impressão que é exatamente o que acontecerá com o Windows PowerShell™, a tecnologia de gerenciamento mais recente da Microsoft. Na verdade, o Windows PowerShell provavelmente facilitará ao máximo o seu trabalho como administrador de Diretiva de Grupo.

Neste artigo, mostrarei como as APIs do GPMC (Console de Gerenciamento de Diretiva de Grupo) da Microsoft®, escritas para linguagens WSH (Windows Script Host) como o VBScript (e linguagens de script baseadas em COM em geral), podem ser consumidas diretamente do Windows PowerShell para simplificar o gerenciamento da Diretiva de Grupo em seu ambiente.

Criando scripts de tarefas de Diretiva de Grupo

Quando a Microsoft lançou o GPMC alguns anos atrás, os administradores de Diretiva de Grupo passaram a contar, de repente, com vários recursos úteis à sua disposição. O snap-in MMC baseado na Diretiva de Grupo, em particular, representou um passo enorme rumo ao gerenciamento da Diretiva de Grupo, especialmente se comparado a Usuários e Computadores do Active Directory®. Além disso, havia uma API nova em folha que permitia que os administradores usassem linguagens baseadas em COM, como o VBScript, para executar a administração de tarefas de Diretiva de Grupo, como fazer backup e restauração de GPOs (objetos de diretiva de grupo), migrar GPOs entre domínios, definir configurações de segurança em GPOs e links e gerar relatórios.

Infelizmente, o GPMC não permitia editar as configurações reais dentro dos Objetos de Diretiva de Grupo. Em outras palavras, você podia executar operações no contêiner do GPO (como ler versões de GPO, ler datas de modificação, criar GPOs novos em folha, fazer backup e restauração/importação de GPOs de diferentes domínios, etc.), mas não podia adicionar ou alterar o conteúdo do GPO via programação (por exemplo, adicionando uma nova pasta redirecionada ou a instalação de um novo software). Em vez disso, o que geralmente você fazia era criar o GPO e definir todas as configurações manualmente usando o Editor de Objeto de Diretiva de Grupo. Em seguida, fazia backup do GPO e o importava em um ambiente de teste. Se tudo fosse verificado e estivesse funcionando corretamente, você o importava para o ambiente ao vivo. Apesar do recurso ausente, o uso de scripts em vez da interação manual com a API do GMPC resultou em uma economia enorme de tempo, esforços e erros na administração diária da Diretiva de Grupo.

O nível seguinte

Em que o Windows PowerShell se diferencia de linguagens de script como o VBScript? Para começar, o Windows PowerShell é um shell e, pelo menos para o nosso objetivo, é como se fosse um interpretador de linhas de comando. Embora o VBScript possa ser executado a partir da linha de comando, um arquivo VBScript não pode ser executado linha por linha. Um script do Windows PowerShell, por outro lado, pode ser criado dinamicamente como uma série de comandos individuais. Além disso, o Windows PowerShell possui funções muito parecidas com sub-rotinas no VBScript e que podem ser criadas em tempo real no prompt de comando do Windows PowerShell.

Melhor ainda, o Windows PowerShell foi desenvolvido com base no Microsoft .NET Framework, enquanto o VBScript se baseia em tecnologia COM mais antiga. Isso significa que a vasta quantidade de código .NET que está sendo produzida hoje em dia pode ser usada diretamente do Windows PowerShell.

Podemos concluir que, com o Windows PowerShell, você terá modo interativo e suporte completo a script, tudo em um único pacote. Todos os exemplos que eu fornecer aqui serão entradas de linha de comando, por isso você pode digitar à medida que lê. Entretanto, eles funcionarão igualmente bem se você os colocar em um arquivo de script do Windows PowerShell e executá-lo.

Recriar scripts antigos usando o Windows PowerShell

A última coisa que você quer quando começa a trabalhar com uma nova tecnologia é ser forçado a abandonar todo o seu trabalho anterior. Existem três abordagens que podem ser usadas para acessar objetos COM a partir da API do GPMC ou, basicamente, para reutilizar qualquer VBScript antigo fora daqui. Você pode selecionar uma destas três opções:

  • Criar um cmdlet do Windows PowerShell usando uma linguagem de programação como C# ou C++ gerenciado.
  • Usar o Windows PowerShell para acessar o ScriptControl em MSScript.ocx a fim de encapsular scripts antigos.
  • Encapsular as chamadas COM em funções reutilizáveis do Windows PowerShell ou chamar os objetos COM diretamente.

Vou me concentrar principalmente na terceira opção, mas antes vamos dar uma olhada em todas as opções.

Criando um cmdlet do Windows PowerShell

A Microsoft incluiu um grande número de cmdlets no Windows PowerShell que permitem copiar arquivos, formatar saídas, recuperar data/hora, etc., mas você pode criar seus próprios cmdlets também. O processo está totalmente documentado em msdn2.microsoft.com/ms714598.aspx . Para resumir, aqui estão as etapas:

  • Crie uma DLL de biblioteca de classes em uma linguagem de programação .NET como C#.
  • Crie uma nova classe e herde do cmdlet da classe base.
  • Defina atributos que determinem o nome, o uso, os parâmetros de entrada, etc. e adicione seu código.

Como o Windows PowerShell foi desenvolvido com base no .NET Framework, quaisquer tipos (como uma seqüência de caracteres, um objeto, etc.) que estejam sendo retornados ou passados como parâmetros são exatamente iguais no código e no Windows PowerShell. Não é necessária nenhuma conversão de tipo especial.

A vantagem dessa solução é que você tem uma linguagem de programação completa à sua disposição.

Encapsulando scripts antigos usando o objeto ScriptControl em MSScript.ocx

Obviamente, você precisa do mecanismo VBScript para executar um arquivo VBScript. O que não é tão óbvio assim é que esse mecanismo é um objeto COM. Já que é possível usar objetos COM a partir do Windows PowerShell, você pode invocar o mecanismo VBScript. Eis um exemplo:

$scriptControl = New-Object -ComObject ScriptControl
$scriptControl.Language = ‘VBScript’
$scriptControl.AddCode(
    ‘Function ShowMessage(messageToDisplay)
    MsgBox messageToDisplay
    End Function’)
$scriptControl.ExecuteStatement(‘ShowMessage
    “Hello World”’)

Se você inserir esse código na CLI (interface de linha de comando) do Windows PowerShell, a função ShowMessage do VBScript será chamada e executada com um parâmetro, resultando na exibição de uma Caixa de Mensagem com o texto “Olá, mundo”.

Alguns de vocês podem pensar: "Legal! Já dominei a arte de usar COM a partir do Windows PowerShell! Posso parar de ler este artigo e começar a preencher o objeto ScriptControl com a minha coleção de scripts antigos do GPMC". Infelizmente, não é esse o caso. Assim que os scripts ficam maiores, essa técnica rapidamente se torna muito complexa e difícil de depurar.

Encapsulando objetos COM

Portanto, a melhor opção é a terceira: encapsular as chamadas COM em funções reutilizáveis do Windows PowerShell, o que lhe permite consumir os objetos COM na API do GPMC. A linha abaixo mostra como criar um objeto .NET diretamente no Windows PowerShell. Nesse caso, trata-se de um objeto FileInfo que pode ser usado para obter o tamanho do arquivo:

$netObject = New-Object System.IO.FileInfo(
“C:\boot.ini”) # Create an instance of FileInfo 
               # representing c:\boot.ini

Observe que # é usado no Windows PowerShell para comentários embutidos. Usando esse objeto FileInfo recém-instanciado, você pode obter o tamanho de boot.ini simplesmente digitando este código:

$netObject.Length # Display the size in bytes of the
                  # file in the command line interface

Espere aí, não deveríamos falar sobre objetos COM e conversão VBScript? Sim, mas veja o seguinte comando:

$comFileSystemObject = New-Object –ComObject Scripting.FileSystemObject

Você observará que a sintaxe é basicamente a mesma que usei anteriormente para criar objetos nativos do .NET Framework, exceto por duas diferenças. Primeira: eu adicionei a opção –ComObject que direciona o Windows PowerShell para o mundo COM em vez do mundo .NET. Segunda: eu usei um ProgID COM em vez de um construtor .NET (nesse caso, Scripting.FileSystemObject). O ProgID é o mesmo nome que você sempre usou. Em VBScript, o equivalente seria:

Set comFileSystemObject = CreateObject(
    “Scripting.FileSystemObject”)

Para obter o tamanho do arquivo usando VBScript, adicione a linha acima a um arquivo, junto com este código:

Set comFileObject = comFileSystemObject.GetFile(
    “C:\Boot.ini”)
WScript.Echo comFileObject.Size

Em seguida, execute-o usando Cscript.exe, por exemplo. No Windows PowerShell, você faria isso desta forma (diretamente da linha de comando do Windows PowerShell, se preferir):

$comFileObject = $comFileSystemObject.GetFile(
    “C:\boot.ini”)
$comFileObject.Size

Obviamente, para converter um VBScript que lê o tamanho de um arquivo, eu poderia ter usado o cmdlet do Windows PowerShell que gerencia objetos em unidades, mas eu quis mostrar como é fácil acessar COM a partir do Windows PowerShell. Observe que, embora eu peça ao Windows PowerShell para criar um objeto COM, o objeto que realmente é criado ($comFileSystemObject aqui) é um objeto .NET que encapsula o objeto COM e expõe sua interface. No escopo deste artigo, porém, isso não tem muita importância.

Windows PowerShell em ação

Agora que você viu como acessar COM a partir do Windows PowerShell, vamos nos concentrar na Diretiva de Grupo. Os exemplos aqui mostrarão trechos de código curtos para lhe dar uma idéia de como usar as APIs do GPMC a partir do Windows PowerShell, mas você encontrará um conjunto completo de funções do Windows PowerShell para gerenciar Diretiva de Grupo no download de código relacionado a este artigo, que está disponível online em technetmagazine.com/code07.aspx. A Figura 1 lista as funções incluídas no download.

Figure 1 Funções personalizadas no download

Nome da função Descrição
BackupAllGpos Faz backup de todos os GPOs em um domínio
BackupGpo Faz backup de um único GPO
RestoreAllGpos Restaura todos os GPOs de um backup para um domínio
RestoreGpo Restaura um único GPO de um backup
GetAllBackedUpGpos Recupera a versão mais recente do backup dos GPOs de um determinado caminho
CopyGpo Copia as configurações de um GPO para outro
CreateGpo Cria um novo GPO vazio.
DeleteGpo Exclui um GPO.
FindDisabledGpos Retorna todos os GPOs em que tanto o usuário como a parte do computador estejam desabilitados
FindUnlinkedGpos Retorna todos os GPOs que não têm links
CreateReportForGpo Cria um relatório XML para um único GPO em um domínio
CreateReportForAllGpos Cria um relatório XML separado para cada GPO em um domínio
GetGpoByNameOrID Localiza um GPO pelo seu nome de exibição ou identificação
GetBackupByNameOrId Localiza o backup de um GPO pelo seu nome de exibição ou identificação
GetAllGposInDomain Retorna todos os GPOs em um domínio

No decorrer da leitura desta seção, fique à vontade para iniciar a linha de comando do Windows PowerShell e digitar nos comandos. No entanto, lembre-se que alguns deles dependem de comandos anteriores. Em outras palavras, alguns dos objetos criados inicialmente serão usados mais tarde, por isso permaneça na mesma sessão do Windows PowerShell. Se você fechar a sessão, terá de começar novamente desde o início, redigitando todos os comandos.

Sendo assim, vamos criar um novo GPO usando o Windows PowerShell. A equipe de Diretiva de Grupo na Microsoft incluiu vários exemplos de VBScript totalmente funcionais com GPMC que você pode aproveitar para agilizar o processo. Eles estão no diretório %ProgramFiles%\GPMC\Scripts, onde você também encontrará um arquivo chamado gpmc.chm que contém a documentação da API do GPMC. Vamos dar uma olhada no script CreateGPO.wsf e dissecá-lo para ver o que o faz funcionar.

Próximo à parte superior, você verá esta linha:

Dim GPM
Set GPM = CreateObject(“GPMgmt.GPM”)

Esse é basicamente o ponto de partida de qualquer script ou sessão de gerenciamento de Diretiva de Grupo porque instancia a classe GPMgmt.GPM que permite o acesso à maior parte da funcionalidade do GPMC. Vamos fazer isso a partir do Windows PowerShell:

$gpm = New-Object -ComObject GPMgmt.GPM

Agora que você tem o ponto de partida para o gerenciamento de Diretiva de Grupo, a próxima etapa é descobrir o que você pode fazer com ele. Normalmente, você se voltaria para a documentação desse tipo de informação, mas o Windows PowerShell tem um recurso muito legal. Se você digitar a linha a seguir, verá a saída mostrada na Figura 2:

Figura 2 Saída de Get-Member

Figura 2** Saída de Get-Member **(Clique na imagem para aumentar a exibição)

$gpm | gm

Muito legal, na minha opinião. Observe como o cmdlet Get-Member (ou gm) permite que você veja as propriedades e os métodos aos quais o objeto oferece suporte diretamente da linha de comando. É claro que não é o mesmo que ler a documentação, mas facilita o uso de objetos familiares quando você não se lembra do número exato de parâmetros, do nome exato, etc. Um ponto importante a ser observado é que, quando você olha para as listagens de nó da documentação do GPMC, parece que o objeto GPM e todas as outras classes têm a letra I como prefixo. Isso se deve a funcionamentos internos do COM e não nos interessa aqui. Destina-se a programadores de C++ que escrevem código COM nativo e denota a diferença entre uma interface e a classe que a implementa. Observe também que, ao usar as APIs do GPMC, só há um objeto que precisa ser criado dessa forma, que é o GPMgmt.GPM. Todos os outros são criados com o uso de métodos que começam com esse objeto GPM.

Vamos continuar agora com a criação de um novo GPO.

A Figura 3 ilustra como é simples criar um GPO. Observe que eu deixei de fora um pouco do código, como o tratamento de erros (por exemplo, o que acontecerá se você não tiver permissão para criar GPOs), e codifiquei um nome de domínio, mas dá para você entender.

Agora que você sabe como criar um GPO, vamos abrir um já existente. Você ainda tem a referência ao domínio, $gpmDomain, por isso digite o seguinte:

$gpmExistingGpo = $gpmDomain.GetGPO(
  “{31B2F340-016D-11D2-945F-00C04FB984F9}”) 
# Open an existing GPO based on its GUID, 
# in this case the Default Domain Policy.
$gpmExistingGpo.DisplayName 
# Show the display name of the GPO, it 
# should say Default Domain Policy
$gpmExistingGpo.GenerateReportToFile($gpmConstants.ReportHTML, “.\DefaultDomainPolicyReport.html”

Isso lhe dá um relatório HTML completo das configurações na Diretiva de Domínio Padrão, mas, obviamente, você pode usar qualquer um dos métodos e propriedades (como ModificationTime, que informa quando o GPO foi modificado pela última vez) para descobrir quando alguma das configurações no GPO foi alterada.

Isso é extremamente útil. É muito provável que você já tenha estado em uma situação em que os telefones não paravam de tocar com usuários reclamando que seus computadores estão funcionando de forma estranha. Você suspeita que isso esteja relacionado a uma configuração de GPO alterada, adicionada ou excluída, mas não tem nem idéia de em qual GPO procurar. A salvação é o Windows PowerShell! Se você inserir o script mostrado na Figura 4 na linha de comando do Windows PowerShell, verá todos os GPOs que foram alterados nas últimas 24 horas.

Figure 4 Descobrindo GPOs modificados

$gpmSearchCriteria = $gpm.CreateSearchCriteria() 
# We want all GPOs so no search criteria will be specified
$gpmAllGpos = $gpmDomain.SearchGPOs($gpmSearchCriteria) 
# Find all GPOs in the domain
foreach ($gpmGpo in $gpmAllGpos)
{
if ($gpmGpo.ModificationTime -ge (get-date).AddDays(-1)) {$gpmGpo.DisplayName}
# Check if the GPO has been modified less than 24 hours from now 
}

Observe o operador –ge, que significa maior ou igual a. Pode parecer estranho se você estiver acostumado aos operadores < and > em outras linguagens de programação ou de script. Mas esses operadores são usados para redirecionamento (por exemplo, para redirecionar a saída para o arquivo) e, portanto, não podem ser usados como operadores de comparação no Windows PowerShell.

Encerramento

O código na Figura 5 lista o script completo para copiar as configurações de um GPO para outro. Agora você deve ter entendido como pode usar essa nova tecnologia com a Diretiva de Grupo e como pode reutilizar qualquer objeto COM ou código VBScript que consuma um objeto COM.

Figure 5 Copie as configurações de um GPO para outro

###########################################################################
# Function  : CopyGpo
# Description: Copies the settings in a GPO to another GPO
# Parameters : $sourceGpo     - The GPO name or GPO ID of the GPO to copy
#           : $sourceDomain   - The dns name, such as microsoft.com, of the domain where the original GPO is located
#           : $targetGpo      - The GPO name of the GPO to add
#           : $targetDomain   - The dns name, such as microsoft.com, of the domain where the copy should be put
#           : $migrationTable - The path to an optional Migration table to use when copying the GPO
# Returns   : N/A
# Dependencies: Uses GetGpoByNameOrID, found in article download
###########################################################################
function CopyGpo(
 [string] $sourceGpo=$(throw ‘$sourceGpo is required’),
 [string] $sourceDomain=$(throw ‘$sourceDomain is required’),
 [string] $targetGpo=$(throw ‘$targetGpo is required’),
 [string] $targetDomain=$(throw ‘$targetDomain is required’),
 [string] $migrationTable=$(“”),
 [switch] $copyAcl)
{
 
 $gpm = New-Object -ComObject GPMgmt.GPM # Create the GPMC Main object
 $gpmConstants = $gpm.GetConstants() # Load the GPMC constants
 $gpmSourceDomain = $gpm.GetDomain($sourceDomain, “”, $gpmConstants.UseAnyDC) # Connect to the domain passed 
                                                                              # using any DC
 $gpmSourceGpo = GetGpoByNameOrID $sourceGpo $gpmSourceDomain
 # Handle situations where no or multiple GPOs was found
 switch ($gpmSourceGpo.Count)
 {
   {$_ -eq 0} {throw ‘No GPO named $gpoName found’; return}
   {$_ -gt 1} {throw ‘More than one GPO named $gpoName found’; return} 
 }
 if ($migrationTable)
 {
   $gpmMigrationTable = $gpm.GetMigrationTable($migrationTable)
 }

 $gpmTargetDomain = $gpm.GetDomain($targetDomain, “”, $gpmConstants.UseAnyDC) # Connect to the domain passed 
                                                                              # using any DC

 $copyFlags = 0
 if ($copyAcl)
 {
   $copyFlags = Constants.ProcessSecurity
 }
 $gpmResult = $gpmSourceGpo.CopyTo($copyFlags, $gpmTargetDomain, $targetGpo)
 [void] $gpmResult.OverallStatus
 
}

O Windows PowerShell será, assim como a Diretiva de Grupo, uma parte natural de qualquer ambiente de gerenciamento do Windows. Mas há milhões de linhas de VBScript lá fora que terão de ser migradas ou mantidas. Felizmente, este tutorial o ajudará nessa tarefa.

No site da TechNet, existem várias fontes que você pode usar para aprimorar a administração da Diretiva de Grupo e outras áreas onde você usou anteriormente o VBScript (como as funções do Windows PowerShell no download), além de um excelente guia de conversão de VBScript para Windows PowerShell que fornece dicas sobre como realizar tarefas comuns no Windows PowerShell quando você sabe o equivalente no VBScript. Você o encontrará em microsoft.com/technet/scriptcenter/topics/winpsh/convert.

Além disso, a API do GPMC está totalmente documentada. Você pode baixar as informações do site de Diretiva de Grupo em microsoft.com/grouppolicy.

Por último, mas não menos importante: se você ainda não instalou o Windows PowerShell, o que está esperando? Baixe-o do site microsoft.com/powershell e divirta-se!

Thorbjörn Sjövold é CTO e fundador da Special Operations Software (www.specopssoft.com), um provedor de produtos de extensão de Segurança e Gerenciamento de Sistemas baseados em Diretiva de Grupo. Entre em contato com ele pelo email thorbjorn.sjovold@specopssoft.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Todos os direitos reservados. A reprodução parcial ou completa sem autorização é proibida..