Let’s create this window – in under 2 minutes – promise!
Before you head to the next section and discover how it’s done: PowerShell is an automation language and text based. Still, it can also serve as efficient application development language for IT tasks, and produce highly useful tools with graphical user interfaces.
At the end of this tutorial, you’ll design a service stopper tool and ship it as application. Just don’t overdo it. Large projects with concurrent tasks are better done in c#.
Creating Sample WPF Dialog Window
Getting started is the hard part, adjusting running code is way more fun. To produce the sample dialog above, in ISESteroids simply right-click any blank space in your editor. In the context menu, choose “WPF / Create Sample WPF Window”. The sample code is inserted, and you can immediately run the code.
You can understand the sample code best when you collapse all regions. Press CTRL+M.
We’ll walk you through the code next. But relax: this code gets auto-generated for you. Not just in this sample. Also when you start to create very own windows. You just need to know the basic idea.
XAML Window Definition
The beauty about WPF is that it works similar to HTML: the user interface design is done in a markup language, so you do not need any programming skills. When you expand the section “XAML Window Definition”, you see the window layout:
It has start and close tags, like <Window>…</Window>. These tags are case-sensitive because WPF is XML-based.
You also see all parts of your dialog window. We marked the spots in orange that define window texts. To tailor the dialog to your needs, just go ahead and change the orange parts to whatever you like. When done, hit F5 to run the code again, and the window reflects your changes. Adjusting WPF code is not hard at all.
How Elements are Organized
Unlike the older WinForm technology, WPF uses an invisible grid, much like an excel sheet, to place elements on the window. This is much easier and not pixel-oriented, so it works well for high resolution displays, too. Here is the grid definition:
The grid has two columns. The first column has a width of “Auto” (wide enough to fit everything in). The second column gets the remaining room.
And it has four rows. The first three are auto-sized, and the last gets the remaining room. Easy enough.
The actual user interface elements are now placed in these grid cells. Lets take a look:
There are user interface elements like “TextBlock” (text labels) and “TextBox” (input areas). They are positioned into the grid using Grid.Column and Grid.Row. Later, you will see how you can use Grid.HorizontalAlignment and Grid.VerticalAlignment to further finetune positioning.
Elements can be nested, too. The two buttons, for example, are placed into a “StackPanel”:
The “StackPanel” stacks its child elements, either horizontal or vertical, and again is placed into the master grid.
The XAML layout is just text. To turn it into a real window that you can show around, you need some code. That’s the code in the region “Code Behind”, and it looks like this:
Basically, it defines the two functions Convert-XAMLtoWindow (which takes your XAML layout and produces a window object), and Show-WPFWindow (which shows the window to the user).
Convert XAML to Window
Once you have these functions, the rest is really easy. Here is how the XAML is turned into a real window:
Take a look at the parameter -NamedElements: it lists all UI elements in your XAML that have a “Name” attribute. This way, you later can directly access these elements via $window.TxtName, for example, to find out what someone entered in a textbox.
Define Event Handlers
XAML just defines the window design. It won’t do anything else. If you want your window to respond to events, such as clicking a button, you need to add event handler code. ISESteroids will do that for you (see below). Here are the event handlers in the sample code:
Basically, the two buttons get assigned a scriptblock each. The scriptblock executes whenever the “Click” event fires. Both event handlers don’t do much. They set the property DialogResult on the window, which closes the window and sets the return value. This way, the caller knows which button was clicked.
Manipulate Window Content
We are almost ready to show the window. Maybe you’d like to preset some things in your window. This is what this part does:
It prefills the two text boxes and sets the input focus to the first text box so that the user can happily start to enter his name into it.
Showing the window at last is just a one-liner:
Note how the window in $window is submitted to Show-WPFWindow. The function returns the value set by the two button click handlers.
When the window is closed, the final part is to suck out the information from it, and use it for whatever you like. This is done in the last part:
It creates an ordered hashtable and defines two keys. Their values are defined by the “Text” property of each of the two “TextBox” input elements. The hashtable then is turned into an object and returned. This is what the result looks like:
WPF Tools in ISESteroids
When you look at the top of the XAML definition in ISESteroids, you’ll discover a couple of new clickable links:
- Edit: Opens a menu with WPF Designer Tools that help you graphically edit and design XAML
- Code Behind: Ensures your WPF code is present and accurate. If not, the code is added or adjusted.
- Events: lists the events a named UI element exposes, and adds all event handlers that you’d like to respond to
In addition, when you look at the XAML code inside ISESteroids, all UI element names are highlighted so you always know the names of elements that you can access from your code. Just make sure you assigned a name to each UI element that you want to “talk” to later.
Designing User Interfaces
While you can adjust and design your UI solely within the ISE editor, it often is much easier to do this with a graphical tool. ISESteroids ships with a special version of the free Kaxaml editor. Just click on Edit, then choose Kaxaml:
Once Kaxaml is loaded, it shows the XAML code in its lower pane, and a live preview in the upper pane. While Kaxaml is connected to ISESteroids, you will see a strong red line around your XAML. Stop working in ISESteroids, and focus on Kaxaml. All changes you do in Kaxaml are automatically synced back to ISESteroids once you close Kaxaml.
Kaxaml does not support graphical rearrangement of UI elements, but you can use its XAML editor to safely change the XAML, get IntelliSense, and also meaningful error messages when you do something wrong.
Please note that Kaxaml takes about 2-3 seconds after your last XAML change to update the visual pane. Only when the visual pane is updated will your edits be accepted. Do not close Kaxaml before the visual pane has updated, or else you might lose your last edits.
Using VisualStudio for WPF Editing
If VisualStudio is installed on your system, you can use its excellent WPF designer instead of Kaxaml. In the list above, click “VisualStudio (1-way-sync).
VisualStudio launches, creates a sample project, and all you need to do is to open the project explorer (press CTRL+ALT+L if it is not open), then double-click the file MainWindow.xaml.
- Project Explorer (Open via CTRL+ALT+L). Double-Click MainWindow.xaml to open the WPF Designer
- WPF Designer. Shows the UI design. You can use the mouse to rearrange items.
- XAML View. Synchronizes with the WPF Designer, so matter in which one of the two you make changes, the other one reflects them, too.
- Properties of selected UI element. You can change properties here, too.
- Toolbox: Click to open a list of UI elements. Drag elements from the Toolbox onto your WPF Designer view to add more UI elements
It may be a bit overwhelming at first to work with VisualStudio, yet it is very powerful. Once your window is designed, save your work, then close VisualStudio.
ISESteroids automatically picks up the changes, so you can immediately continue your work there, or run your script to test-drive the latest UI changes you applied.
Attaching to Events
On top of your XAML code inside ISESteroids, you can click “Events” to open a dialog listing all named UI elements in your XAML layout.
Let’s take the sample WPF code inserted earlier, and make sure the dialog box beeps whenever a key is pressed. Click “Events”. A dialog opens:
- Select the named element that you want to attach to. Chose the first textbox named “TxtName”
- Select the event you want to subscribe to. Choose “TextChanged”.
- Click “Insert” to create the event handler.
ISESteroids automatically adds code similar to this:
This scriptblock is executed now whenever the “TextChanged” event fires for the UI element with name “TxtName”. You can see that the even passes over some arguments, but if you just want to beep on every key press, change it like so:
When you run your code and enter text into the first textbox, Windows beeps with every key press now – provided you turned on your speakers.
Things can be much more sophisticated, though. Let’s assume you want to enable the OK button only if someone actually enters a valid email address in the second textbox. Create another event handler, this time for TxtEmail, and subscribe again to the “TextChanged” event.
When you run your code, it works! The OK button is dimmed when no valid email address is entered into the second text box – except it turns out that the regular expression used in this example isn’t very strict. This is not WPF’s fault, though. You get the idea. From within an event handler, you can access any other named UI element and manipulate it.
Powerful Data Binding
Let’s do a real thing and create a dialog that can stop services. This is what it should look like:
Here is the code – test yourself, it is pretty much the same approach as in the sample before:
The new things are:
- The XAML uses a new UI element called “ComboBox”
- The combobox is filled with the results of a PowerShell command. It’s ridiculously easy to fill WPF elements this way – just tell them where their “ItemsSource” is.
- The combobox can display any given property found in the objects you filled them with. Use “DisplayMemberPath” to specify the property.
- The event handler for the OK button does not close the window. Instead, it performs some action (stops a service), then updates the combobox
The result is a quick and dirty yet powerful tool that can be used to stop services. With the same approach, you could have it restart services. You could limit the number of services before you make them available in the combobox. Or you could show disabled Active Directory users instead, and make someone unlock them.
Just remember: in the code above, we deliberately turned off the stop-service functionality with the parameter -whatIf. You need to remove this parameter from your code to actually stop services. Be careful! Some services don’t like to be stopped.
Creating a PowerShell Application (EXE)
To actually pass on your tool to someone else, you could decide to make it an application first. It’s dead simple. Just choose the menu “Tools / Turn Code into EXE”. A dialog opens. Here is what to choose:
- Make sure the PowerShell console is hidden. You just created a UI, so you don’t need the console anymore (except if you want to use it to output results of course)
- Select some icon for your application. That’s optional, but you could go to the windows folder and search for some *.ico files just for the fun of it
- Require Administrator privileges. Your tool needs them. A regular user cannot stop services.
- Click OK, and choose where to save your EXE file.
When you launch your newly created application via double-click, Windows asks for elevation (because you required Administrator privileges). Next, your window pops up and shows the list of running services, and the option to stop some.