Getting Started with PrimalForms

drivereport I hope you are as excited about the release of PrimalForms as I am. In the past creating a Windows form in PowerShell was a very tedious task and one I rarely used except for the most simplest of forms. No more. The free PrimalForms tool lets me create a very rich Windows form using a WYSIWYG editor. I can export the form to a file, add my PowerShell code and call it a day.

Start:

The first time you launch the tool, I strongly encourage you to also click the Getting Started and spend a few minutes going through the Getting Started guide. It will walk you through PrimalForms as well as creating a PowerShell script. I’ve also provided several sample forms and associated scripts. While you could use them in a production environment (after testing of course), they are primarily intended as samples.

Remember, PrimalForms only generates PowerShell code to present the form. If you associate an event with a control, like Click with a button control, the generated PowerShell code will define script blocks. All you have to do is add your PowerShell code. Windows PowerShell v1.0: TFM 2nd Edition has additional information on creating and using Windows Forms with PowerShell.

If you have issues using the tool itself, there is a free tools support forum at SAPIEN.com. If you need help developing a PowerShell script from your form, please use the PowerShell forum at ScriptingAnswers.com.

Sample:

To get you started and perhaps whet your appetite, here is another PrimalForms-generated script. The script gets all the logical disks for a specified computer using WMI and displays useful information. A progress bar will give you a graphical representation of how much free space is left on the drive.

   1: #DriveInfo.ps1
   2: #v1.0 11/3/2008
   3: #Jeffery Hicks jhicks@sapien.com
   4: #http://www.scriptingAnswers.com
   5:
   6: #USAGE: .\driveinfo.ps1
   7:
   8: # ****************************************************************
   9: # * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
  10: # * IN A SECURED LAB ENVIRONMENT. USE AT YOUR OWN RISK.          * 
  11: # ****************************************************************
  12:
  13: Function Get-Drives {
  14:  Param([string]$computername=$env:computername)
  15:
  16:  #don't display any error messages
  17:  $drives=Get-WmiObject Win32_logicaldisk -computername $computername `
  18:  -filter "drivetype=3" -ea "SilentlyContinue"
  19:
  20:  foreach ($drive in $drives) {
  21:     write $drive.deviceID
  22:  }
  23:
  24: }
  25:
  26: Function Get-DriveInfo {
  27:     Param([string]$computername=$env:computername,
  28:            [string]$drive="c:"
  29:            )
  30:
  31:   $logical=get-wmiobject win32_logicaldisk -computername $computername -filter "deviceid='$drive'"
  32:   $partition= get-wmiobject -computername $computername `
  33:   -query "associators of {win32_logicaldisk.deviceid='$drive'} where resultclass=win32_diskpartition"
  34:
  35:   $obj=New-Object PSObject
  36:   $obj | Add-Member Noteproperty "DeviceId" $logical.DeviceID
  37:   $obj | Add-Member Noteproperty "VolumeName" $logical.VolumeName
  38:   $obj | Add-Member Noteproperty "VolumeSerialNumber" $logical.VolumeSerialNumber
  39:   $obj | Add-Member Noteproperty "PrimaryPartition" $partition.PrimaryPartition
  40:   $obj | Add-Member Noteproperty "NumberOfBlocks" $partition.NumberofBlocks
  41:   $obj | Add-Member Noteproperty "BlockSize" $partition.blocksize
  42:   $obj | Add-Member Noteproperty "BootPartition" $partition.BootPartition
  43:   $obj | Add-Member Noteproperty "Compressed" $logical.Compressed
  44:   $obj | Add-Member Noteproperty "Filesystem" $logical.FileSystem
  45:   $obj | Add-Member Noteproperty "Size(MB)" ($logical.Size/1MB -as [int])
  46:   $obj | Add-Member Noteproperty "Freespace(MB)" ($logical.Freespace/1MB -as [int])
  47:   $obj | Add-Member Noteproperty "PercentFree" (([double]$logical.freespace/[double]$logical.size)*100 -as [int])
  48:   $obj | Add-Member Noteproperty "PartitionSize(MB)" ($partition.size/1MB -as [int])
  49:
  50:   write $obj
  51: }
  52:
  53: ########################################################################
  54: # Code Generated By: SAPIEN Technologies PrimalForms 2009 v1.0.0.0
  55: # Generated On: 11/3/2008 10:39 AM
  56: # Generated By: Jeffery Hicks
  57: ########################################################################
  58:
  59: #region Import the Assembles
  60: [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
  61: [reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
  62: #endregion
  63:
  64: #region Generated Form Objects
  65: $form1 = New-Object System.Windows.Forms.Form
  66: $linkLabel1 = New-Object System.Windows.Forms.LinkLabel
  67: $btnGetInfo = New-Object System.Windows.Forms.Button
  68: $richTextBox1 = New-Object System.Windows.Forms.RichTextBox
  69: $btnClose = New-Object System.Windows.Forms.Button
  70: $comboDrives = New-Object System.Windows.Forms.ComboBox
  71: $statusBar = New-Object System.Windows.Forms.StatusBar
  72: $lblDrive = New-Object System.Windows.Forms.Label
  73: $progUsage = New-Object System.Windows.Forms.ProgressBar
  74: $txtComputerName = New-Object System.Windows.Forms.TextBox
  75: #endregion Generated Form Objects
  76:
  77: #----------------------------------------------
  78: #Generated Event Script Blocks
  79: #----------------------------------------------
  80: #Provide Custom Code for events specified in PrimalForms.
  81: $CloseForm=
  82: {
  83: $form1.close()
  84: }
  85:
  86: $OpenDrive=
  87: {
  88: [system.Diagnostics.Process]::start("Explorer",$linkLabel1.text)
  89: }
  90:
  91: $GetDriveInfo=
  92: {
  93: $statusBar.Text=("Getting drive details for {0} on {1}" -f $comboDrives.SelectedItem,$txtComputerName.text)
  94:
  95: $driveData=Get-DriveInfo -computername $txtComputerName.Text -drive $comboDrives.SelectedItem
  96:
  97: #set drive label to selected DeviceID
  98: $lblDrive.text=$driveData.DeviceID
  99:
 100: #build report data and convert to string
 101: $report=$driveData | Format-List |Out-String
 102:
 103: #set richtext box text to report data
 104: $richTextBox1.Text=$report.Trim()
 105:
 106: $progUsage.Value=$driveData.PercentFree
 107:
 108: $linkLabel1.text="\\{0}\{1}" -f $txtComputerName.Text.ToUpper(),$driveData.DeviceID.Replace(":","$")
 109:
 110: $statusBar.Text="Ready"
 111:
 112: }
 113:
 114: $GetDrives=
 115: {
 116: $statusBar.Text=("Getting fixed logical drives for {0}" -f $txtComputername.text.toUpper())
 117:
 118: #clear richTextBox
 119: $richTextBox1.text=$Null
 120:
 121: $collDrives=Get-Drives $txtComputerName.Text
 122: if ($collDrives) {
 123: #only proceed if a connection was made to the computer
 124:     #clear the drive dropdown of any existing values
 125:     $comboDrives.Items.Clear()
 126:
 127:     #populate the drive dropdown
 128:     foreach ($drive in $collDrives) {
 129:       $comboDrives.Items.add($drive)
 130:     }
 131:     $comboDrives.SelectedIndex=0
 132:     $comboDrives.Enabled=$True
 133:
 134:     &$GetDriveInfo
 135: }
 136: else
 137: {
 138: $richTextBox1.text=("Failed to get drives for {0}" -f $txtComputerName.Text.ToUpper())
 139: $comboDrives.Items.Clear()
 140: $comboDrives.Text="N/A"
 141: $progUsage.value=0
 142: $lblDrive="N/A"
 143: $linkLabel1.text="N/A"
 144: }
 145:
 146: $statusBar.Text="Ready"
 147:
 148: }
 149:
 150: #----------------------------------------------
 151: #region Generated Form Code
 152: $form1.Name = 'form1'
 153: $form1.Text = 'Drive Report'
 154: $form1.DataBindings.DefaultDataSourceUpdateMode = 0
 155: $form1.FormBorderStyle = 1
 156: $System_Drawing_Size = New-Object System.Drawing.Size
 157: $System_Drawing_Size.Width = 284
 158: $System_Drawing_Size.Height = 333
 159: $form1.ClientSize = $System_Drawing_Size
 160: $form1.add_Load($GetDrives)
 161:
 162: $linkLabel1.TabIndex = 7
 163: $linkLabel1.Text = 'open'
 164: $linkLabel1.TabStop = $True
 165: $linkLabel1.Name = 'linkLabel1'
 166: $System_Drawing_Point = New-Object System.Drawing.Point
 167: $System_Drawing_Point.X = 151
 168: $System_Drawing_Point.Y = 48
 169: $linkLabel1.Location = $System_Drawing_Point
 170: $linkLabel1.TextAlign = 32
 171: $System_Drawing_Size = New-Object System.Drawing.Size
 172: $System_Drawing_Size.Width = 100
 173: $System_Drawing_Size.Height = 23
 174: $linkLabel1.Size = $System_Drawing_Size
 175: $linkLabel1.DataBindings.DefaultDataSourceUpdateMode = 0
 176: $linkLabel1.add_Click($OpenDrive)
 177:
 178: $form1.Controls.Add($linkLabel1)
 179:
 180: $btnGetInfo.UseVisualStyleBackColor = $True
 181: $btnGetInfo.Text = 'Get Drives'
 182: $btnGetInfo.DataBindings.DefaultDataSourceUpdateMode = 0
 183: $btnGetInfo.TabIndex = 1
 184: $btnGetInfo.Name = 'btnGetInfo'
 185: $System_Drawing_Size = New-Object System.Drawing.Size
 186: $System_Drawing_Size.Width = 75
 187: $System_Drawing_Size.Height = 23
 188: $btnGetInfo.Size = $System_Drawing_Size
 189: $System_Drawing_Point = New-Object System.Drawing.Point
 190: $System_Drawing_Point.X = 197
 191: $System_Drawing_Point.Y = 13
 192: $btnGetInfo.Location = $System_Drawing_Point
 193: $btnGetInfo.add_Click($GetDrives)
 194:
 195: $form1.Controls.Add($btnGetInfo)
 196:
 197: $richTextBox1.Text = ''
 198: $richTextBox1.TabIndex = 6
 199: $richTextBox1.Name = 'richTextBox1'
 200: $richTextBox1.Font = New-Object System.Drawing.Font("Lucida Console",8.25,0,3,1)
 201: $richTextBox1.BackColor = [System.Drawing.Color]::FromArgb(255,240,240,240)
 202: $richTextBox1.ReadOnly = $True
 203: $richTextBox1.BorderStyle = 0
 204: $System_Drawing_Size = New-Object System.Drawing.Size
 205: $System_Drawing_Size.Width = 259
 206: $System_Drawing_Size.Height = 159
 207: $richTextBox1.Size = $System_Drawing_Size
 208: $richTextBox1.DataBindings.DefaultDataSourceUpdateMode = 0
 209: $System_Drawing_Point = New-Object System.Drawing.Point
 210: $System_Drawing_Point.X = 13
 211: $System_Drawing_Point.Y = 78
 212: $richTextBox1.Location = $System_Drawing_Point
 213:
 214: $form1.Controls.Add($richTextBox1)
 215:
 216: $btnClose.UseVisualStyleBackColor = $True
 217: $btnClose.Text = 'Close'
 218: $btnClose.DataBindings.DefaultDataSourceUpdateMode = 0
 219: $btnClose.TabIndex = 3
 220: $btnClose.Name = 'btnClose'
 221: $System_Drawing_Size = New-Object System.Drawing.Size
 222: $System_Drawing_Size.Width = 75
 223: $System_Drawing_Size.Height = 23
 224: $btnClose.Size = $System_Drawing_Size
 225: $System_Drawing_Point = New-Object System.Drawing.Point
 226: $System_Drawing_Point.X = 102
 227: $System_Drawing_Point.Y = 282
 228: $btnClose.Location = $System_Drawing_Point
 229: $btnClose.add_Click($CloseForm)
 230:
 231: $form1.Controls.Add($btnClose)
 232:
 233: $comboDrives.Name = 'comboDrives'
 234: $System_Drawing_Size = New-Object System.Drawing.Size
 235: $System_Drawing_Size.Width = 121
 236: $System_Drawing_Size.Height = 21
 237: $comboDrives.Size = $System_Drawing_Size
 238: $comboDrives.FormattingEnabled = $True
 239: $comboDrives.Enabled = $False
 240: $comboDrives.TabIndex = 2
 241: $System_Drawing_Point = New-Object System.Drawing.Point
 242: $System_Drawing_Point.X = 13
 243: $System_Drawing_Point.Y = 50
 244: $comboDrives.Location = $System_Drawing_Point
 245: $comboDrives.DataBindings.DefaultDataSourceUpdateMode = 0
 246: $comboDrives.add_SelectedIndexChanged($GetDriveInfo)
 247:
 248: $form1.Controls.Add($comboDrives)
 249:
 250: $statusBar.Name = 'statusBar'
 251: $statusBar.DataBindings.DefaultDataSourceUpdateMode = 0
 252: $statusBar.TabIndex = 3
 253: $System_Drawing_Size = New-Object System.Drawing.Size
 254: $System_Drawing_Size.Width = 284
 255: $System_Drawing_Size.Height = 22
 256: $statusBar.Size = $System_Drawing_Size
 257: $System_Drawing_Point = New-Object System.Drawing.Point
 258: $System_Drawing_Point.X = 0
 259: $System_Drawing_Point.Y = 311
 260: $statusBar.Location = $System_Drawing_Point
 261: $statusBar.Text = 'Ready'
 262:
 263: $form1.Controls.Add($statusBar)
 264:
 265: $lblDrive.Text = 'C:'
 266: $lblDrive.DataBindings.DefaultDataSourceUpdateMode = 0
 267: $lblDrive.TabIndex = 2
 268: $lblDrive.TextAlign = 64
 269: $lblDrive.Name = 'lblDrive'
 270: $System_Drawing_Size = New-Object System.Drawing.Size
 271: $System_Drawing_Size.Width = 32
 272: $System_Drawing_Size.Height = 23
 273: $lblDrive.Size = $System_Drawing_Size
 274: $System_Drawing_Point = New-Object System.Drawing.Point
 275: $System_Drawing_Point.X = 0
 276: $System_Drawing_Point.Y = 243
 277: $lblDrive.Location = $System_Drawing_Point
 278:
 279: $form1.Controls.Add($lblDrive)
 280:
 281: $progUsage.DataBindings.DefaultDataSourceUpdateMode = 0
 282: $progUsage.Style = 1
 283: $progUsage.TabIndex = 1
 284: $progUsage.Name = 'progUsage'
 285: $System_Drawing_Size = New-Object System.Drawing.Size
 286: $System_Drawing_Size.Width = 234
 287: $System_Drawing_Size.Height = 23
 288: $progUsage.Size = $System_Drawing_Size
 289: $progUsage.ForeColor = [System.Drawing.Color]::FromArgb(255,0,255,0)
 290: $progUsage.BackColor = [System.Drawing.Color]::FromArgb(255,255,0,0)
 291: $System_Drawing_Point = New-Object System.Drawing.Point
 292: $System_Drawing_Point.X = 29
 293: $System_Drawing_Point.Y = 243
 294: $progUsage.Location = $System_Drawing_Point
 295:
 296: $form1.Controls.Add($progUsage)
 297:
 298: $txtComputerName.Text = $env:computername
 299: $txtComputerName.Name = 'txtComputerName'
 300: $txtComputerName.TabIndex = 0
 301: $System_Drawing_Size = New-Object System.Drawing.Size
 302: $System_Drawing_Size.Width = 178
 303: $System_Drawing_Size.Height = 20
 304: $txtComputerName.Size = $System_Drawing_Size
 305: $System_Drawing_Point = New-Object System.Drawing.Point
 306: $System_Drawing_Point.X = 13
 307: $System_Drawing_Point.Y = 13
 308: $txtComputerName.Location = $System_Drawing_Point
 309: $txtComputerName.DataBindings.DefaultDataSourceUpdateMode = 0
 310:
 311: $form1.Controls.Add($txtComputerName)
 312:
 313: #endregion Generated Form Code
 314:
 315: #Show the Form
 316: $form1.ShowDialog()| Out-Null
 317:

The script defaults to the C: drive on the local host. Enter a new computername, and click the Get Drives button. This will populate the drop down list with all logical drives on that computer. The default drive will be C:\. An error will be displayed if the remote computer can’t be reached. The script assumes you have administrative shares enabled so you can click on the link to the right and connect to the corresponding share.

You can download a zip file with the form and script here.

Share:

Once you finish your PowerShell forms script, I hope you’ll share it. Not only might other administrators need your tool, they might find it helpful as a template or starting point for there own projects.