• PowerShell Dynamic Windows Forms

    Home » Forums » Developers, developers, developers » DevOps Lounge » PowerShell Dynamic Windows Forms

    Author
    Topic
    #2377551

    Hey Y’all,

    I’ve been on a programming tear again trying to figure out how to do PowerShell Windows Forms that can automatically adjust to the data to be output. I was initially inspired by a post on StackOverflow. Well I finally did it and I have less hair to show for it! If you think you might be interested in it you can download it here. Just open the folder and download the Check-InstalledPrograms.zip file.

    FYI: The output looks like this:

    Check-InstalledPrograms
    Disclaimer: This is mostly for code junkies.

    May the Forces of good computing be with you!

    RG

    PowerShell & VBA Rule!
    Computer Specs

    1 user thanked author for this post.
    Viewing 4 reply threads
    Author
    Replies
    • #2377721

      RG, that is some very nicely crafted and concise code (some of which I even understood).

      I love that you can add your own software titles to look for, especially portables (which I find myself using more and more these days).

      If I may make a suggestion about graphic resources… perhaps make them relative, i.e. change:

      $CKMark      = "G:\BEKDocs\Scripts\Test\Check-mark-3-256.jpg"
      $XXMark      = "G:\BEKDocs\Scripts\Test\x-mark-256.gif"

      to

      $CKMark      = ".\Check-mark-3-256.jpg"
      $XXMark      = ".\x-mark-256.gif"

      It’s the difference – for us – between:

      rg_c-ip_orig

      and:

      rg_c-ip_amended

      (…  or provide remote access to your BEKDocs\Scripts\Test folder. 🙂 )

      Now… just in case you have any hair left… how about providing support for the native UWP apps?

      (I’m kidding… doesn’t everyone just de-bloat Windows 10+ of these?)

      Hope this helps…

      • #2377727

        Rick,

        Great suggestion! I’ll recode so that the graphic files are searched for in the same folder as the script is run from. That way no matter where you are when you call the script (using the appropriate location info) it will find the files.

        I’ll post back when done. 😎

        May the Forces of good computing be with you!

        RG

        PowerShell & VBA Rule!
        Computer Specs

        • #2377746

          RG… as a matter of interest – are the 2 graphics open source or your own?

          The reason I ask is because they are so clear and unequivocable that I was musing about re-using them (in AutoHotkey, of course… I don’t yet understand that newfangled PowerShell).

          However, I have no wish to step inadvertently on anyone’s copyright toes.

    • #2377776

      Rick,

      The program has been recoded so that as long as the graphics files are in the same folder/directory as the .ps1 file the program will find them no matter where you launch the program from.

      As for the graphics files they are free downloads from the net. 😎

      PS: use link in OP.

      May the Forces of good computing be with you!

      RG

      PowerShell & VBA Rule!
      Computer Specs

      1 user thanked author for this post.
      • #2377782

        Many thanks, RG

        But bitterly disappointed that no support for UWP apps despite the ~4 hours lead time since my suggestion.

        ROFL

        (Why is there no apparent mechanism to detach/delete attachments?)

         

    • #2377966

      Rick,

      You’re slipping…LOL!

      I wrote that one back in 2015!

      <#  
        +----------------------------------------------------------------------+
        | Program      : Uninstall Win10 Std Apps.ps1                          |
        | Programmer   : RetiredGeek (WSL) aka: ComputerMentor                 |
        | Created      : 01 Nov 2015                                           |
        | Last Updated : 07 Nov 2015                                           |
        | Current Vers : 5.6                                                   |
        | Description  : Prompts the user with a dialog with check boxes to    |
        |                select the Apps the user wishes to uninstall.         |
        |                The selected Apps will be automatically uninstalled   |
        |                when the user selects the UnInstall button.           |
        |                                                                      |
        | Credits      : http://www.howtogeek.com/224798/how-to-uninstall      |
        |                -windows-10s-built-in-apps-and-how-to-reinstall-them/ |
        |                                                                      |
        | Requirements : Windows 10 - PowerShell 4.0 - Administrator Access    |
        +----------------------------------------------------------------------+
      #>
      
      Function New-Button {
      <#+----------------------------------------------------------------------+
        | Function     : New-Button                                            |
        | Description  : Create a new Button object                            |
        | Programmer   : RetiredGeek (WSL) aka: ComputerMentor                 |
        | Created      : 11 Dec 2014                                           |
        | Last Updated :                                                       |
        | Current Vers : 1.0                                                   |
        +----------------------------------------------------------------------+
      #>
        param(
              [Parameter(Mandatory=$true)]
                [Int]$BtnLocX,   #Distance from left edge of form
              [Parameter(Mandatory=$true)]
                [Int]$BtnLocY,   #Distance from top of form
              [Parameter(Mandatory=$true)]
                [Int]$BtnWidth,
              [Parameter(Mandatory=$true)]
                [Int]$BtnHeight,
               [Parameter(Mandatory=$true)]
                [String]$BtnText,
               [Parameter(Mandatory=$true)]
                    $BtnFont,
               [Parameter(Mandatory=$true)]
                [String]$BtnBackColor,
               [Parameter(Mandatory=$false)]
                [String]$Result ="None"   # Yes No Cancel Ok    
             )
      
        $Button = New-Object System.Windows.Forms.Button
        $Button.Location = New-Object -TypeName `
                              System.Drawing.Size($BtnLocX,$BtnLocY)
        $Button.Size     = New-Object -TypeName `
                              System.Drawing.Size($BtnWidth,$BtnHeight)
        $Button.Text = "$BtnText"
        $Button.BackColor = "$BtnBackColor"
        $Button.Font = $BtnFont
        If ($Result -ne "None") {
          $Button.DialogResult = [System.Windows.Forms.DialogResult]::$Result
        }
        $Button
      
      }   #End Function New-Button
      
      Function New-CheckBox {
      <#+----------------------------------------------------------------------+
        | Function     : New-CheckBox                                          |
        | Description  : Create a new ChecktBox object                         |
        | Programmer   : RetiredGeek (WSL) aka: ComputerMentor                 |
        | Created      : 11 Dec 2014                                           |
        | Last Updated :                                                       |
        | Current Vers : 1.0                                                   |
        +----------------------------------------------------------------------+
      #>
      param(
              [Parameter(Mandatory=$true)]
                [Int]$CheckBoxLocX,   #Distance from left edge of form
              [Parameter(Mandatory=$true)]
                [Int]$CheckBoxLocY,   #Distance from top of form
              [Parameter(Mandatory=$true)]
                [Int]$CheckBoxWidth,
              [Parameter(Mandatory=$true)]
                [Int]$CheckBoxHeight,
              [Parameter(Mandatory=$true)]
                    $CheckBoxFont
            )
      
        $ObjCheckBox = New-Object -TypeName System.Windows.Forms.CheckBox 
        $ObjCheckBox.Location = New-Object -TypeName `
                         System.Drawing.Size($CheckBoxLocX,$CheckBoxLocY) 
        $ObjCheckBox.Size = New-Object -TypeName `
                         System.Drawing.Size($CheckBoxWidth,$CheckBoxHeight) 
        $ObjCheckBox.Font = $lbfont
      
        Return ,$ObjCheckBox
      
      }  #End Function New-Checkbox
      
      Function New-Font {
      <#+----------------------------------------------------------------------+
        | Function     : New-Font                                              |
        | Description  : Create a new font object                              |
        | Programmer   : RetiredGeek (WSL) aka: ComputerMentor                 |
        | Created      : 11 Dec 2014                                           |
        | Last Updated :                                                       |
        | Current Vers : 1.0                                                   |
        +----------------------------------------------------------------------+
      #>
       param(
              [Parameter(Mandatory=$true)]
                [String]$FontName,
              [Parameter(Mandatory=$false)]
                [String]$FontStyle='Regular',
              [Parameter(Mandatory=$false)]
                [Single]$FontSize=12
             )
      
        New-Object -TypeName System.Drawing.Font("$FontName",$FontSize, `
                                  [System.Drawing.FontStyle]::$FontStyle)  
      
      }   #End Function New-Font
      
      Function New-Label {
      <#+----------------------------------------------------------------------+
        | Function     : New-Label                                             |
        | Description  : Create a new Label object                             |
        | Programmer   : RetiredGeek (WSL) aka: ComputerMentor                 |
        | Created      : 11 Dec 2014                                           |
        | Last Updated :                                                       |
        | Current Vers : 1.0                                                   |
        +----------------------------------------------------------------------+
      #>
       param(
              [Parameter(Mandatory=$true)]
                [Int]$LabelLocXC1,   #Distance from left edge of form
              [Parameter(Mandatory=$true)]
                [Int]$LabelLocY,   #Distance from top of form
              [Parameter(Mandatory=$true)]
                [Int]$LabelWidth,
              [Parameter(Mandatory=$true)]
                [Int]$LabelHeight,
              [Parameter(Mandatory=$true)]
                [String]$LabelText,
              [Parameter(Mandatory=$true)]
                    $LabelFont
            )
      
        $objLabel = New-Object System.Windows.Forms.Label
        $objLabel.Location = New-Object System.Drawing.Size($LabelLocXC1,$LabelLocY) 
        $objLabel.Size = New-Object System.Drawing.Size($LabelWidth,$LabelHeight) 
        $objLabel.Text = "$LabelText"
        $objLabel.Font = $LabelFont
        
        Return ,$objLabel
      
      }   #End Function New-Label
      
      # -------------------   Main ------------------------
      
      Add-Type -AssemblyName System.Windows.Forms  #PS V3+
      Add-Type -AssemblyName System.Drawing
      
      # ----------------  add a helper  --------------------
      $showWindowAsync = Add-Type –memberDefinition @” 
      [DllImport("user32.dll")] 
      public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); 
      “@ -name “Win32ShowWindowAsync” -namespace Win32Functions –passThru
      
      function Show-PowerShell() { 
           [void]$showWindowAsync::ShowWindowAsync(
                      (Get-Process –id $pid).MainWindowHandle, 10) 
      }
      
      function Hide-PowerShell() { 
          [void]$showWindowAsync::ShowWindowAsync(
                     (Get-Process –id $pid).MainWindowHandle, 2) 
      }
      
      # ------------------ End Helper -------------------------------
      
      # ------------------ Main Program ------------------------------
      
      Hide-PowerShell
      
      $MyVersion = "Ver 5.6"
      $ErrorActionPreference = 'Stop'
      
      $MsgBox  = [Windows.Forms.MessageBox]
      $Buttons = [Windows.Forms.MessageBoxButtons]
      $MBIcons = [Windows.Forms.MessageBoxIcon]
      
      <#  **** Check Operating Requirements   ***
          **** Windows10+                   ***
          **** PowerShell 4.0+ as Admin       ***
      #>
      
      $WinTestVer = 63    #Use W8.1 = 63  W10 = 100
      $CurOS = Get-CimInstance -ClassName Win32_OperatingSystem
      $FullVersion = $CurOS.Version
      
      $OSVerItems = $CurOs.Version.split('.')
      <#
         Use CASTing [int] to make sure result is a NUMBER!
      #>
      $OSVer = ($([int]$OSVerItems[0])*10) + [int]$OSVerItems[1]
      $CurPSVer = [int]$psversiontable.psversion.Major
      If (-NOT ([Security.Principal.WindowsPrincipal] `
                [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
                [Security.Principal.WindowsBuiltInRole] "Administrator")) 
                {$PSPriv = "User"} Else {$PSPriv = "Administrator"} 
      
      If ($OSVer -lt $WinTestVer -or $CurPSVer -lt 4 -or $PSPriv -eq "User") {
      #*** Now strings incorporate ALL spaces thus no identing!
        $ReqWinVer = $(if ($WinTestVer -eq 100) {"10"} Else {"8.1"})
        $Message = `
      @("This program requires:
           Windows $($ReqWinVer)+ 
           PowerShell 4.0+ 
           Run as Administrator
      
       You are running:
           Windows:`t$($FullVersion.Trim(" "))
           PowerShell:`t$CurPSVer
           Running as:`t$($PSPriv)")
      
        [void]$MsgBox::Show("$Message","System Exit", `
                       $Buttons::OK, $MBIcons::Stop)
        Exit
      }
      # *** End Check Operating Requirements ***
      
      # --------- Enumerate Installed App Packages and Filter ---------------------
      
      [System.Collections.ArrayList]$AppList = @()  #Define an Empty dynamic array
      
      Get-AppxPackage | Sort-Object Name |
        ForEach-Object  {
      
      # *** Filter out Apps which CAN NOT be UnInstalled! ***
      
          If ( ($_.Name -notlike "*.VCLibs*" ) -and 
               ($_.Name -notlike "*.WinJS.*" ) -and
               ($_.Name -notLike "*store*"   ) -and
               ($_.Name -notLike "*MoCamera*") -and
               ($_.Name -notLike "*JunosPul*") -and
               ($_.Name -notLike "*SonicWAl*") -and
               ($_.Name -notlike "*.NET.*"   )) {
            [void] $AppList.add($_.name.Trim(" "))
          }
        }   # End ForEach-Object
      
      
      # Font styles are: Regular, Bold, Italic, Underline, Strikeout
      $Font    = New-Font -FontName "Tahoma"      -FontStyle "Regular" -FontSize 13
      $HdrFont = New-Font -FontName "Verdana"     -FontStyle "Regular" -FontSize 14
      $LBFont  = New-Font -FontName "Courier New" -FontStyle "Regular" -FontSize 11
      
      [System.Collections.ArrayList]$lblList  = @()  #Define an Empty dynamic array
      [System.Collections.ArrayList]$cboxList = @()  #Define an Empty dynamic array
      
      #Form Object Location/Width/Height sizes
      $LNSpacing       = 40
      $CurRowLoc       = 10
      $FormHeight      = 650
      $FormWidth       = 1080
      $MainTitleHeight = 50
      $OkCanBtnLoc     = $FormHeight - 95
      $StdBtnWidth     = 100
      $StdBtnHeight    = 40
      $LblHeight       = 30
      $CboxWidth       = 30
      $LblWidth        = 450
      $HDRWidth        = 430
      $HDRLoc          = (($FormWidth-$HdrWidth)/2)
      $ChkBoxCol       = @(0,20,(40+$CboxWidth+$LblWidth))
      $LabelCol        = @(0,55,(75+$Cboxwidth+$lblWidth))
      
      
      $OKButton     = New-Button -BtnLocX $ChkBoxCol[1]  -BtnLocY $OkCanBtnLoc   `
                                 -BtnWidth $StdBtnWidth -BtnHeight $StdBtnHeight `
                                 -BtnText "OK"          -BtnFont $HDRFont `
                                 -BtnBackColor "Green"  -Result "OK"
      
      $CancelButton = New-Button -BtnLocX (($FormWidth) - ($StdBtnWidth + 50))   `
                                 -BtnLocY $OkCanBtnLoc `
                                 -BtnWidth $StdBtnWidth -BtnHeight $StdBtnHeight `
                                 -BtnText "Cancel"      -BtnFont $HDRFont        `
                                 -BtnBackColor "Red"    -Result "Cancel"
      
      #Labels:
      
      $lblHeader = New-Label `
          -LabelLocX  $HdrLoc          -LabelLocY   $CurRowLoc `
          -LabelWidth $HDRWidth        -LabelHeight $LblHeight `
          -LabelText  " Check Apps you wish to UNInstall! " `
          -LabelFont  $HDRFont
      $LblHeader.BackColor = "Yellow"
      
      $CurRowLoc = 10                   #First position within tab control!
      $ColNo      = 1
      
      $AppList | ForEach-Object {
      
         [Void]$lblList.Add( $(New-Label `
            -LabelLocX  $LabelCol[2 - ($ColNo % 2)] -LabelLocY  $CurRowLoc `
            -LabelWidth $LblWidth                   -LabelHeight $LblHeight `
            -LabelText  $_.ToString()               -LabelFont  $Font))
      
         [Void]$cboxlist.add( $(New-CheckBox `
            -CheckBoxLocX  $ChkBoxCol[2-($ColNo % 2)] -CheckBoxLocY $CurRowLoc `
            -CheckBoxWidth $CboxWidth                 -CheckBoxHeight $LblHeight `
            -CheckBoxFont  $LBFont))
      
         $ColNo += 1
         $CurRowLoc += if ($ColNo % 2) {$LNSpacing} Else {0} 
      
      }  #End ForEach-Object
      
      #Form Setup:
      
      #----------- Main Tab Control ---------------------
      
      $System_Windows_Forms_Padding = New-Object `
                                      -TypeName System.Windows.Forms.Padding
      $System_Windows_Forms_Padding.All = 0
      
      $MainTabControl = New-Object -TypeName System.Windows.Forms.TabControl
      $tabInstApps    = New-Object -TypeName System.Windows.Forms.TabPage
      
      $MainTabControl.Name      = "MainTabControl"
      $MainTabControl.Location  = New-Object -TypeName System.Drawing.Point(10,50)
      $MainTabControl.Size      = New-Object -TypeName System.Drawing.Size($(
                                         $FormWidth-40), $($FormHeight -  170))
      $MainTabControl.ShowToolTips  = $True
      $MainTabControl.TabIndex      = 4
      $MainTabControl.Font          =  New-Object `
                                      -TypeName System.Drawing.Font("Tahoma",20,2,0)
      
      $tabWidth               = $FormWidth-20
      $tabHeight              = $FormHeight - $MainTitleHeight  + 20
      $tabInstApps.Name       = "Installed Apps"
      $tabInstApps.Location   = New-Object -TypeName System.Drawing.point(4,22)
      $tabInstApps.Padding    = $System_Windows_Forms_Padding
      $tabInstApps.Size       = New-Object -TypeName System.Drawing.Size(
                                                   $tabWidth,$tabHeight)  
      $tabInstApps.TabIndex   = 0
      $tabInstApps.AutoScroll = $True
      $tabInstApps.BackColor  = [Drawing.Color]::white
      $tabInstApps.Text       = "Installed Apps"
      $tabInstApps.DataBindings.DefaultDataSourceUpdateMode = 0
      $tabInstApps.UseVisualStyleBackColor = $True
      
      $MainTabControl.Controls.Add($tabInstApps)
      $lblList  | ForEach-Object {$tabInstApps.Controls.add($_)}
      $cboxList | ForEach-Object {$tabInstApps.Controls.add($_)}
      
      #--------------------------------- Main Form --------------------------------
      $objForm      = New-Object -TypeName System.Windows.Forms.Form 
      $objForm.Text = "Uninstall Windows 10 Builtin Apps $MyVersion"
      $objForm.Size = New-Object -TypeName System.Drawing.Size(
                                              $FormWidth,$FormHeight) 
      $objForm.StartPosition = "CenterScreen"
      $objForm.AcceptButton  = $OKButton
      $objForm.CancelButton  = $CancelButton
      $objForm.Topmost       = $True
      $objForm.ControlBox    = $False
      $objForm.AutoScroll    = $False
      
      $FormCtrls = `
           @($lblHeader, $MainTabControl, $OKButton, $CancelButton ) 
      
      $objForm.Controls.AddRange( $FormCtrls )
      
      $dialogResult = $objForm.ShowDialog()
      
      #Process Form Contents:
      
      if ($dialogResult -eq [System.Windows.Forms.DialogResult]::OK)
      {
      
        Clear-Host
      
        $Cntr = $applist.Count
      
        For ( $i = 0 ; $i -lt $cntr; $i++) {
         
           if ( $CboxList[$i].checked ) {
             Try {
                  Write-Host "Uninstalling $($AppList[$i])"
                  Get-AppxPackage -Name   "$($AppList[$i])" | Remove-AppxPackage 
             }          #End Try
             Catch {
                  Write-Host "Error Uninstalling: $($AppList[$i])"
             }          #End Catch
             Finally {
             }          #End Finally
           }
      
        } #End For $i
        
       
      }   #End if ($dialogResult -eq [System.Windows.Forms.DialogResult]::OK)
      Else
      {
          $Message = "User selected CANCEL or clicked the close box."
          $MsgBox::Show("$Message","User Exit", 
                         $Buttons::OK, $MBIcons::Stop)
      }
      
      $objForm.dispose()
      Show-PowerShell
      

      I called the file Dynamic-Uninst-Win10BuiltinApps.ps1
      HTH 😎

      May the Forces of good computing be with you!

      RG

      PowerShell & VBA Rule!
      Computer Specs

      1 user thanked author for this post.
    • #2377982

      RG… I don’t believe it. How the heck did I miss that one?

      (Or is my memory going…?)

      Thank you. 🙂

    • #2584039

      The download link no longer works.

      • #2584080

        the download link is fine..

        OnedriveCPM

        Windows - commercial by definition and now function...
        • #2584263

          Thanks.  I was able to get it on my personal computer.  I guess someone on my Cyber Security team is bucking for a promotion.

        • #2584267

          It depends on your network/security settings.  I don’t get it at my office either.

          Susan Bradley Patch Lady/Prudent patcher

    Viewing 4 reply threads
    Reply To: PowerShell Dynamic Windows Forms

    You can use BBCodes to format your content.
    Your account can't use all available BBCodes, they will be stripped before saving.

    Your information: