Share via


PowerShell form with Dynamic Content

Tools were created (PowerShell forms/scripts) for other teams in the business. With the number of tools growing per team, we thought it would be a good idea to have all these tools accessed from a single application/form/tool.

So, we created a tool that dynamically creates buttons on it when clicked and opens the respective tool.

The idea was:

  1. Change existing scripts to have specific information in them, preferably in the top of the script.

  2. Store all the tools in one central location.

3.Get the all-in-one tool to go through the scripts in a central location, parse the lines with specific text in them, and build the dynamic form.

Let's look at a sample script

For example, this is what my script has in the top three lines:

#Text = "Setup Lync User"

#Description = "Used to setup Lync User Account"

#Technology = "Lync"

Second has this:

#Text = "Redirect Printer"

#Description = "Used to redirect print queue"

#Technology = "Printer"

This is the script that does the work and builds the dynamic form:

    















    $form1 = New-Object 'System.Windows.Forms.Form'
    $flowlayoutpanel1 = New-Object 'System.Windows.Forms.FlowLayoutPanel'
    $tooltip1 = New-Object 'System.Windows.Forms.ToolTip'
    $InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
    $statusbar1 = New-Object 'System.Windows.Forms.StatusBar'  
    $form1_Load = {
    #Read the Scripts at this location and capture the tags at the top of the file
        $Script:scripts = Get-ChildItem "D:\Temp\Scripts\Production" -Include *.ps1 -Exclude "Dynamic_Buttons_Sample.ps1" -Recurse
        $Script:arrtxts = @()
    #Set Variables based on the tags and add the values to an array
        foreach ($script in $scripts)
        {
        $content = $null
        $shortcut = $null
        $Content = Get-Content $script
            $technology = (($Content | Select-String "#Technology = ") -replace "#Technology = ", "") -replace "`"",""
            $text =  $technology + " - " + ((($Content | Select-String "#Text = ") -replace "#Text = ", "") -replace "`"","")
            $description = (($Content | Select-String  "#Description = ") -replace "#Description = ", "") -replace "`"", ""
            $Script:click = $script.FullName
             
            $obj1 = New-Object -TypeName PSObject
            $obj1 | Add-Member -MemberType NoteProperty -Name Technology -Value $technology 
            $obj1 | Add-Member -MemberType NoteProperty -Name Text -Value $text
            $obj1 | Add-Member -MemberType NoteProperty -Name Description -Value $description
            $obj1 | Add-Member -MemberType NoteProperty -Name Path -Value $click
            $arrtxts = $arrtxts + $obj1
        }
        # Get Unique Technology values - this is used to create child flowlayout panels
        #to create button for each different technology
        $arrtxts = $arrtxts | sort Text
        $arrtech = $arrtxts.technology | Get-Unique | foreach-object {$tech = $_
        $flowlayoutpanel = New-Object 'System.Windows.Forms.FlowLayoutPanel'
        #$flowlayoutpanel.AutoScroll = $True
        $flowlayoutpanel.AutoSize = $true
        $flowlayoutpanel.Size = '300, 350'
        $flowlayoutpanel1.Controls.Add($flowlayoutpanel)
        $btn = New-Object 'System.Windows.Forms.Button'
        $lbl = New-Object 'System.Windows.Forms.Label'
        $lbl.Text = $tech
        $lbl.Size = '482, 23'
        $lbl.Location = '3, 0'
        $lbl.TextAlign = 'MiddleCenter'
        $lbl.Font = New-Object System.Drawing.Font("Times New Roman",15,[System.Drawing.FontStyle]::BOLD)
    $flowlayoutpanel.Controls.Add($lbl)
#For each of the technology/flowlayoutpanel create button for all scripts
$techscripts = $arrtxts | Where-Object {$_.Technology -eq $tech} | foreach-object {
$btn = New-Object 'System.Windows.Forms.Button'
            $btn.Size = '98,48'
            $btn.Text = $_.Text
            $btn.Tag = $_.Path
            #Add Tooltip
            $Tooltip1.SetToolTip($btn, $_.Description)
            $flowlayoutpanel.Controls.Add($btn)
            $btn.add_Click({ $p = (($($this.tag))); & $p } )
    }
        }
}
    $form1.Controls.Add($flowlayoutpanel1)
    $form1.Controls.Add($statusbar1)
    $form1.ClientSize = '600, 600'
    $form1.FormBorderStyle = 'FixedDialog'
    $form1.Name = 'form1'
    $form1.Text = 'All In One Tool'
    $form1.add_Load($form1_Load)
    $flowlayoutpanel1.AutoScroll = $True
    $flowlayoutpanel1.Location = '12, 25'
    $flowlayoutpanel1.Name = 'flowlayoutpanel1'
    $flowlayoutpanel1.Size = '590, 550'
    $flowlayoutpanel1.TabIndex = 0
    $statusbar1.Location = '0, 413'
    $statusbar1.Name = 'statusbar1'
    $statusbar1.Size = '580, 22'
    $statusbar1.TabIndex = 1
    $InitialFormWindowState = $form1.WindowState
    return $form1.ShowDialog()

Screenshot of the script:

http://blog.cybertechcomputers.co.nz/wp-content/uploads/2015/09/300x800xDynamic_Form-300x169.jpg.pagespeed.ic.5yvLF5ycmz.jpg

This is how the script works:

  1. Reads the scripts in the location specified and collects the info from the tags at the top of each script.

  2. Stores all this into in an array.

  3. Get-Unique technology tag values and creates a new child flowlayoutpanel for each of the technologies. Repeat for each technology.

  4. Find all the scripts that relate to a specific technology and create a button with the click event handler to open that particular script. Do this for all child flow layout panels.

  5. Add tooltip to each button so that the user can see what the button click does.

Try this out and provide feedback.

This was originally posted in the author's blog http://blog.cybertechcomputers.co.nz/