I want to push that point a bit and demonstrate a real world example of how and why you would design scripts with multiple layers in mind. In the real world, lots of scripts run in the shell, behind the scenes, and, nothing else. That trend, however, has to budge a little to account for GUI-based folks who want their Windows utilities. Its named Windows for a reason, remember. With that in mind, Ill demonstrate two different approaches to the same project and let you decide which works better for you. The main project is to create a PowerShell utility that examines NTP (network time protocol) data in a way end users can take advantage of. Approach 1 will include two scripts: 1) a "working example" and 2) a GUI wrapper. Approach 2 will include a single script with both unctions.
Approach 1: the normal model - a script and a GUI
Since no mere mortal uses w32tm or remembers the syntax for it, you were tasked with creating a little script utility to retrieve data from NTP servers. Your first efforts result in this basic, working command:
For the sake of argument, well pretend your admins and tech support team know what the output (listed below) means,w32tm /query /status
Well, alright. Youve got some sharp cookies on your team. But, instead of having to pick through this and manually type the command over and over, they want to achieve the condition representing the pinnacle of al IT: administratoronomic lazinosuous. Translation: uber-lazy admins jedi status. Ok, you take it up a notch and give them this,Leap Indicator: 3(last minute has 61 seconds)Stratum: 0 (unspecified)Precision: -6 (15.625ms per tick)Root Delay: 0.2264709sRoot Dispersion: 7.9770577sReferenceId: 0x00000000 (unspecified)Last Successful Sync Time: 7/13/2012 1:59:35 PMSource: ntp.server.orgPoll Interval: 10 (1024s)
A little less work, as now, you can simply type five characters and tab complete the rest. Better, they say, but, they like the idea of one button. In the back of your mind, you feel the old war wounds rouse up of the GUI versus command line battle you face with these young jedi gone bad who had so much potential. Fine, you give in, just, to avoid fighting stupid wars. So, you use your free download of Sapiens Primal Forms and come up with this little form. Yes, its a single, big, lazy button.function Get-NTPStatus{w32tm /query /status}
#Generated Form Functionfunction GenerateForm {######################################################################### Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.10.0# Generated On: 7/13/2012 4:07 PM# Generated By: wsteele#########################################################################region Import the Assemblies[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null#endregion#region Generated Form Objects$form1 = New-Object System.Windows.Forms.Form$button1 = New-Object System.Windows.Forms.Button$textBox1 = New-Object System.Windows.Forms.TextBox$InitialFormWindowState= New-Object System.Windows.Forms.FormWindowState#endregion Generated Form Objects#----------------------------------------------#Generated Event Script Blocks#----------------------------------------------#Provide Custom Code for events specified in PrimalForms.$button1_OnClick={#TODO: Place custom script here$textBox1.Text = w32tm /query /status}$OnLoadForm_StateCorrection={#Correct the initial state of the form to prevent the .Net maximized form issue$form1.WindowState = $InitialFormWindowState}#----------------------------------------------#region Generated Form Code$System_Drawing_Size= New-Object System.Drawing.Size$System_Drawing_Size.Height = 280$System_Drawing_Size.Width = 282$form1.ClientSize = $System_Drawing_Size$form1.DataBindings.DefaultDataSourceUpdateMode = 0$form1.Name = "form1"$form1.Text = "Primal Form"$button1.DataBindings.DefaultDataSourceUpdateMode = 0$System_Drawing_Point= New-Object System.Drawing.Point$System_Drawing_Point.X = 13$System_Drawing_Point.Y = 13$button1.Location = $System_Drawing_Point$button1.Name = "button1"$System_Drawing_Size= New-Object System.Drawing.Size$System_Drawing_Size.Height = 32$System_Drawing_Size.Width = 257$button1.Size = $System_Drawing_Size$button1.TabIndex = 1$button1.Text = "Give me some NTP goodness"$button1.UseVisualStyleBackColor = $True$button1.add_Click($button1_OnClick)$form1.Controls.Add($button1)$textBox1.DataBindings.DefaultDataSourceUpdateMode = 0$System_Drawing_Point= New-Object System.Drawing.Point$System_Drawing_Point.X = 13$System_Drawing_Point.Y = 51$textBox1.Location = $System_Drawing_Point$textBox1.Multiline = $True$textBox1.Name = "textBox1"$System_Drawing_Size= New-Object System.Drawing.Size$System_Drawing_Size.Height = 215$System_Drawing_Size.Width = 257$textBox1.Size = $System_Drawing_Size$textBox1.TabIndex = 0$form1.Controls.Add($textBox1)#endregion Generated Form Code#Save the initial state of the form$InitialFormWindowState= $form1.WindowState#Init the OnLoad event to correct the initial state of the form$form1.add_Load($OnLoadForm_StateCorrection)#Show the Form$form1