Using .NET Event Handlers in a PowerShell GUI

GUI development tools, such as PowerShellStudio, make it very easy to manage events for controls on our winforms.

Once the control is on the form, and we select it, click on the Events button (the lightning symbol), the Properties panel gives us a list of the events available for us to manage. However, events are not just restricted to controls. There’s a world of other events out there that we can use to interact with our winforms projects.

In this article, we’ll create a forms project that downloads the latest 64 bit antimalware definitions from Microsoft and updates a progress control to show how far the download is to completion, using methods and events from a .NET class.

Updates to the latest antimalware definitions can be obtained through http://go.microsoft.com/fwlink/?LinkID=87341&clcid=0x409 and a look through MSDN shows us that we can use the .NET WebClient class to carry out downloads programmatically.

To start this process, create a new forms project, and drag a progress bar, label, and button onto the form. Then set the properties of the controls as below. Note that properties with text controls will automatically be named for you if you set the text property first.

Label
Text : Progress
Name : labelProgress

Button
Text : Download
Name : buttonDownload

Progress Bar
Name : progressbarDownload

Here’s how my form looks.

Blog - Adding Events - Form Design

Once this is complete, we can begin writing the event code.

In our forms Load event, we create an instance of the System.Net.Webclient class. This is assigned to the script level variable, $webclient. This scope is required in order for the other parts of the solution to be able to process the object and its events.

The next two lines add event handlers for the DownloadProgressChanged and DownloadFileCompleted events. DownloadProgressChanged indicates a change in the state of the transfer with regards to the amount of content downloaded, whilst DownloadFileCompleted is fired on the completion of a download. The scriptblocks for these are $webclient_DownloadProgressChanged and $webclient_DownloadFileCompleted respectively.

The event handler for updating the progress of the download is written next:

To make it easier to read, $progressInfo is used for the rest of the code instead of $_. The variable contains the values given to us by the System.Net.DownloadProgressChangedEventArgs class instance that is passed into the handler.

The DownloadProgressChangedEventArgs class contains ProgressPercentage, BytesReceived, and TotalBytesToReceive properties. We use these for changing the progress meter value property, and also updating the text in the label below to show bytes received and the total size of the download.

The event handler for DownLoadFileCompleted is next:

When DownloadFileCompleted is fired, the label text is changed to indicate the download’s completion.

Lastly, the download button’s Click event is set to begin an asynchronous download of the antimalware definition.

Blog - Adding Events - Code

Our project code

And when we run the project and click on Download! We see this in action, with the progress bar being updated and the progress text below it also, using the code we wrote earlier.

Blog - Adding Events - Downloader Running

The downloader in action

This same methodology can be employed for using .NET events, creating an instance of the object, adding the event handler definition, and then the scriptblock code to be used.

You can find exported project code and the project files at my repository on GitHub, and a short video of the project in action on the powershell.amsterdam YouTube channel.

 

Share

Copying files to and from remote sessions

Those of you running Windows 10 or Server vNext (I’ve yet check WMF 5.0 RTM on other operating systems after it was pulled by Microsoft from DownloadCenter), may have missed the inclusion of new parameters for Copy-Item, which allow to copying of files to a remote session and from a remote session. These are names ToSession and FromSession respectively.

Oddly, Microsoft do not appear to have updated their help to provide information on this. You’ll only notice it if you use Get-Command or alternatively tab through Copy-Item.

What’s nice is that PowerShell 5 is not required to be installed on the system for which we have created a remote session.

Usage is simply a case of providing a valid value of PSSession type to the ToSession or FromSession parameters, in addition to your standard Path and Destination parameters.

Examples are below :

Copy Remote Sessions

Unfortunately at present, FromSession and ToSession are mutually exclusive, preventing the possibility of being able to directly copy from one remote session to another.

Share

Removing Items from Lists Using the Keyboard

In an earlier post, we created a form with two listgridview controls, and used both add and remove buttons, and double click functionality to allow an item to move an item from one control to another in an intuitive manner.

Todays post shows how we can use a remove items from a list by pressing a key. Specifically, we’ll be using the DELETE key for removing items. This will be carried out in Sapien’s PowerShell Studio 2015, but the same methodology applies to however you generate winforms in PowerShell.

For initial setup, carry out the following :

  • create a new form with a header and several items.
  • create a listview control called $lstControl
  • populate the control with a header
  • add some items to the listview control

Sample form and control layout

 

  • select the control
  • select Events in the properties pane
  • double click on KeyDown
  • Insert the following code :

The KeyDown event’s code

 

Go ahead and test it, adding an item to the control on the right hand side, selecting it, and then pressing the DELETE key.

Also, because the code loops through each selected item in the control, we can also use standard multiple selection functionality offered by the various use of the SHIFT and CTRL combinations.

Two items are selected using a click SHIFT combination

The DELETe key is pressed, and the previous selected items are removed from the list

You can find the files, if you are using PowerShell Studio 2015, or exported .ps1 file at my gitlab repository.

Additionally, there’s a (basic) video of this code in action at my channel on You Tube.

Thanks for reading, and feel free to provide feedback.

cheers,

Tim

Share

Using Double Click for Adding and Removing Items from Lists

Double click functionality for movement of items between listboxes is commonly used within Windows, and quite intuitive. This article shows how we can implement this in our own forms based projects. We’ll use this example with ListView, but it is also applicable to ListBoxes (ListView controls inherit from ListBoxes).

For initial setup of this project, follow the steps below, using your preferred GUI editor or code.

  • Create a new forms project
  • Change the form’s control name and text if desired (called AddServers and Double Click Demo in this article)
  • Add two ListView controls, with names of lstFrom, and lstTo
  • Add two Button controls, with names of btnAdd, and btnRemove
  • (optional) Set the Text property of the form

lstFrom

  • Add a column to the form
    • Name : columnComputernameFrom
    • Sorting : Ascending
    • Text : Computername
    • View : Details
    • Add the following items to lstFrom , with Text values of Computer1, Computer2, Computer3, and Computer4

lstTo

  • Add a column to the form
    • Name : columnComputernameFrom
    • Text : Computername
    • View : Details
    • Sorting : Ascending

Buttons
Set the name of the top button to btnAdd, and the Text property to >
Set the name of the bottom button to btnRemove, and the Text property to <

Arrange the controls to look something like the picture below :

Our form design

Our form design

Once this is complete, we’re going to start adding some features.

Add/Remove Buttons

This could be described as the ‘classic’ method of adding and removing items from lists, with arrows pointing in alternative directions to indicate the addition or removal of an item from one listbox to another.

In the Load event, we’ll set the arrow buttons Enabled property to $false, since no items are selected.

Let’s activate or deactive the add and remove buttons depending on whether the appropriate listboxes are populated, and additionally disable the appropriate button when an item is selected. There’s no point of the add button being enabled when we have selected an item from the To listgridview for example.

Now we add the code for the button events, adding to removing from the appropriate listgridview. We use the FindItemWithText method to verify that the item does not already exist there, preventing duplications.

Now go ahead and run it. Select double click on an item on the left hand column, and it will add it to the right one, and versa.

Double Click - Running 1

Double click on one of the items

Double Click - Running 2

…..and it is moved to the other side

 

The mechanisms that double click provides for list also be used on other controls. For example, double clicking on an item in a list which automatically populates a textbox with the value that has been selected in the list.

You can find a copy of the PowerShell Studio .psf form file, and also an exported .ps1 of the same for at my repository on GitHub.

A video of this is also available on the PowerShell.Amsterdam YouTube channel.

Thanks for reading, and please provide feedback if you have comments, questions, or have noticed any errors in this article.

cheers,

Tim

Share

PowerShell and GitLab CI – Part 5

Introduction

During the last article in this series on the use of PowerShell with GitLab, we noticed some displays on the build console, and some results from our build that was a bit unusual.

Today, I’m going to look a bit further into how the build engine works, which will also explain some of these results we are seeing.

How GitLab CI Runner Works

It would be logical to think that the PowerShell code is run in the same location or a subdirectory of the folder where the service file is, similar to Jenkins, but after a bit of investigation, I found out this is not the case.

To look further into what was happening, let’s add a line to the script section of the YAML file, and put a Start-Sleep command in.Make it ten minutes, to give enough time to remote onto the GitLab CI Runner, and do a search for our .ps1 file stored in a subdirectory of the repository.

Use the content below for our build file.

  • Save the changes
  • Add the updated file
  • Commit the changes
  • Push the changes
  • Navigate to the build section
  • Click on the commit

The job is running, and because of the Start-Sleep command, will continue to do so for the next ten minutes.

Part 5 - GitLab Job Running

Discoveries

  • Remote onto your build server (if it is not already the same system you are accessing GitLab from.
  • Go to the C:\Windows\Temp

There will be a folder name of the format Build_xxxxPart 5 - Temp Dir

  • Double click on the folder

Part 5 - Build Script Contents Dir

  • Within this folder is a script.ps1 file.
  • Open the file

Part 5 - The Script Code

The PowerShell code contained within the script: section of the YAML file is adjusted to make it suitable for returning the output we can see on the console window within a Gitlab job.

Looking at the code now, we can see that it has been changed significantly :

  • ErrorActionPreference has been set to ‘Stop‘.
  • Commands are in place to check to see if an error has occured, and if so to exit the script.  This will also result in the job being flagged as having failed.
  • Probably the most interesting of the changes is the frequent use of Echo command which mimics the command that follows it.

This explains several things to us :

  • How the console output is seen on the job screen
  • Some lines output appeared strange because variables were undefined at the stage when the Echo command ran

Because PowerShell returns all output from a function, it explains why were receive an array when the HappyHelloWorld function is called. It consists of the intented output, but also the Echo commands.

The use of a function in our build code now becomes a challenge or possibly could be perceived as something to be avoided, since we cannot guarantee the element in the array that will contain our desired output.  One way i’ve been able to get round this is to make the function return a PScustomobject, and make use of the -is operator outside of the function to obtain the value.

e.g. $functionOutput = $arrayReturned | Where {$PSItem -is [pscustomobject]}

However, I’ve found a better approach is to minimize the actual PowerShell commands that you use in the script, and instead create a Build folder within your repository which contains files with the actual commands that you wish to use for the build. These can be dotsourced to make them available from within the script, without the need for adding custom code to handle this.

There are many other aspects and configuration settings possible within GitLab, which lets you have powerful control over your build steps. Examples of this are defining the order of execution, ignoring errors, and setting the steps to be taken after each one.

It’s also worthwhile noting that these articles do not include the use of testing, which should be part of your chain of operations. If you are not already familiar with the use of Pester, I’d recommend taking a look at the documentation and examples on GitLab. Amongst others, Jakub Jareš has also written an excellent series of articles on its use, which you can find on PowerShellMagazine.com

That’s it for this series of articles on the use of PowerShell and GitLab. Thanks for reading, and feel free to provide feedback.

cheers,

Tim

Share