Crie GUIs WPF com PowerShell: Funções, Entradas e Resultados

PowerShell é uma ferramenta de linha de comando, mas você sabia que também pode ser usada como base para interfaces gráficas? Às vezes, a linha de comando não é o melhor tipo de interface para uma determinada situação. Criar uma GUI do PowerShell para o seu service desk é um ótimo exemplo. Este é um daqueles momentos em que é mais apropriado construir ferramentas gráficas.

Not a reader? Watch this related video.

Reforce a verificação do usuário final ao redefinir senhas na central de ajuda. Reduza sua vulnerabilidade à engenharia social com o Specops Secure Service Desk. Entre em contato conosco para uma demonstração!

O PowerShell pode usar e expor funcionalidades e recursos do .NET. Como resultado, é possível criar interfaces gráficas para os scripts que você cria. Construir GUIs do PowerShell pode parecer complicado, especialmente se você é um iniciante.

Mas se você tem experiência básica com scripts do PowerShell, não há motivo para não aprender e adaptar a prática de criar GUIs para seus scripts.

Neste post, você aprenderá como criar um GUI do PowerShell usando o Windows Presentation Framework (WPF).

Pré-requisitos

Antes de começar, certifique-se de atender aos seguintes requisitos:

  1. Visual Studio 2017 ou posterior – Você usará isso para criar a interface gráfica usando o WPF. Você pode baixar uma versão gratuita/comunitária.
  2. A script editor – I use Visual Studio Code, but you can also use another text editor of your choice. Some other options are Notepad++ and the built-in PowerShell ISE
  3. A Windows 10 computer with Windows PowerShell 5.1.

Construindo o Script

Neste post, você criará um script simples chamado Main.ps1. No script, você escreverá código que buscará informações do disco de um sistema local ou remoto consultando a classe WMI Win32_LogicalDisk.

Você precisará de um script para envolver primeiro uma GUI. Eu escolhi usar um script que permite fornecer um nome de computador e consultar informações do disco. Isso, de forma alguma, é necessário para construir uma GUI, no entanto. Use as técnicas que você aprende neste post para adaptar suas GUIs aos seus próprios scripts.

Como exemplo de script, criarei uma função que realiza as seguintes ações:

  1. Aceita entrada para o nome do computador a ser consultado
  2. Consulta o computador e armazena as informações dos discos fixos em uma variável
  3. Retorna os resultados

Escrevendo a Função

Abaixo está a função que você usará para este projeto, adequadamente chamada de Get-FixedDisk. O objetivo deste projeto é obter informações sobre os discos não removíveis ou discos fixos na máquina alvo.

Embora este trecho de código possa ser usado como está, criar uma GUI seria benéfico se você quiser realizar uma consulta rápida sem ter que usar a função e digitar manualmente os comandos cada vez.

Function Get-FixedDisk {
    [CmdletBinding()]
    # Este bloco param() indica o início da declaração de parâmetros
    param (
        <# 
            Este parâmetro aceita o nome do computador de destino.
            Também é definido como obrigatório para que a função não execute sem especificar o valor.
        #>
        [Parameter(Mandatory)]
        [string]$Computer
    )
    <#
        Comando de consulta WMI que obtém a lista de todos os discos lógicos e salva os resultados em uma variável chamada $DiskInfo
    #>
    $DiskInfo = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter 'DriveType=3'
   $DiskInfo
}

Você pode ver que eu adicionei um bloco param() no código. Isso é para instruir a função a aceitar entradas com base no tipo de dados indicado.

No exemplo, eu adicionei um parâmetro Computer que aceita um valor de string. Além disso, ao adicionar o atributo de parâmetro Mandatory, garante que a função não seja executada se o parâmetro Computer não for especificado durante a execução.

Em seguida, linha 18 mostra o comando de consulta WMI real que obtém a lista de todos os discos lógicos e salva os resultados em uma variável chamada $DiskInfo. Também adicionei um filtro para obter apenas os discos com DriveType=3. Este filtro garante que apenas as informações sobre discos fixos locais sejam exibidas.

Importando o Código (Sourcing de Pontos)

Neste momento, você já tem um script funcional e está pronto para testá-lo. Mas antes de poder testar o script, você precisa importar o código em uma sessão do PowerShell. Uma maneira de carregar o código em uma sessão do PowerShell é através da importação de ponto.

Para importar um script, digite um ponto (.) e um espaço antes do caminho do script. Se o script estiver na pasta C:\PoshGUI-sample, você pode importá-lo como abaixo.

PS C:\PoshGUI-sample> . .\Main.ps1

Você também pode especificar o caminho completo se não estiver no diretório de trabalho atual. No código de exemplo abaixo, você pode ver o caminho completo do script.

PS C:>. C:\PoshGUI-sample\Main.ps1

Agora que importamos o código na memória, podemos prosseguir com o teste da função que criamos. No exemplo abaixo, mostra que a função Get-FixedDisk é usada para consultar o computador poshLabExc.

PS51> Get-FixedDisk -Computer poshLabExc

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 53037772800
Size         : 135838822400
VolumeName   : Windows

DeviceID     : D:
DriveType    : 3
ProviderName :
FreeSpace    : 14872641536
Size         : 17178750976
VolumeName   : Temporary Storage

DeviceID     : E:
DriveType    : 3
ProviderName :
FreeSpace    : 488202240
Size         : 524283904
VolumeName   : System Reserved

Construindo a GUI do PowerShell

Neste ponto, você criou o arquivo de script chamado Main.ps1, e dentro do script criou a função Get-FixedDisk. Você também foi capaz de testar e confirmar que a função está funcionando.

Agora que você sabe que o script funciona, você pode começar a construir a GUI.

Projetando o Formulário da GUI do PowerShell

Primeiro, planeje como você gostaria que a GUI parecesse e os elementos que gostaria de usar. Para este exemplo simples, nossa GUI terá:

  • a text box where the computer name can be entered
  • a button to execute the function
  • a text box where we can display the results

Em seguida, você pode começar a construí-la!

Para começar a criar a GUI, abra o Visual Studio e crie um novo projeto.

Uma vez que o Visual Studio está aberto, clique em Arquivo (1) –> Novo (2) –> Projeto (3).

Creating a new Visual Studio project

Na janela Novo Projeto, escolha Visual C# (1), selecione Aplicativo WPF (.NET Framework) (2), altere o nome para PoshGUI-sample (3) e clique em OK.

Choosing a Visual Studio project

Após a criação do projeto, será apresentado um formulário em branco com o nome de MainWindow.xaml.

Visual Studio MainWindow.xaml

Agora é preciso formatar este formulário para atender aos nossos requisitos. Abaixo estão os controles e o formato que você precisará adicionar.

  • Janela
    • Título: Informações do Disco
    • Altura: 326
    • Largura: 403
  • Controles (4)
    • Rótulo
      • Conteúdo: “Nome do Computador:”
      • Margem: 10, 10, 0, 0
    • Caixa de Texto
      • Nome: txtComputer
      • Texto: “”
      • Altura: 23
      • Largura: 174
    • Botão
      • Nome: btnQuery
      • Conteúdo: Consultar
      • Margem: 0, 13, 12, 0
    • Caixa de Texto
      • Nome: txtResults
      • Texto: “”
      • Somente Leitura: True
      • Margem: 10, 60, 0, 0
      • Altura: 225
      • Largura: 373

A aparência final do formulário deve ser semelhante ao que é mostrado na imagem abaixo. Você pode rearranjar o layout da sua janela de maneira diferente. Seja criativo!

PowerShell GUI Template

Combinando o Script e a Interface Gráfica do PowerShell

Depois de ficar satisfeito com o design, você pode começar a integrá-lo ao script.

O PowerShell não pode exibir formulários nativamente. Para poder exibir o formulário, precisamos adicionar uma linha de código no início do nosso script para dar suporte à renderização do Formulário WPF.

Add-Type -AssemblyName PresentationFramework

Em seguida, adicione código para realizar as seguintes ações:

  1. Importar e ler o código XAML do formulário.
  2. Criar dinamicamente variáveis atribuídas a cada controle nomeado
  3. Exibir o formulário

Abaixo está o código atualizado dentro do seu script.

Nota: Certifique-se de modificar a linha $xamlFile e apontá-la para o caminho completo do seu arquivo MainWindow.xaml.

Add-Type -AssemblyName PresentationFramework

Function Get-FixedDisk {
    [CmdletBinding()]
    # Este bloco param() indica o início da declaração de parâmetros
    param (
        <# 
            Este parâmetro aceita o nome do computador de destino.
            Também é configurado como obrigatório para que a função não execute sem especificar o valor.
        #>
        [Parameter(Mandatory)]
        [string]$Computer
    )
    <#
        Comando de consulta WMI que obtém a lista de todos os discos lógicos e salva os resultados em uma variável chamada $DiskInfo
    #>
    $DiskInfo = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter 'DriveType=3'
    $DiskInfo
}

# onde está o arquivo XAML?
$xamlFile = "C:\PoshGUI-sample\MainWindow.xaml"

#criar janela
$inputXML = Get-Content $xamlFile -Raw
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
[XML]$XAML = $inputXML

#Ler XAML
$reader = (New-Object System.Xml.XmlNodeReader $xaml)
try {
    $window = [Windows.Markup.XamlReader]::Load( $reader )
} catch {
    Write-Warning $_.Exception
    throw
}

# Criar variáveis baseadas nos nomes dos controles do formulário.
# A variável será nomeada como 'var_<nome do controle>'

$xaml.SelectNodes("//*[@Name]") | ForEach-Object {
    # "tentando item $($_.Name)"
    try {
        Set-Variable -Name "var_$($_.Name)" -Value $window.FindName($_.Name) -ErrorAction Stop
    } catch {
        throw
    }
}
Get-Variable var_*

$Null = $window.ShowDialog()

Nota: $Null = $window.ShowDialog() deve ser sempre a última linha de código dentro do seu script.

Quando você executar este código ao executar o script Main.ps1, você deve ver o exemplo de saída abaixo.

PowerShell GUI variable and field mappings

Como você pode ver, os três controles nomeados foram atribuídos às suas variáveis. Esses nomes de variáveis serão referenciados mais tarde no script quando adicionarmos o código de lógica de controle.

  • var_btnQuery
  • var_btnComputer
  • var_txtResults

Leve em consideração que o script neste ponto só pode exibir o formulário, mas os controles são inúteis pois você ainda não adicionou o código.

Adicionando o Código do Evento de Clique do Botão

Agora que você modificou com sucesso o script para importar e exibir a GUI, comece a adicionar o código aos controles para recuperar e exibir os dados de informações do disco.

Neste projeto, apenas o botão btnQuery terá uma ação atribuída. Os outros controles servirão apenas como controles de entrada e saída/exibição. Isso significa que só precisamos adicionar um código de evento de clique ao btnQuery.

Para adicionar a ação de clique ao btnQuery, atribua o código abaixo ao seu nome de variável correspondente $var_btnQuery. Copie o código abaixo e insira-o entre as referências de código Get-Variable var_* e $Null = $window.ShowDialog() no script.

$var_btnQuery.Add_Click( {
   #limpar a caixa de resultados
   $var_txtResults.Text = ""
       if ($result = Get-FixedDisk -Computer $var_txtComputer.Text) {
           foreach ($item in $result) {
               $var_txtResults.Text = $var_txtResults.Text + "DeviceID: $($item.DeviceID)`n"
               $var_txtResults.Text = $var_txtResults.Text + "VolumeName: $($item.VolumeName)`n"
               $var_txtResults.Text = $var_txtResults.Text + "FreeSpace: $($item.FreeSpace)`n"
               $var_txtResults.Text = $var_txtResults.Text + "Size: $($item.Size)`n`n"
           }
       }       
   })

$var_txtComputer.Text = $env:COMPUTERNAME

Testando a GUI do PowerShell Finalizada

Com todas as partes cobertas, abaixo está o código concluído para nosso script que incorpora a função e a GUI do PowerShell que projetamos.

Add-Type -AssemblyName PresentationFramework

Function Get-FixedDisk {
    [CmdletBinding()]
    # Este bloco param() indica o início da declaração de parâmetros
    param (
        <# 
            Este parâmetro aceita o nome do computador de destino.
            Também é definido como obrigatório para que a função não seja executada sem especificar o valor.
        #>
        [Parameter(Mandatory)]
        [string]$Computer
    )
    <#
        Comando de consulta WMI que obtém a lista de todos os discos lógicos e salva os resultados em uma variável chamada $DiskInfo
    #>
    $DiskInfo = Get-WmiObject Win32_LogicalDisk -ComputerName $Computer -Filter 'DriveType=3'
   $DiskInfo
}

#onde está o arquivo XAML?
$xamlFile = "C:\Users\june\source\repos\PoshGUI-sample\PoshGUI-sample\MainWindow.xaml"

#criar janela
$inputXML = Get-Content $xamlFile -Raw
$inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window'
[xml]$XAML = $inputXML
#Ler XAML

$reader = (New-Object System.Xml.XmlNodeReader $xaml)
try {
    $window = [Windows.Markup.XamlReader]::Load( $reader )
}
catch {
    Write-Warning $_.Exception
    throw
}

#Criar variáveis baseadas nos nomes dos controles do formulário.
#A variável será nomeada como 'var_<nome do controle>'

$xaml.SelectNodes("//*[@Name]") | ForEach-Object {
    #"tentando item $($_.Name)";
    try {
        Set-Variable -Name "var_$($_.Name)" -Value $window.FindName($_.Name) -ErrorAction Stop
    } catch {
        throw
   }
}

Get-Variable var_*

$var_btnQuery.Add_Click( {
   #limpar a caixa de resultados
   $var_txtResults.Text = ""
       if ($result = Get-FixedDisk -Computer $var_txtComputer.Text) {
           foreach ($item in $result) {
               $var_txtResults.Text = $var_txtResults.Text + "DeviceID: $($item.DeviceID)`n"
               $var_txtResults.Text = $var_txtResults.Text + "VolumeName: $($item.VolumeName)`n"
               $var_txtResults.Text = $var_txtResults.Text + "FreeSpace: $($item.FreeSpace)`n"
               $var_txtResults.Text = $var_txtResults.Text + "Size: $($item.Size)`n`n"
           }
       }       
   })

$var_txtComputer.Text = $env:COMPUTERNAME
$Null = $window.ShowDialog()

Como você pode ver abaixo, após chamar o script no PowerShell, as janelas de GUI do PowerShell apareceram. Em seguida, você pode inserir um nome de computador válido para testar a funcionalidade.

PowerShell GUI Example Result

Verifique os chamadores com segurança com métodos de autenticação que removem a oportunidade de personificação do usuário. Bloqueie hackers de helpdesk com o Specops Secure Service Desk. Experimente grátis!

Resumo

Neste artigo, você aprendeu como criar uma função simples que aceita entrada e retorna resultados. Você também aprendeu como criar uma GUI básica do PowerShell WPF, bem como como importá-la para atuar como uma interface para o script do PowerShell que você criou.

Este é apenas uma combinação básica de script e GUI. Inúmeras melhorias podem ser feitas, tais como:

  • Formatar o tamanho e o espaço livre para exibir como valores de GB.
  • Alterar o nome da propriedade exibida.
  • Usar GridView em vez de TextBox para mostrar os resultados.
  • Adicionar um botão de importação para percorrer uma lista de servidores de um arquivo CSV.

Cabe a você modificar e adicionar funcionalidades com base em seus requisitos.

Leitura Adicional

Source:
https://adamtheautomator.com/powershell-gui/