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

O 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 instância específica. Construir uma GUI do PowerShell para o seu serviço de help desk é um ótimo exemplo. Este é um daqueles momentos em que é mais apropriado construir ferramentas gráficas em vez disso.

Not a reader? Watch this related video.

Aplicar verificação de usuário final ao redefinir senhas no help desk. 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 escrever interfaces gráficas para os scripts que você cria. Construir interfaces gráficas 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á razão para você não aprender e adaptar a prática de criar interfaces gráficas para seus scripts.

Neste post, você aprenderá como criar uma 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 do usuário 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 uma GUI primeiro. 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. Use as técnicas que aprender neste post para adaptar suas GUIs aos seus próprios scripts.

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

  1. Aceitar entrada para o nome do computador a ser consultado
  2. Consultar o computador e armazenar as informações dos discos fixos em uma variável
  3. Retornar os resultados

Escrevendo a Função

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

Embora este trecho de código possa ser usado como está, criar uma GUI seria benéfico se você apenas quiser realizar uma consulta rápida sem precisar carregar 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 é configurado 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
}

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

No exemplo, 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 será executada se o parâmetro Computer não for especificado durante a execução.

Em seguida, linha 18 mostra o comando real de consulta WMI 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. Esse filtro garante que apenas as informações sobre discos fixos locais sejam exibidas.

Importando o Código (Dot Sourcing)

Neste ponto, você agora 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 código em uma sessão do PowerShell é por meio de fonte de ponto.

Para fonte de ponto um script, digite um ponto (.) e um espaço antes do caminho do script. Se o script estiver na pasta C:\PoshGUI-sample, você poderia fonte de ponto como abaixo.

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

Você também pode especificar o caminho completo se você 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 para a 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 nomeado 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 GUI do PowerShell

Primeiro, planeje como você gostaria que a GUI se 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í-lo!

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

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

Creating a new Visual Studio project

Sob a 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, um formulário em branco será apresentado com o nome de MainWindow.xaml.

Visual Studio MainWindow.xaml

Agora você precisa formatar este formulário de acordo com nossos requisitos. Abaixo estão os controles e a formatação 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: “”
      • SomenteLeitura: 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 forma diferente. Seja criativo!

PowerShell GUI Template

Combinando o Script e a GUI do PowerShell

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

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

Add-Type -AssemblyName PresentationFramework

Em seguida, adicione código para executar 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 é 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:\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 com base 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 sempre ser a última linha de código dentro do seu script.

Ao executar este código ao executar o Main.ps1 script, você deverá ver a saída de exemplo 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 posteriormente no script quando adicionarmos o código lógico do controle.

  • var_btnQuery
  • var_btnComputer
  • var_txtResults

Tenha em mente que, neste ponto, o script só pode exibir o formulário, mas os controles são inúteis, já que 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 receberá 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 resultado
   $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 completo 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 com base nos nomes dos controles do formulário.
#A variável será nomeada como 'var_<nome do controle>'

$xaml.SelectNodes("//*[@Name]") | ForEach-Object {
    #"tentando o 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 resultado
   $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 GUI do PowerShell apareceram. Em seguida, você pode inserir um nome de computador válido para testar a funcionalidade.

PowerShell GUI Example Result

Verifique com segurança os chamadores com métodos de autenticação que eliminam a oportunidade de falsificação de 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 interface gráfica básica do PowerShell (WPF) e como importá-la para atuar como uma interface para o script do PowerShell que você criou.

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

  • Formatar o tamanho e o espaço livre para exibir em 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/