Building Power Shell GUIs Taking your scripting to
Building Power. Shell GUIs Taking your scripting to the next level Nathan Ziehnert 08/23/2019
Experience? • Who has written a script for some repeatable process? • Who has written a script that requires parameters? • Who has designed a GUI for a Power. Shell Script? • Who is familiar with Win. Forms? • Who is familiar with WPF?
Why Create a GUI? • Part of your skill progression • Empowering your coworkers • Let someone else drive so that you don't have to
In Order To Learn How To Program. . . • Common ‘First-GUI’ Ideas • • Password Resets Provision new users Babysitting tasks Setting a computer name and OU in an OSD Task Sequence
Example UI
By The End Of This Session
Basics of WPF
WPF Overview • Windows Presentation Framework • UI Framework • "You write the markup, I write the code" – Your Complier • Advantages over Win. Forms • Look and Feel • Layouts • Community Themes/Controls • Damien Van Robaeys (@syst_and_deploy) | http: //www. systanddeploy. com/ • Jérôme Bezet-Torres (@JM 2 K 69) | http: //jm 2 k 69. github. io/ • Animations! • FREE TOOLS!!!
Creating WPF Dialogs in Power. Shell Using Objects aka straight Power. Shell. . . aka the “Sapien” Win. Forms method. . .
ABOUT MENU
Structuring Your Power. Shell • Add the Framework(s)
Add The Framework(s) ## Presentation. Framework / Presentation. Framework. dll contains all of the WPF controls ## that are necessary to build our GUI. Add-Type -Assembly. Name Presentation. Framework ## You may SOMETIMES see the following referenced in other Power. Shell scripts. These ## should never be required to create WPF GUIs with objects in Power. Shell, and also ## shouldn't be required if you're using the XAML method either. Add-Type -Assembly. Name Presentation. Core Add-Type -Assembly. Name Windows. Base
Structuring Your Power. Shell • Add the Frameworks • Create Your Objects (Window, Buttons, Labels, Grids, You Get the Picture)
Create Your Objects $Window = New-Object System. Windows. Window $Window. Height = 600 $Window. Width = 400 $Window. Title = "Big Surprise" $Window. Resize. Mode = "No. Resize" $Stack. Panel = New-Object System. Windows. Controls. Stack. Panel $Surprise = New-Object System. Windows. Controls. Image $Surprise. Source = "$PSScript. Root╲xx-Surprise. jpg" $Surprise. Visibility = "Hidden" $Surprise. Height = 500 $Button = New-Object System. Windows. Controls. Button $Button. Content = "How you doin? " $Button. Height = 50 $Button. Width = 100
Structuring Your Power. Shell • Add the Frameworks • Create Your Objects (Window, Buttons, Labels, Grids, You Get the Picture) • Add Your Child Objects to Their Parent
Add Your Children ## Parent objects accept a couple different ways to add content depending on which ## control the parent object is. These include: ## - $Object. Content = $Child ## - $Object. Add. Child($Child) $Stack. Panel. Add. Child($Surprise) $Stack. Panel. Add. Child($Button) $Window. Content = $Stack. Panel
Structuring Your Power. Shell • Add the Frameworks • Create Your Objects (Window, Buttons, Labels, Grids, You Get the Picture) • Add Your Child Objects to Their Parent • Add Your Events
Add Your Events ## ## ## Events are added by getting the name of the event and prepending "Add_" to it. - $Object. Add_Click({event script block}) You can get the list of available events by creating the object in Power. Shell and then running the Get-Member cmdlet against it: - $Object | Get-Member. Type Event $Button. Add_Click( { $Surprise. Visibility = "Visible" } )
Structuring Your Power. Shell • Add the Frameworks • Create Your Objects (Window, Buttons, Labels, Grids, You Get the Picture) • Add Your Child Objects to Their Parent • Add Your Events • Show the Dialog
Show Your Dialog ## By prepending "$null =" to our Show. Dialog() method we won’t get the Boolean output ## of the Show. Dialog() method. $null = $Window. Show. Dialog()
Straight Power. Shell. No Chaser.
Pro Et Contra Pros Cons • Familiar language (if you used to • No WYSIWYG Editors that will generate the object code (AFAIK) build GUIs with Sapien or a similar WYSIWYG editor) • Requires an existing knowledge of WPF controls and their attributes • It’s good to learn your roots • Responsive GUIs are much harder to create (as if they weren't hard enough already) • Complex GUIs are hard to design and super verbose • Lots of lines of code very quickly
Creating WPF Dialogs in Power. Shell Using XAML
XAML Structure • e. Xtensible Application Markup Language • It's like XML. • Really though. . . It's XML. • Parent/Child relationship with properties • XAML executes no code (no Power. Shell, no C#, etc) – it's a "markup" language • How do we present this data vs how do we generate/format the data
Creating XAML Drag and Drop for that processed factory farm feel Hand-Coded for that free-range organic feel
Good Layout Hygiene • Direct Drag and Drop (i. e. no supporting Grid layout or Stack. Panel)
Good Mediocre Layout Hygiene • Direct Drag and Drop • Leads to element positioning defined by pixel in margin attribute (i. e. there isn't really an "absolute" positioning attribute in WPF)
Creating XAML
Good Mediocre Layout Hygiene • Direct Drag and Drop • Leads to element positioning defined by pixel in margin attribute (i. e. there isn't really an "absolute" positioning attribute in WPF) • Does not scale well • Issues arise when you nest elements like Stack. Panels in Grids (Visual Studio ends up placing them in the parent element) • Simple UIs – All Day Long • Complex UIs – Learn to read XAML
Good Layout Hygiene • Grids • Similar to HTML tables • Row/Column sizes defined in three formats: • Proportional Division (Star/*) • Pixels • Automatic sizing based on content • Stack. Panel • Kind of like "Automatic Tables" • Elements/Controls "stack" horizontally/vertically
Making a WPF UI - Flow • Design your User Interface in Visual Studio • Copy XAML • Paste XAML into new file • Load Parse XAML • Write Event Handlers • Give to end users to run • Get bonus at next review. . .
The XAML Way.
Stylizing WPF Dialogs Making your GUIs pretty.
Options • "You can GO YOUR OWN WAY! (go your own waaaaay)" • Visual Studio Blend • Use a community theme / control. Examples include: • Mah. Apps. Metro • Material Design
Community Themes • Download / collect the appropriate resource libraries (DLLs) • Nu. Get + 7 -Zip • Visual Studio • Design GUI based on theme • Add resources references to XAML via resource dictionary • In some cases you may need to modify the XAML elements (Window) • *cough* Mah. Apps *cough* • Controls might be named differently (or maybe they're entirely new) • Import DLL(s) in Power. Shell script
Downloading Community Themes • Download / collect the appropriate resource libraries (DLLs) • IANAL!!! Review the license agreements with your legal team. • Nu. Get. org • Doesn't require you to install Visual Studio CE. . . • Extract and review *. nuspec file for dependency chaining • Visual Studio Community • Review the licensing with your legal team. . . • Create a basic WPF application and use the Nu. Get package manager • Resources Here: "Solution. Root╲packages" • Make note of required. NET version
Adding Community Themes • Design GUI based on theme/control • Rely on the documentation for theme/control • Rely on those who have gone before you. . . Bing it.
Importing Community Themes • Import DLL(s) in Power. Shell script • Add-Type –Path "path╲to╲resource. dll"
Rely On Those Who Have Gone Before You • Mah. Apps. Metro • http: //www. systanddeploy. com/2016/01/powershell-gui-add-mahappsmetro-theme. html • Material Design • https: //jm 2 k 69. github. io/2018 -10 -09 -How-to-use-Material-Desgin-with. Power. Shell/
Pretty!
Interacting with an OSD TS Because who doesn't want to roll their own Task Sequence GUI?
Task Sequence Interaction • WPF issues with Win. PE 1809 • With Win. PE 1809 from the ADK, two DLLs were missing • FIX: "Copy BCP 47*. dll from Windows╲System 32 of a Windows 10 x 64 1809 and add them to your Win. PE Extra Files to be copied to <Win. PE>: ╲Windows╲System 32 or add these files in Offline Servicing. " • https: //www. osdeploy. com/blog/winpe-10 -1809 -wpf-drama
Task Sequence Interaction • Getting / Setting Variables • Add the Microsoft SMS TSEnvironment COMObject • $ts. Env = New-Object -COMObject Microsoft. SMS. TSEnvironment • Get a Variable • $ts. Env. Value("Variable. Name") • Set a Variable • $ts. Env. Value("Variable. Name") = "New Value" • Example: Access the value of a textblock to set as the value • $ts. Env. Value("OSDComputer. Name") = $Text. Box. Text • Cannot set read only variables (Generally start with an _)
Task Sequence Interaction • Hiding the Progress UI • Add the Microsoft SMS TSProgress. UI COMObject • $ts. Prog = New-Object -COMObject Microsoft. SMS. TSProgress. UI • Hide the Dialog • $ts. Prog. Close. Progress. Dialog() • The Progress UI will reopen when the next step of the task sequence executes
Let's Test it in a TS
Getting the Dialog To Show In Explorer • Service. UI. exe • Somewhat confusing command line Service. UI. exe -process: tsprogressui. exe "c: WindowsSystem 32Windows. Powershellv 1. 0powershell. exe" -Execution. Policy Bypass -Window. Style Hidden -File "User. Notification. ps 1" -Settings. File "Settings. ini"
Building Responsive GUIs
Unresponsive Example
The Problem of Threads • Your WPF script runs in two threads. . . but really, it's one thread • UI Thread (the script, and the UI including "painting" and actions) • Render Thread (the rendering of the GUI)
The Problem of Threads • Button in UI thread • We add a Script. Block to the Button control • UI Thread now locked • Until the ENTIRE script block completes • UI Thread cannot process repaints • Once Script. Block completes, UI Thread can once again repaint
The Problem of Threads
The Solution!
Multi-Threading • Leave the UI THREAD ALONE
Multi-Threading • Leave the UI THREAD ALONE • Let it do what it's good at – • Responding to the user • Painting the GUI • Create a new thread to do some heavy lifting!
Multi-Threading • How?
Looking at some code. . .
Use a Framework • Po. SHPF (Power. Shell Presentation Framework) • Start-Background. Script. Block • $Sync. Class. Update. Element("Object", "Property", "Value") • Makes use of Runspaces and cleans up runspaces when complete
Responsive Example
Resources / Links • Power. Shell Presentation Framework • https: //github. com/theznerd/Po. SHPF • Power. Shell Blog Series on WPF • https: //z-nerd. com/blog/2019/05/27 -posh-presentation-framework-part 1/
Special Thanks To Our Sponsors!
- Slides: 61