Display WPF XAML code in PowerShell

Last week I went to the Minnesota Management Summit at the Mall of America #MMSMOA, and I got inspired to work on a few projects in my backlog.

One of the presentations I went to was with Ryan Ephgrave (@EphingPosh on Twitter.com), and his talk on “Better Know a PowerShell UI“.

Overall it was a great presentation, and I learned a lot. And got me thinking about some of the things I could do with a framework I started earlier in the year but never got around to finishing.

WPF4PS

Without further adieu, I present Windows Presentation Framework for PowerShell (WPF4PS). It is also the first project I’ve released as source code on GitHub:

https://github.com/keithga/WPF4PS

Background

Most WPF + PowerShell examples are created with a lot of custom code to add in event handlers for the User Interface elements. The goal is to find all control elements on the page and if there is a pre-defined function created, then use it. Which means minimal code for overhead.

Example

Here is a fully functional example:

  • Load the WPF4PS module
  • Import a XAML defined in Visual Studio
  • Create a scriptBlock to handle the button Click
  • Create a HashTable to pass data between our script that the XAML Window
  • Call the Show-XAMLWindow function
  • Get the value of the TextBox from the Hash

wpf4ps

<#
.SYNOPSIS
WPF4PS framework Examples

.DESCRIPTION
Simple Example

.NOTES
Copyright Keith Garner, All rights reserved.

#>

[cmdletbinding()]
param()

import-module $PSScriptRoot\wpf4ps -force

$MyXAML = @"
<Window x:Class="WpfApplication1.MainWindow"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 xmlns:local="clr-namespace:WpfApplication1"
 mc:Ignorable="d"
 Title="MainWindow" FontFamily="Segoe WP Semibold" Width="400" Height="300" Name="WindowMain" >
 <Grid>
 <Label>Hello World</Label>
 <Button x:Name="Button1" Content="Big Red Button" Width="125" Height="25" Background="#FFDD0000" Margin="0,60,0,0"/>
 <TextBox x:Name="textBox1" Height="23" Width="200" />
 </Grid>
</Window>
"@

$MyControl = [scriptBlock]{

    function global:button1_click()
    {
        "Click the Big Red Button`n" + $TextBox1.TExt  | show-MessageBox 
        $WindowMain.Close()
    }

}

$MyHash = [Hashtable]::Synchronized(@{ textBox1 = "Hello World" })

Show-XAMLWindow -XAML $MyXAML -ControlScripts $MyControl -SyncHash $MyHash

$MyHash.TextBox1 | Write-Host

Next

My goal is to work out the kinks and eventually upload/share this on PowerShellGallery.com.

For example:

  • I created two Show-XAMLWindow() functions in the library, one inline and another Async. I still don’t know what the usage case of Async is.
  • Ryan Ephgrave did some XAML + Powershell examples in his “Better Know a PowerShell UI” blog series with XAML “Binding” elements, something I have not used in the past, so I excluded them from this package.
  • I had to do some weirdness with the declaring the functions above as “global” to make them visible to the Module

If you have feedback on the layout or usage, please let me know.

-k

Fix for Windows 1511 ADK bug

First off, yes, I have a new job working for 1e! I’m super excited, and I should have posted something about it, but I’ve been super busy. My first day on the job was at a customer site in Dallas, and I’ve been on the go ever since, working on this and that (stay tuned :^).

As many of you may have known, there has been a pretty big bug in the Windows 10 Version 1511 ADK, it’s caused all kinds of interop problems with Configuration Manager. Well Microsoft released a fix today! KB3143760. Yea!

Well I opened up KB3143760, and yikes! The instructions are a bit dry. Mount this, patch that, watch out for the data streams!

I needed to patch my local Windows 1511 ADK installation because I’m working on a SCCM+MDT Refresh scenario, and I don’t want to uninstall the 1511 ADK. Perfect timing, if only there was a way to automate this..

Repair-1511ADK.ps1

Here is a link to a PowerShell script I wrote to auto-magically patch your WinPE files!

https://onedrive.live.com/redir?resid=5407B03614346A99!158500&authkey=!AHWArN5C7FyRPIY&ithint=file%2cps1

This script will:

  • Download the patch (no need to go through the E-Mail process)
  • Take care of all the stream issues (really I don’t use IE/Edge, so no security streams)
  • Auto extract the patch contents
  • Mount the wim file
  • Patch the appropriate dat files
  • Fix the permissions
  • Dismounts the WIM
  • Cleans up all left over files

So, for example, if you wanted to patch all of the WinPE Wim files in the ADK directory (before importing them into SCCM), you can run the following command:

get-childitem 'C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\*.wim' -recurse | .\Repair-1511ADK.ps1 -verbose

Lately, when programming in PowerShell, I have taken the “write-host considered harmful” rule to heart, so by default, there is *NO* std console output. Instead, I redirect most information output to “verbose”, so if you want to see what is happening in the background, use the -verbose switch.

-k

Hopefully, moving forwards, this will be the *last* time I place a new script up on OneDrive, really I should be moving towards something more… modern… like GitHub.

MDT package now on Chocolatey.org ready for Windows 10!

Been a while since I posted, I’ve been busy with Surface, Windows 10, and other Kits. But my chocolatey package just got approved, so I thought I would share.

I’ve been following the progress of PowerShell’s OneGet, and http://Chocolatey.org for a while now, and thought it was time to stick my toes in and create a package for public use. MDT seemed like a great start.

As you may already know OneGet is a new feature of PowerShell, included in Windows 10 and available through WMF 5.0 that allows for the installation of packages over the internet. Chocolatey is one of the back-end providers, with a great collection of apps ready for installation.

With the recent release of MDT 2013 Update 2, it seemed like a great opportunity to practice my packaging skills. Eventually I created a PowerShell script to auto generate the chocolatey package (not shown here), it would download the MSI files, and extract out the MSI Product Code and Checksum values. You can see the code generated on the Chocolatey MDT page.

Now to install MDT on Windows 10 (or Windows Server 2016), we can run the commands:

set-executionpolicy RemoteSigned; 
Install-Package -Name MDT -ProviderName Chocolatey `
-ForceBootstrap -Force -Verbose

How it works

First step we need to do on clean machine is to set the execution policy:

set-executionpolicy RemoteSigned

Chocolatey has some PowerShell scripts that run in the background, so we need to allow PowerShell to run these commands with the Set-ExecutionPolicy command. Most Powershell users run this command anyways, so it’s not that uncommon.

Then we install the package using the PowerShell 5.0 “Install-Package” cmdlet built into Windows 10:

Install-Package -Name MDT -ProviderName Chocolatey

We must specify the “-ProviderName Chocolatey” parameter the fist time we call Install-Package so the chocolatey Provider is installed, MDT is only known to Chocolatey at this time.

Install-Package will prompt us to confirm installation of the chocolatey provider, we can skip this with the -ForceBootStrap parameter. Additionally, Install-Package will also ask for confirmation before installing MDT, and we can sip the confirmation with the -Force Paramater.

I like to see what is going on the background, so I add the -verbose parameter, and my screen fills with yellow:

Capture

We can see Install-Package downloading MicrosoftDeploymentToolkit2013_x64.msi from the Microsoft web servers.

ADK

The Windows 10 ADK package has also been uploaded to Chocolatey, but hasn’t been officially approved yet, so when you try to run the “windows-ADK” package it will install the older Windows 8.1 version. We can force the Windows 10 ADK to install with a version parameter. Additionally, the default version of the “Windows-ADK” package does not install USMT, so to install everything we will need the “windows-adk-all” package (which is a lot of stuff, sorry).

install-package -ProviderName Chocolatey -Name Windows-ADK-All `
-force -Verbose -MinimumVersion 10.1.10586.0

More information:

https://chocolatey.org/packages/MDT

-k

Deployment Gotcha – Get Windows 10 App doesn’t work with MDT

Did you know that you can download *.iso images of Windows 10 using the Get Windows 10 app?

http://www.microsoft.com/en-us/software-download/windows10

It’s a tool that will allow you to download *.iso images for deployment.

The only problem is that it doesn’t actually download *.iso images, instead, it downloads *.esd images, which are highly compressed *.wim files, that are encrypted/encoded. The tool then decrypts/decodes the *.esd file into *.wim files, and constructs a *.iso image for use.

Additionally, the *.wim file is still a highly compressed *.esd file, so legacy tools that leverage the WIMGAPI library like imagex.exe don’t understand it.  Dism works fine.

C:\>"c:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\DISM\imagex.exe" /info g:\getwin10\Windows\sources\install.wim
ImageX Tool for Windows
 Copyright (C) Microsoft Corp. All rights reserved.
 Version: 10.0.10011.16384

Error opening file [g:\getwin10\Windows\sources\install.wim].

An attempt was made to load a program with an incorrect format.
C:\>dism /get-wiminfo /wimfile:g:\getwin10\Windows\sources\install.wim

Deployment Image Servicing and Management tool
 Version: 6.3.9600.17031

Details for image : g:\getwin10\Windows\sources\install.wim
 Index : 1
 Name : Windows 10 Pro
 Description : Windows 10 Pro
 Size : 9,343,966,034 bytes

The operation completed successfully.

That means that you can’t import the images into MDT, because MDT uses the WIMGAPI libarary, and powershell commands might not work either.

I tried to export the *.wim file to another *.wim file, but DISM.exe doesn’t like doing that either.

As a work around you might be able to export the *.wim file to a *.vhd container, and re-capture back to *.wim file with normal compression.

Johan has been documenting esd to wim techniques on his blog.

http://deploymentresearch.com/Research/Post/399/How-to-REALLY-create-a-Windows-10-ISO-no-3rd-party-tools-needed

Otherwise, I hope the DISM team fixes this for TH2 :^) <hint> <hint>

 

 

MDT 2013 UberBug01 – MDAC and the Fast Machine

Well MDT 2013 Update 1 is out. Yea!

Time to test and evaluate to see if there are any regressions in my test and environment.

Wait… Something went wrong…

dism

Fast System

As I mentioned in an earlier blog post, I recently purchased a super fast Intel 750 SSD to make my MDT Build machine run faster. Blazing Fast

WP_20150507_19_51_57_Pro

You might think: “Wow, that’s super cool, everything would be so much better with a faster machine”

Essentially, yes, except when it’s faster than the Operating System can handle.  :^(

The Bug

When updating a deployment share you may get the following error message:

Deployment Image Servicing and Management tool
Version: 10.0.10240.16384
 
Image Version: 10.0.10240.16384
 
Processing 1 of 1 - Adding package WinPE-MDAC-Package~31bf3856ad364e35~amd64~~10.0.10240.16384
 
Error: 1726
 
The remote procedure call failed.
An error occurred closing a servicing component in the image.
Wait a few minutes and try running the command again.
 

Dism.log shows nothing interesting:

 
2015-07-15 13:55:00, Error                 DISM   DISM.EXE: DISM Package Manager processed the command line but failed. HRESULT=800706BE
2015-07-15 13:55:00, Error                 DISM   DISM Manager: PID=2364 TID=2424 Failed to get the IDismImage instance from the image session - CDISMManager::CloseImageSession(hr:0x800706ba)
2015-07-15 13:55:00, Error                 DISM   DISM.EXE:  - CDismWrapper::CloseSession(hr:0x800706ba)

I asked someone knowledgeable at Microsoft (MNiehaus), and he mentioned that he saw it a couple of times, but couldn’t repro it consistently. However, I could easily reproduce the problem on demand with my hydration/buildout scripts.

Turns out that there is a narrow case where this bug manifests:

  • If you add any optional components to WinPE within MDT
  • If you have a fast hard disk (like my Intel 750 SSD)
  • If you have <UseBootWim> defined in you settings.xml, it may get worse.

The fast disk is most likely why the Windows Product Group teams never saw this bug in testing.

Well, I provided a repro environment to the Windows Product Groups involved in this component, even letting them log into my machine to reproduce the issue.

Good news is that they were able to determine what the root cause is ( timing related during unload of various components ), and even provided me with a private fix for testing! The private passed!

Now the real fun begins, there is a legitimate challenge here, because the error exists in the Windows 10 Servicing Stack, and that stack is embedded *into* WinPE.wim on the ADK and Boot.wim on the OS Install disk.

How do you update these files with the updated servicing stack, it’s not a trivial matter. They could send out a KB QFE Fix, and let customers manually update the files manually with dism.exe, they could also repackage/rerelease the ADK Itself, or worst case wait till the next release of the Windows OS ISO images.

I have been monitoring status, and there are several team members working on the release issues, and even someone from Customer Support acting as a customer advocate. My work is done.

Work Around

In the mean time, you can work around the issue:

  • Removing optional components from MDT. :^(
  • Of course, you move to a machine with a slower disk.
  • I had some luck getting optional components added when I set <UseBootWim> to false in the settings.xml file.
  • Additionally, Johan has mentioned that he can get it to pass if the OS running MDT is Windows 10 ( I was running Windows Server 2012 R2 ).

For me, it was easy, I don’t use the MDAC components in my environment, so I just removed them from the settings.xml file. Lame, I know.

-k

More Deployment bugs to follow!

Updated Dell Driver Catalog Script for Windows 10

Woot!

Schema

Dell has updated the Schema on their DriverPackageCatalog.xml to include full SMBIOS Make and Model information for their systems!

I updated the Install-DellDriverCatalog.ps1 script to take advantage of the new metadata and tried importing drivers for my trusty Dell Venue 8 Pro.  As you may recall, in previous versions of the DriverPackageCatalog.xml file, the Dell Venue 8 Pro had a weird 5830 number for the Model, which didn’t match what was in the Firmware.

Anyways, I tried importing into MDT, and got the following…

DellModelVenue

Looks Great!!

WinPE

Additionally, with the addition of the Windows 10 ADK, I have updated the script to support this platform, and other changes

mdt selection profiles

Scripts:

Install-DellDriverCatalog.ps1

Install-DellWinPEDriverCatalog.ps1

 

Thanks to @WarrenByle for putting up with my pestering :^) Great stuff from dell.

Updated Dell Driver Catalog script

So I provided feedback to Dell last year about the schema on their DriverPackCatalog.xml file. I wanted to tie the Make & Model information from XML file directly with the SMBIOS data returned in WMI queries like Win32_ComputerSystemProduct. Right now Dell provides some model information in the XML:

<Brand key=90 prefix=TABLET>
<Display lang=en><![CDATA[ Tablet ]]></Display>
   <Model systemID=0630>
      <Display lang=en><![CDATA[ 5830 ]]></Display>
   </Model>
</Brand>

But how to cross reference that with my Dell Venue 8 Pro:

PS C:\> Get-WMIObject Win32_ComputerSystemProduct

IdentifyingNumber : 123QWER
Name              : Venue 8 Pro 5830
Vendor            : DellInc.
Version           : Not Specified
Caption           : Computer System Product

I could try to do some sub-string matching, but I can’t seem to come up with the ideal pattern matching system, in addition, I want to support Johan’s Total-Control system, and if Dell doesn’t support the full Name “Venue 8 Pro” out of the “Venue 8 Pro 5830” I can’t construct the correct folder name.

Request: I would like Dell to supply the *FULL* SMBios name for each platform in the DriverPackCatalog.xml file.

Well, Dell went and updated the schema, but instead of adding full Model strings for the SupportedSystems, they modified the schema in ways that broke some other things in my scripts. My scripts have been hopelessly out of date and broken for some time. :^(

Updated Scripts

I updated the Install-DellWinPEDriverCatalog.ps1 file to match the new Dell Schema.

Fair warning, I don’t have enough Dell machines to do proper testing, but from what I can tell it was able to import WinPE and Some Latitude drivers into my test MDT environment.

Dell

(perhaps Dell can send me a new Precision Workstation so I can do proper testing ;^)

Updated Scripts:

Install-DellDriverCatalog.ps1

Install-DellWinPEDriverCatalog.ps1