Two ways to provide GUI interaction to users

February 17, 2014 FoxDeploy

Learning PowerShell GUIs

This post is part of the Learning GUI Toolmaking Series, here on FoxDeploy. Click the banner to return to the series jump page!


In this blog post, I’ll outline two methods you can use in your PowerShell scripts to provide GUI interactivity to your users, and allow them to select an object from a list.  These may not be the best method to achieve a goal, but are quick and simple enough that you can throw them in your scripts.

Method One

First, the System.Windows.Forms .Net way of building a form.  In this case, we’ll have a string $users, which will contain the results of an Active Directory Query to return all users with a name like ‘Fox-*’, so Fox-01, Fox-07, and so on.  One thing that is tricky to many (I know it was to me!) when they first start using .net forms to build GUIs is that it can be hard to understand how to list dynamic content in a ComboBox or ListBox.

One thing to keep in mind when choosing between the two is that only a ListBox allows for the selection of more than one object.

ListBox v. ComboBox - Bitter Enemies

Assume we have a ListBox defined and added to our Form.  This is the code you’d need to do so.

`#begin to draw list box 
$ListBox = New-Object System.Windows.Forms.ListBox $ListBox.Location = New-Object System.Drawing.Size(10,40) 
$ListBox.Size = New-Object System.Drawing.Size(160,20) 
$ListBox.Height = 80 
$ListBox.Name = 'ListBox_UserName' 
$ListBox.SelectionMode = "MultiExtended"`

Note : in all of these examples, you could use a .ComboBox instead of a .ListBox and it would still work.

If we run this code in PowerShell and then pipe $ListBox to Get-Member, we’ll see a number of interesting properties and methods available.  The one which will store the content happens to be titled .Items, to access the contents, check $ListBox.Items. The trick to adding Dynamic content (e.g. the results of a query or search) to your UI elements is to add each element to the $ListBox.Items Property using the .Add method, as seen below.

$ListBox.Items.Add("Something we want to add") $ListBox.Items.Add("waffles")

For those of you following along at home, if you input $ListBox.Items, you’ll see the following.

Maybe it should say ‘Something we want to eat’[/caption]

Now, that we know it is so easy to add items to a list or combo box, if we want to add the results of a query or function, we just use a ForEach function!

#For each object within Users... 
$users| ForEach-Object{ 
  #the [void] below adds this element to our form, but suppresses any output associated 
  [void] $ListBox.Items.Add($_.Name) }`

Now, we’ll jump ahead for a bit and assume you’ve built a form and added listeners for Enter and Escape (code available here).

If you run this in PowerShell, you’ll see output similar to this.  In this lazy example, we’ll depend on the user hitting Enter to leave the form.  If you want to add an okay button, I suppose that is acceptable as well.  Throw this bad boy into your code.

#Set Properties for the Ok button 
$OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Size(180,75) 
$OKButton.Size = New-Object System.Drawing.Size(75,23) 
$OKButton.Text = "OK" 
#What to do when the button is clicked, you can treat this like a function 
$OKButton.Add_Click({$Form.Close()}) 
#Add the button to our form 
$Form.Controls.Add($OKButton)`

You should be left with a result like this [Link to code] and it will look like this.

If we need to access the objects selected, we can call $Listbox.SelectedItems to see all of the items that were selected.

So, this worked and was relatively simple.  But not that simple, and it really is quite a lot of code to do all this.  There is an easier method.

Method Two

Sure, it’s a lot of fun to add all of this code to our scripts to create a GUI, but starting in PowerShell v3, a very powerful new ability was bestowed upon Out-GridView: the new -PassThru switch!

Lets recreate functionally the same tool, but using this new method.  Stretch your typing fingers, kiddies, its going to be quite a stretch!

$users = get-aduser -filter {Name -like "Fox-*"}

$x = $users | Select Name | Out-GridView -PassThru -Title 'Pick a user' | % {$_}

Surely that can’t be it.  Lets just give it a try…

No fliiping way!

And the objects are available for you to act on at the end as well, stored in $x.

I’ve sworn by creating WPF GUIs in PowerShell for a long while now.  However, this new flexibility at least gives me some pause.

Readers: do you like posts like this?  The skies the limit to the complexity of UI we create in PowerShell.  If you’d like to see more, let me know!``

Continue Reading...

Before everything fails, ask.

February 06, 2014 FoxDeploy

This was a definite learning experience.

At a client recently for a side-by-side 2012 R2 SCCM migration, I was testing image build on desktop and laptop models, and noticed that some 2007 clients were able to detect the 2012 MP and were trying to download content from them!  That was very undesired, and so we delved into AD Sites and Services and discovered that some of the subnets in a particular site were more expansive than previously thought.  We then noticed a perfectly innocuous looking Site, ‘CompanyLocation_TestLab’ and found that this corresponded to a switch in a testing area nearby.  Perfect!  I quickly edited the boundaries and set them to this new AD Site and resumed image testing.

And so began the slow. Image transfer, and content download dropped to a standstill, even though I applied the slow OSD KB to the boot images, CAS and DPs.

I finally asked if there was some sort of traffic bandwidth management/shaping protocol in affect on the testlab subnet. Well, turns out there was!! There was a bandwidth shaping device in place for this subnet that has transfers throttled down to much slower than t1 speeds, in order to test remote office performance for the slowest of remote sites. It made copying a 3 GB image take an astounding 13 hours.

All of this could have been avoided had I asked the right questions from the beginning.  It was a very teachable moment.

Before everything fails, ask.

Continue Reading...

SCCM SQL Reports fail with 'An Error has occurred during report processing'

January 23, 2014 FoxDeploy

Recently at a client, we encountered this lovely error message when launching a Configuration Manager (ConfigMgr) report from the webconsole:

“An error occurred during client rendering. An error has occurred during report processing. (rsProcessingAborted) Cannot impersonate user for data source ‘AutoGen_[GUID]_’. (rsErrorImpersonatingUser) Log on failed. (rsLogonFailed) For more information about this error navigate to the report server on the local server machine, or enable remote errors “

Additionally, we witnessed a similar message with stack trace info in the SCCM console itself.

Such a great way to start your day, eh?

The fix for this error is one of two things:

  1. Ensure that you’re using a service account to access the SCCM Data Source, this is configured under Administration -> Site Configuration ->Servers and Site Roles->Site Server Running Reporting->Reporting Services Point.

    Double-check that a local user account with a changing user account IS NOT being used.

    If these credentials are valid, move on to #2.

  2. Connect to the reporting service point with an account that has administrative rights from a web console.  Click your SQL Reporting instance and go to Security.  Ensure the account above has at least SQL Reporting Administrator rights.

    If this is set, move on to #3.

  3. Launch Reporting Services Configuration Manager and connect to the server running your SQL Reporting Instance.  Ensure that the same account above is listed as the Execution Account.

We detected that the issue was caused by an administrators account being used for the above fields (it was set during installation before the service account was ready), and the password recently changed.  Hope this helps!

Continue Reading...

SCCM: Solved Update not synced due to pending EULA Download.

January 23, 2014 FoxDeploy

Today while attempting to deploy certain Windows Updates (namely IE 9 and IE 11) in a new 2012 R2 environment, I noticed that the two updates would not appear while doing a search for them within SCCM. After checking my product classifications to ensure the update should be there, I then c  hecked WSUS on the server for the update, saw them.

Why are you hiding from me?

I then investigated the log files.  Within wsyncmgr.log, I saw numerous entries like the following:

Error ' Wsyncmgr.log' entry Update [GUID] not synced due to pending EULA Download. [..] EULA sync failures summary: Update [GUID] not synced due to pending EULA Download. Sync partially completed due to pending EULAs.  No admin intervention required, will retry in 60 minutes.

This can occasionally happen if your proxy settings do not support HTTP 1.1 redirection, and so I double checked the proxy.  The settings checked out (but if not, some recommend changing these values under Administration \ Site Configuration \ Servers and Site System Roles\Site Name\Software Update Point)

Try double-checking these values if you run into the same situation

One measure you can take in troubleshooting a WSUS system is to use the WSUSUtil and its parameters to try to locate the issue.  In this case, I used the reset switch, which forces WSUS to recheck all content and redownload any missing or corrupt update files.  You’ll find the tool at %drive%\Program Files\Update Services\Tools. Give the tool a few minutes to run, you’ll see no command output, nor records in the Application Event Viewer Log.  Afterwards, I reran the sync and watched the wsyncmgr.log again.  This time I saw messages like 'Synchronizing update [GUID] - Internet Explorer 11 for Windows 7'.

Ahhh, the smell of progress.

And within the console

Whenever I see IE 11 written out, I hear that ‘Too close’ song by Alex Clair in my head.

I hope this helps you out.

Continue Reading...

SCCM PowerShell Reference : Configuring File Replication

January 03, 2014 FoxDeploy

Depicts an image saying 'Scripting System Center Configuration Manager'

This post is part of the ‘Scripting SCCM’ series on FoxDeploy, click the banner for more!


This is a little quicky.  I’ve found the documentation both on TechNet and in PowerShell’s in-line help to be very lacking for the new Configuration Manager Commandlettes, so I did the work to figure them out on my own and will post some of what I’ve learned here.  I recently needed to configure Bandwidth Control for a client and loathed manually setting these options on all of the servers, so I turned to PS.   In my example, I needed to restrict package transfer at certain times, and during those times, also control how much bandwidth was being used.

To limit package transfers between all servers to Medium and High priority between 6 and 5:00 (corresponding to the Schedule Tab under Administration Hierarchy Configuration File Replication)
Get-CMFileReplicationRoute | Set-CMFileReplicationRoute -DaysOfWeek Monday,Tuesday,Wednesday,Thursday,Friday -ControlNetworkLoadSchedule -TimePeriodStart 6 -TimePeriodEnd 17 -AvailabilityLevel MediumHigh

The Options for -AvailabilityLevel are :

  • All - transfer all packages
  • Closed - transfer no packages
  • High - transfer only High Priority Packages
  • MediumHigh - transfer Medium and High Priority Packages

Set the bandwidth consumed between all servers to 30% between 6 and 5:00 (Corresponding to options you would set on the ‘Rate Limits’ tab)

Get-CMFileReplicationRoute | Set-CMFileReplicationRoute -Limited -LimitAvailableBandwidthPercentage 30 -LimitedTimePeriodStart 6 -LimitedTimePeriodEnd 17

Combining the two commands proved to be difficult, as PowerShell would get hung up on -Limited thinking it was an ambiguous parameter.  I ended up running them separately.  Hope this helps!

Continue Reading...

SCCM Powershell Reference: Adding content to all Distribution Points

January 03, 2014 FoxDeploy

Depicts an image saying 'Scripting System Center Configuration Manager'

This post is part of the ‘Scripting SCCM’ series on FoxDeploy, click the banner for more!


Another quickie here: I needed a way to add all packages to all distribution points, and do so with as few / zero clicks as possible.  Using a few PowerShell commands, I was able to do just that!  While there is no native command (yet!) to push content to a distribution point, you can easily do so with a WMI call, and automate the whole process with a single pipeline.

For the first step, we’ll use the Configuration Manager Module’s Get-CMPackage Command, and pipe it into a filter.  We’ll need the PackageID field, and would prefer not to have the value include the column header, so we’ll use the -ExpandProperty parameter to omit this.

Get-CMPackage | Select - ExpandProperty PackageID

Now, we need to connect to the local SCCM instance.  We’ll use Get-WMIObject to do so.

Get-WMIObject -NameSpace "Root\SMS\Site_YOUR_PRIMARY_OR_CAS_SITE_CODE" -Class SMS_DistributionPointGroup

If you pipe this command into Get-Member, you’ll see the output below.  This tells us of all of the properties and methods we’ll have available using the WMI Object.  I’ve highlighted the method we need, AddPackages().

Now, to put it all together.  We’ll first enumerate all of the PackageIDs, and send this value on down our command line using a pipeline.  This value will be assigned to $package in the run phase of the ForEach-Object command, in which the WMI Object’s AddPackage() method will be called once for each object in the variable, using the $_ current pipeline object character.  Some rudimentary error catching is here, looking to see if a non-zero value is returned.  Here is the command.

Get-CMPackage | Select -ExpandProperty PackageID | ForEach-Object { $package = $_ Write-host "Adding Package: $package" if (((Get-WMIObject -NameSpace "Root\SMS\Site_YOUR-THREE-DIGIT-SITE-CODE" -Class SMS_DistributionPointGroup).AddPackages($package)).ReturnValue -ne 0) { Write-host -ForegroundColor DarkRed "Possible error processing $package" } ELSE{ Write-Host -ForegroundColor GREEN "Success!" } } 

And here it is in action.

Happy Green makes me feel alright!

I hope this helped you out.  You could also distribute drivers, operating system images, updates or any other content that uses a PackageID using this same syntax.

Continue Reading...

Microsoft MVP

Five time Microsoft MVP, and now I work for the mothership


Need Help?

Get help much faster on our new dedicated Subreddit!

depicts a crowd of people in a night club with colored lights and says 'join the foxdeploy subrreddit today'


Blog Series
series_sml_IntroToDsc
series_sml_PowerShellGUI series_sml_IntroToRaspberryPi Programming series_sml_IntroToWindows Remote Management Series The Logo for System Center Configuration Manager is displayed here Depicts a road sign saying 'Learning PowerShell Autocomplete'




Blog Stats