Unable to Import MahApps.Metro DLL Files using PowerShell in SCCM/MDT Boot Image

I’ve been working on converting some of my PowerShell scripts for SCCM into Graphical User Interfaces (GUIs), specifically using Windows Presentation Foundation (WPF). I’ve been a long admirer of the ConfigMgr OSD Front End from scconfigmgr.com by Nickolaj Andersen who pointed me to the MahApps.Metro theme when I complimented him on the aesthetics of his Front End.

I’d recommend checking out the instructions by Kevin Rahetilahy on his blog at dev4sysblog and Damien Van Robaeys’s how-to video on creating WPF GUIs and applying the MahApps.Metro theme.

Now, coming back to this post. Getting the MahApps.Metro theme to work with the WPF GUI requires loading a couple of DLL files in the PowerShell script but annoyingly I ran into a problem where the DLLs wouldn’t import in the SCCM/MDT boot images In WindowsPE but works flawlessly in Windows 10. This is the error message I was getting:

“Could not load file or assembly MahApps.Metro.dll or one of its dependencies. Operation is not supported.”

image

Attempting to load “System.Windows.interactivity.dll” also threw the same error message. I also tried changing the DLL files from .Net 4.0 to 4.5 and also tried solutions from the community which presented me with the same error message each time. I knew these community solutions work in other environment so there was something definitely wrong from my end.

After trying a lot of different things I finally managed to resolve this with a workaround. Here’s what I done.

First, let’s take a look at the three DLLs I’ve been trying to load in my script.

[System.Reflection.Assembly]::LoadWithPartialName("presentationframework")
[System.Reflection.Assembly]::LoadFrom("$MyScriptDir\assembly\MahApps.Metro.dll")
[System.Reflection.Assembly]::LoadFrom("$MyScriptDir\assembly\System.Windows.Interactivity.dll")

The first DLL, the “presentationframework.dll”, imported successfully whereas the other two failed consistently no matter what I tried. After concentrating far too long on the two problematic DLLs and failing to come up with a solution I decided to take a closer look at the “presentationframework.dll”. When I load this DLL I get the following output in my console:

image

I saw that the DLL was being loaded from “X:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\presentationframework\v4.0_4.0.0.0__31bf3856ad364e35”.

So I decided to manually create this folder structure as shown below for each of my DLL files and copy them over:

Folder structure to create and location to copy MahApps.Metro.dll:

“X:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\MahApps.Metro\v4.0_4.0.0.0__31bf3856ad364e35\MahApps.Metro.dll”

Folder structure to create and location to copy System.Windows.Interactivity.dll:

“C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Interactivity\v4.0_4.0.0.0__31bf3856ad364e35\System.Windows.Interactivity.dll”

I then tried loading the DLL files using the following lines:

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Interactivity")
[System.Reflection.Assembly]::LoadWithPartialName("MahApps.Metro")

And voila! The two DLL files were loaded successfully!

image

The GUI and the theme works absolutely fine with this workaround. I spent a lot of time grappling with this problem so it was a relief to finally have it resolved, not to mention my GUI looks so much better with the theme. I just had to write this post not only for my own reference but also hoping it may help someone else out there too.

I’m refraining myself from inserting a screenshot of the GUI as I want to write a separate post introducing it to the community :)

Advertisements

Automate the Process of Building and Capturing a Windows 10 1703 Reference Image: Automating using PowerShell

So far in this series we’ve populated our Deployment Share, created a Build and Capture Task Sequence and configured the CustomSettings.ini rules to skip the MDT Deployment Wizard to run our task sequence.

At this point, the CustomSettings.ini rules helps us to automate the process of running the task sequence and capturing the image but there’s still a few manual tasks of having to:

  • Create a Virtual Machine
  • Giving the VM’s network adapter the specific MAC address that we specified in the rules
  • Attaching the MDT Boot Image to the VM’s DVD drive
  • Turning on the VM

Only then does the MDT Deployment Wizard look up the MAC address in the VM and then processes the rules under a matching MAC address section in the CustomSettings.ini file.

So here we need a bit of help from PowerShell and also XML.

Download the zip file containing the PowerShell module and XML file

One of my goals of automating this process using PowerShell was that it should be extensible without having to change any PowerShell code. When Windows 10 1709 comes along later this year I don’t want to have to change anything in the code to account for that. Also, I don’t just create reference images for Windows 10 – I have other reference images to create for Windows 7 and 8.1 (with matching task sequences and rules in MDT). Taking inspiration from Mikael Nystrom’s image factory, I decided to have an XML file to hold data about the Windows reference images I want to create.

The XML file holds global data relating to each VM to create, such as the number of processors, RAM, Hyper-V Switch, ISO path, etc. It also holds data relating to every reference image I want to create, such as the name to give the VM and, most importantly, the Mac address to assign the VM.

This will, I hope, become clearer with an example of how to run the PowerShell function:

New-ReferenceImage –Image windows10-1703 –DestroyVM

Update: Click on the GIF for the high quality image. I didn’t realise WordPress will compress the image so much in the post that the text would be unreadable. Clicking on the image however displays the original high quality GIF.  Powershell 3

The value you provide in the –Image switch has to match a tag in the XML file (which is where the module gets its data from). PowerShell will match the value provided in the –Image switch with an <Image> tag in the XML file and then proceed to create the VM with the name and Mac address within the matching tag.

In the above example, this is how things work:

  1. PowerShell matches the value provided in –Image switch (windows10-1703) with the tag highlighted yellow below
  2. It creates a VM called “Reference Image – Windows 10 1703”
  3. Give the network adapter the MAC address 00:15:5D:00:0B:04. This is the same MAC address we have in our CustomSettings.ini rules.
  4. The MDT boot image is attached to the VM
  5. The VM fires up to boot straight into the MDT Deployment Wizard.
  6. The Deployment Wizard then looks up the VM’s MAC address and matches it with the MAC address provided in the CustomSettings.ini rules.
  7. The rules underneath the MAC address tells the Deployment Wizard to run our Build and Capture Task Sequence and create a captured WIM file at the end

Continue reading

Quick Fix: Get-MDTComputer by Description Broken in the MDT PowerShell Module

The short story:

Launch SQL Server Management Studio, expand the MDT database > Views > right-click on dbo.ComputerSettings and click on “Design”, tick the “Description” column in the CI table in the View.

The long story:

During my experiments with using PowerShell to automate Windows imaging and deployment tasks I’ve been working with the MDT database module, provided by Michael Niehaus from Microsoft.

I was disappointed to find the Get-MDTComputer cmdlet is broken somewhat, as in you can’t retrieve a computer record from the database matching a description. This is what the error message says when you try:

image

I thought I’d take a look at the Get-MDTComputer function in the PowerShell module and saw that the function was doing nothing more than building a SQL statement and querying the MDT database. Specifically, it was querying the “ComputerSettings” table as shown below:

image

This, along with the error message we saw earlier mentioning “Invalid column name ‘Description'”, led me to fire up the SQL Server Management Studio to examine the “ComputerSettings” table, only to find there isn’t a table with that name but there was a “View” called “ComputerSettings”.

I right-clicked the “ComputerSettings” View and selected “Design” and immediately saw what the issue was here. It was apparent that the problem was that the “ComputerSettings” View didn’t include the “Description” column from the ComputerIdentity table.

So the solution is to tick the checkbox next to the “Description” column in the CI table in the View:

image

 

And here you can see the Get-MDTComputer cmdlet working with the –Description parameter:

image