All documentation

Creating a Dynamic PowerShell GUI for Viewing and Filtering Data

Published June 17, 2024 Guide

Introduction

PowerShell, a task automation and configuration management framework from Microsoft, is highly valued for its powerful scripting capabilities. However, it is typically used in a command-line interface, which might not be ideal for all users. To enhance usability and create more user-friendly scripts, you can add graphical user interfaces (GUIs) to PowerShell scripts. This article guides you through creating a dynamic PowerShell GUI for viewing and filtering data using Windows Forms.

Prerequisites

  • PowerShell 5.1 or later: Ensure you have an appropriate version of PowerShell installed.
  • .NET Framework: Required for Windows Forms.

Steps to Create a Dynamic PowerShell GUI

1. Setting Up the Environment

First, you need to load the necessary .NET assemblies for Windows Forms:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

2. Defining the GUI Function

Create a function that accepts any enumerable collection of objects and displays them in a DataGridView:

function Show-DataInGrid {
    param (
        [Parameter(Mandatory = $true)]
        [System.Collections.IEnumerable]$Data
    )

    # Create the form
    $form = New-Object System.Windows.Forms.Form
    $form.Text = "Data Viewer"
    $form.Size = New-Object System.Drawing.Size(800, 450)
    $form.StartPosition = "CenterScreen"

    # Create the filter TextBox
    $textBox = New-Object System.Windows.Forms.TextBox
    $textBox.Location = New-Object System.Drawing.Point(10, 10)
    $textBox.Size = New-Object System.Drawing.Size(680, 20)
    $form.Controls.Add($textBox)

    # Create the filter Button
    $button = New-Object System.Windows.Forms.Button
    $button.Location = New-Object System.Drawing.Point(700, 10)
    $button.Size = New-Object System.Drawing.Size(75, 20)
    $button.Text = "Filter"
    $form.Controls.Add($button)

    # Create the DataGridView
    $dataGridView = New-Object System.Windows.Forms.DataGridView
    $dataGridView.Location = New-Object System.Drawing.Point(10, 40)
    $dataGridView.Size = New-Object System.Drawing.Size(760, 360)
    $dataGridView.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor `
                           [System.Windows.Forms.AnchorStyles]::Bottom -bor `
                           [System.Windows.Forms.AnchorStyles]::Left -bor `
                           [System.Windows.Forms.AnchorStyles]::Right
    $dataGridView.AutoSizeColumnsMode = "Fill"
    $dataGridView.ReadOnly = $true
    $form.Controls.Add($dataGridView)

    # Create DataTable and add columns dynamically
    $dataTable = New-Object System.Data.DataTable
    $firstItem = $Data | Select-Object -First 1
    $columns = $firstItem.PSObject.Properties.Name
    foreach ($column in $columns) {
        $dataTable.Columns.Add($column) > $null
    }

    # Add rows dynamically
    function Populate-DataTable {
        $dataTable.Rows.Clear()
        foreach ($item in $Data) {
            $row = $dataTable.NewRow()
            foreach ($column in $columns) {
                $row[$column] = $item.$column
            }
            $dataTable.Rows.Add($row) > $null
        }
    }

    Populate-DataTable

    $dataGridView.DataSource = $dataTable

    # Handle the Resize event to adjust DataGridView size
    $form.Add_Shown({$form.Activate()})
    $form.add_Resize({
        $dataGridView.Size = New-Object System.Drawing.Size($form.ClientSize.Width - 20, $form.ClientSize.Height - 50)
    })

    # Add the filter functionality
    $button.Add_Click({
        $filter = $textBox.Text
        $filteredData = $Data | Where-Object {
            $match = $false
            foreach ($column in $columns) {
                if ($_.PSObject.Properties[$column].Value -like "*$filter*") {
                    $match = $true
                }
            }
            $match
        }
        $dataTable.Rows.Clear()
        foreach ($item in $filteredData) {
            $row = $dataTable.NewRow()
            foreach ($column in $columns) {
                $row[$column] = $item.$column
            }
            $dataTable.Rows.Add($row) > $null
        }
    })

    # Show the form
    [void] $form.ShowDialog()
}

Example Usage

Displaying Processes

You can use the Show-DataInGrid function to display processes:

$processes = Get-Process | Select-Object -Property Id, ProcessName, CPU, WorkingSet
Show-DataInGrid -Data $processes

Option to Export the data to a CSV


Displaying Active Directory Users

If you have the Active Directory module installed, you can display AD users:

Import-Module ActiveDirectory
$users = Get-ADUser -Filter * -Property DisplayName, SamAccountName, UserPrincipalName | Select-Object DisplayName, SamAccountName, UserPrincipalName
Show-DataInGrid -Data $users

Explanation

  1. Dynamic Columns and Rows: The script dynamically creates columns based on the properties of the first item in the data collection. Rows are populated for each item in the data collection.
  2. Filtering Functionality: Users can enter a filter string in the TextBox. When the button is clicked, the script filters the data and updates the DataGridView.
  3. Resizable GUI: The DataGridView resizes dynamically when the form is resized, ensuring a responsive interface.

Conclusion

This script enhances the usability of PowerShell by providing a dynamic GUI for viewing and filtering data. It demonstrates how to leverage Windows Forms within PowerShell scripts, making data management more accessible and user-friendly. You can adapt this script to various datasets and customize it further to meet your specific needs.