References
https://adminscache.wordpress.com/2013/06/09/base64-encoding-of-images/
How to use task sequence variables – Configuration Manager | Microsoft Learn
Overview
Designed as a more customisable alternative to MDT, this solution displays an XAML UI during a task sequence to configure client specific settings. We’re using PowerShell to set Task Sequence Variables. I’ll run through the basic setup, and what features I’ve configured for our environment.
There are 3 core components of this script to consider which I’ll list below.
Breakdown
1. We start by creating our XAML UI template. I used Visual Studio to do this. Create a WPF application, and design your UI from there. Your resultant XAML file will be stored amongst your WPF Project Files. In the example below, I’ve copied the content of the XAML file into our PowerShell script. This will create the XAML file in preparation for displaying on the endpoint.
| #Main Window | |
| [string]$data=@" | |
| <Window x:Name="Window" x:Class="MECM_TSWizard.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:MECM_TSWizard" | |
| mc:Ignorable="d" | |
| Title="Install Notification" WindowStartupLocation="CenterScreen" WindowStyle="None" Topmost="True" WindowState="Maximized"> | |
| <Grid x:Name="MainMenu1"> | |
| <Label Content="Computer Name: | |
| " HorizontalAlignment="Left" Margin="25,141,0,0" VerticalAlignment="Top" Height="32" Width="120" FontSize="14"/> | |
| <Label Content=" Task Sequence Wizard" HorizontalAlignment="Left" Margin="0,33,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="22" FontWeight="Bold"/> | |
| <Label Content="Brand New Computer:" HorizontalAlignment="Left" Margin="25,221,0,0" VerticalAlignment="Top" Height="32" Width="333" FontSize="14"/> | |
| <Label Content="Restore from Backup:" HorizontalAlignment="Left" Margin="25,253,0,0" VerticalAlignment="Top" Height="32" Width="376" FontSize="14"/> | |
| <Label Content=" Computer Name" HorizontalAlignment="Left" Margin="0,98,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="20" FontWeight="Bold" Background="#FF0069B4" Foreground="White"/> | |
| <Label Content=" Build Type" HorizontalAlignment="Left" Margin="0,178,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="20" FontWeight="Bold" Background="#FF0069B4" Foreground="White"/> | |
| <Label Content=" Location" HorizontalAlignment="Left" Margin="0,290,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="20" FontWeight="Bold" Background="#FF0069B4" Foreground="White"/> | |
| <RadioButton x:Name="BuildType1" Content="" HorizontalAlignment="Left" Margin="180,229,0,0" VerticalAlignment="Top" GroupName="BuildType" IsChecked="True"/> | |
| <RadioButton x:Name="BuildType2" Content="" HorizontalAlignment="Left" Margin="180,261,0,0" VerticalAlignment="Top" GroupName="BuildType"/> | |
| <Label Content="Location 1:" HorizontalAlignment="Left" Margin="25,333,0,0" VerticalAlignment="Top" Height="32" Width="171" FontSize="14"/> | |
| <Label Content="Location 2:" HorizontalAlignment="Left" Margin="25,360,0,0" VerticalAlignment="Top" Height="32" Width="102" FontSize="14"/> | |
| <Label Content="Location 3" HorizontalAlignment="Left" Margin="25,386,0,0" VerticalAlignment="Top" Height="32" Width="187" FontSize="14"/> | |
| <Label Content="Location 5:" HorizontalAlignment="Left" Margin="25,440,0,0" VerticalAlignment="Top" Height="32" Width="129" FontSize="14"/> | |
| <Label Content="Location 4" HorizontalAlignment="Left" Margin="25,414,0,0" VerticalAlignment="Top" Height="32" Width="89" FontSize="14"/> | |
| <RadioButton x:Name="Location1" Content="" HorizontalAlignment="Left" Margin="110,341,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <RadioButton x:Name="Location2" Content="" HorizontalAlignment="Left" Margin="110,368,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <RadioButton x:Name="Location3" Content="" HorizontalAlignment="Left" Margin="110,395,0,0" VerticalAlignment="Top" GroupName="Location" IsChecked="True"/> | |
| <RadioButton x:Name="Location4" Content="" HorizontalAlignment="Left" Margin="110,424,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <RadioButton x:Name="Location5" Content="" HorizontalAlignment="Left" Margin="110,448,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <TextBox x:Name="ComputerNameText" HorizontalAlignment="Left" Height="23" Margin="145,145,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/> | |
| <ComboBox x:Name="BuildType2ComboBox" HorizontalAlignment="Left" Margin="210,256,0,0" VerticalAlignment="Top" Width="120"> | |
| <ComboBoxItem Name="BuildTypeComboBox1" IsSelected="True">Restore Server 1</ComboBoxItem> | |
| <ComboBoxItem Name="BuildTypeComboBox2">Restore Server 2</ComboBoxItem> | |
| <ComboBoxItem Name="BuildTypeComboBox3">External Drive</ComboBoxItem> | |
| </ComboBox> | |
| <Border BorderThickness="1" HorizontalAlignment="Left" Height="92" Margin="270,76,0,0" VerticalAlignment="Top" Width="225"> | |
| <Expander Width="200" HorizontalContentAlignment="Stretch" Margin="-0.8,-66.8,24,-0.8" ExpandDirection="Up"> | |
| <Expander.Header> | |
| <BulletDecorator> | |
| <TextBlock Margin="2,0,0,0"><Run Text="Naming Convention"/></TextBlock> | |
| </BulletDecorator> | |
| </Expander.Header> | |
| <Label Content="Naming Convention Description | |
| to go here." Margin="0,0,-1.6,0" Background="White" /> | |
| </Expander> | |
| </Border> | |
| <Label x:Name="Version" HorizontalAlignment="Left" Margin="25,500,0,0" VerticalAlignment="Top" Width="70" Height="27" FontSize="10"/> | |
| <Label x:Name="ErrorLabel" Content="" HorizontalAlignment="Left" Margin="100,495,0,0" VerticalAlignment="Top" Height="32" Width="572" FlowDirection="RightToLeft" FontSize="14" Foreground="Red"/> | |
| <Button x:Name="Continue" Content="Continue" HorizontalAlignment="Left" Margin="677,500,0,0" VerticalAlignment="Top" Width="75"/> | |
| </Grid> | |
| </Window> | |
| "@ | |
| #Copy file to disk | |
| $Data | Set-Content "$PSScriptRoot\MainWindow.xaml" -Force |
2. Next, we’re staging our Net Framework Assemblies which will allow us to set content for the XAML UI within Powershell. For example, we can set values for items such as labels, buttons and radio buttons. All XAML content is stored under the $Synchash variable we define below. I won’t delve into the technicalities here, but on the next paragraph we’ll be looking at examples of how XAML content is set within PowerShell.
| ################################################################################################################################### | |
| #Load XAML | |
| ################################################################################################################################### | |
| function Get-XamlObject { | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Position = 0, | |
| Mandatory = $true, | |
| ValuefromPipelineByPropertyName = $true, | |
| ValuefromPipeline = $true)] | |
| [Alias("FullName")] | |
| [System.String[]]$Path | |
| ) | |
| BEGIN | |
| { | |
| Set-StrictMode -Version Latest | |
| $expandedParams = $null | |
| $PSBoundParameters.GetEnumerator() | ForEach-Object { $expandedParams += ' -' + $_.key + ' '; $expandedParams += $_.value } | |
| Write-Verbose "Starting: $($MyInvocation.MyCommand.Name)$expandedParams" | |
| $output = @{ } | |
| Add-Type -AssemblyName presentationframework, presentationcore | |
| } #BEGIN | |
| PROCESS { | |
| try | |
| { | |
| foreach ($xamlFile in $Path) | |
| { | |
| #Change content of Xaml file to be a set of powershell GUI objects | |
| $inputXML = Get-Content -Path $xamlFile -ErrorAction Stop | |
| [xml]$xaml = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace 'x:Class=".*?"', '' -replace 'd:DesignHeight="\d*?"', '' -replace 'd:DesignWidth="\d*?"', '' | |
| $tempform = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $xaml -ErrorAction Stop)) | |
| #Grab named objects from tree and put in a flat structure using Xpath | |
| $namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | |
| $namedNodes | ForEach-Object { | |
| $output.Add($_.Name, $tempform.FindName($_.Name)) | |
| } #foreach-object | |
| } #foreach xamlpath | |
| } #try | |
| catch | |
| { | |
| throw $error[0] | |
| } #catch | |
| } #PROCESS | |
| END | |
| { | |
| Write-Output $output | |
| Write-Verbose "Finished: $($MyInvocation.Mycommand)" | |
| } #END | |
| } | |
| $path = "$PSScriptRoot" | |
| $script:syncHash = [hashtable]::Synchronized(@{ }) | |
| $script:syncHash = Get-ChildItem -Path $path -Filter *.xaml -file | Where-Object { $_.Name -ne 'App.xaml' } | Get-XamlObject | |
| # Hide PowerShell Console | |
| Add-Type -Name Window -Namespace Console -MemberDefinition ' | |
| [DllImport("Kernel32.dll")] | |
| public static extern IntPtr GetConsoleWindow(); | |
| [DllImport("user32.dll")] | |
| public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow); | |
| ' | |
| $consolePtr = [Console.Window]::GetConsoleWindow() | |
| [Console.Window]::ShowWindow($consolePtr, 0) | |
| ################################################################################################################################### | |
| #Load XAML End | |
| ################################################################################################################################### |
3. Finally, we’re defining our Task Sequence Variables based on values set in the XAML UI. The $tsenv variable is used to store data from the Task Sequence environment, then we use the $Synchash variable (Created from our previous step) to retrieve or set values from the XAML UI.
For example to set the computer name variable in your Task Sequence based on the value inputted in the XAML, use the following command:
$tsenv.Value(“OSDComputerName”) = $Synchash.ComputerNameText.Text
In this example, I’ve also defined regex to prevent the Task Sequence from continuing if the name entered does not match the convention specified.
Complete Example
| ################################################################################################################################### | |
| #Load XAML | |
| ################################################################################################################################### | |
| function Get-XamlObject { | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Position = 0, | |
| Mandatory = $true, | |
| ValuefromPipelineByPropertyName = $true, | |
| ValuefromPipeline = $true)] | |
| [Alias("FullName")] | |
| [System.String[]]$Path | |
| ) | |
| BEGIN | |
| { | |
| Set-StrictMode -Version Latest | |
| $expandedParams = $null | |
| $PSBoundParameters.GetEnumerator() | ForEach-Object { $expandedParams += ' -' + $_.key + ' '; $expandedParams += $_.value } | |
| Write-Verbose "Starting: $($MyInvocation.MyCommand.Name)$expandedParams" | |
| $output = @{ } | |
| Add-Type -AssemblyName presentationframework, presentationcore | |
| } #BEGIN | |
| PROCESS { | |
| try | |
| { | |
| foreach ($xamlFile in $Path) | |
| { | |
| #Change content of Xaml file to be a set of powershell GUI objects | |
| $inputXML = Get-Content -Path $xamlFile -ErrorAction Stop | |
| [xml]$xaml = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace 'x:Class=".*?"', '' -replace 'd:DesignHeight="\d*?"', '' -replace 'd:DesignWidth="\d*?"', '' | |
| $tempform = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $xaml -ErrorAction Stop)) | |
| #Grab named objects from tree and put in a flat structure using Xpath | |
| $namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | |
| $namedNodes | ForEach-Object { | |
| $output.Add($_.Name, $tempform.FindName($_.Name)) | |
| } #foreach-object | |
| } #foreach xamlpath | |
| } #try | |
| catch | |
| { | |
| throw $error[0] | |
| } #catch | |
| } #PROCESS | |
| END | |
| { | |
| Write-Output $output | |
| Write-Verbose "Finished: $($MyInvocation.Mycommand)" | |
| } #END | |
| } | |
| $path = "$PSScriptRoot" | |
| $script:syncHash = [hashtable]::Synchronized(@{ }) | |
| $script:syncHash = Get-ChildItem -Path $path -Filter *.xaml -file | Where-Object { $_.Name -ne 'App.xaml' } | Get-XamlObject | |
| # Hide PowerShell Console | |
| Add-Type -Name Window -Namespace Console -MemberDefinition ' | |
| [DllImport("Kernel32.dll")] | |
| public static extern IntPtr GetConsoleWindow(); | |
| [DllImport("user32.dll")] | |
| public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow); | |
| ' | |
| $consolePtr = [Console.Window]::GetConsoleWindow() | |
| [Console.Window]::ShowWindow($consolePtr, 0) | |
| ################################################################################################################################### | |
| #Load XAML End | |
| ################################################################################################################################### |
How to use
Configure a Task Sequence Step to run the PowerShell Script below. There’s no need to create a package here; simply use the “Enter Script” feature in your Task Sequence.
You can use the example below to see how this could work. However, you’ll likely need to define your own XAML content and Task Sequence Variables for this to be useful for your unique environment. Feel free to throw any questions in the comment section below.
The UI from my sample:

Complete Script
| #MECM Task Sequence Wizard | |
| #Custom Powershell and XAML UI used to configure Task Sequence Variables | |
| #Contact | Josh Woods | |
| $Version = "v2.0.0" | |
| ########################################################################################################### | |
| #Prerequisites | |
| Add-Type -AssemblyName PresentationFramework | |
| #Main Window | |
| [string]$data=@" | |
| <Window x:Name="Window" x:Class="MECM_TSWizard.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:MECM_TSWizard" | |
| mc:Ignorable="d" | |
| Title="Install Notification" WindowStartupLocation="CenterScreen" WindowStyle="None" Topmost="True" WindowState="Maximized"> | |
| <Grid x:Name="MainMenu1"> | |
| <Label Content="Computer Name: | |
| " HorizontalAlignment="Left" Margin="25,141,0,0" VerticalAlignment="Top" Height="32" Width="120" FontSize="14"/> | |
| <Label Content=" Task Sequence Wizard" HorizontalAlignment="Left" Margin="0,33,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="22" FontWeight="Bold"/> | |
| <Label Content="Brand New Computer:" HorizontalAlignment="Left" Margin="25,221,0,0" VerticalAlignment="Top" Height="32" Width="333" FontSize="14"/> | |
| <Label Content="Restore from Backup:" HorizontalAlignment="Left" Margin="25,253,0,0" VerticalAlignment="Top" Height="32" Width="376" FontSize="14"/> | |
| <Label Content=" Computer Name" HorizontalAlignment="Left" Margin="0,98,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="20" FontWeight="Bold" Background="#FF0069B4" Foreground="White"/> | |
| <Label Content=" Build Type" HorizontalAlignment="Left" Margin="0,178,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="20" FontWeight="Bold" Background="#FF0069B4" Foreground="White"/> | |
| <Label Content=" Location" HorizontalAlignment="Left" Margin="0,290,-0.4,0" VerticalAlignment="Top" Height="38" Width="762" FontSize="20" FontWeight="Bold" Background="#FF0069B4" Foreground="White"/> | |
| <RadioButton x:Name="BuildType1" Content="" HorizontalAlignment="Left" Margin="180,229,0,0" VerticalAlignment="Top" GroupName="BuildType" IsChecked="True"/> | |
| <RadioButton x:Name="BuildType2" Content="" HorizontalAlignment="Left" Margin="180,261,0,0" VerticalAlignment="Top" GroupName="BuildType"/> | |
| <Label Content="Location 1:" HorizontalAlignment="Left" Margin="25,333,0,0" VerticalAlignment="Top" Height="32" Width="171" FontSize="14"/> | |
| <Label Content="Location 2:" HorizontalAlignment="Left" Margin="25,360,0,0" VerticalAlignment="Top" Height="32" Width="102" FontSize="14"/> | |
| <Label Content="Location 3" HorizontalAlignment="Left" Margin="25,386,0,0" VerticalAlignment="Top" Height="32" Width="187" FontSize="14"/> | |
| <Label Content="Location 5:" HorizontalAlignment="Left" Margin="25,440,0,0" VerticalAlignment="Top" Height="32" Width="129" FontSize="14"/> | |
| <Label Content="Location 4" HorizontalAlignment="Left" Margin="25,414,0,0" VerticalAlignment="Top" Height="32" Width="89" FontSize="14"/> | |
| <RadioButton x:Name="Location1" Content="" HorizontalAlignment="Left" Margin="110,341,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <RadioButton x:Name="Location2" Content="" HorizontalAlignment="Left" Margin="110,368,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <RadioButton x:Name="Location3" Content="" HorizontalAlignment="Left" Margin="110,395,0,0" VerticalAlignment="Top" GroupName="Location" IsChecked="True"/> | |
| <RadioButton x:Name="Location4" Content="" HorizontalAlignment="Left" Margin="110,424,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <RadioButton x:Name="Location5" Content="" HorizontalAlignment="Left" Margin="110,448,0,0" VerticalAlignment="Top" GroupName="Location"/> | |
| <TextBox x:Name="ComputerNameText" HorizontalAlignment="Left" Height="23" Margin="145,145,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/> | |
| <ComboBox x:Name="BuildType2ComboBox" HorizontalAlignment="Left" Margin="210,256,0,0" VerticalAlignment="Top" Width="120"> | |
| <ComboBoxItem Name="BuildTypeComboBox1" IsSelected="True">Restore Server 1</ComboBoxItem> | |
| <ComboBoxItem Name="BuildTypeComboBox2">Restore Server 2</ComboBoxItem> | |
| <ComboBoxItem Name="BuildTypeComboBox3">External Drive</ComboBoxItem> | |
| </ComboBox> | |
| <Border BorderThickness="1" HorizontalAlignment="Left" Height="92" Margin="270,76,0,0" VerticalAlignment="Top" Width="225"> | |
| <Expander Width="200" HorizontalContentAlignment="Stretch" Margin="-0.8,-66.8,24,-0.8" ExpandDirection="Up"> | |
| <Expander.Header> | |
| <BulletDecorator> | |
| <TextBlock Margin="2,0,0,0"><Run Text="Naming Convention"/></TextBlock> | |
| </BulletDecorator> | |
| </Expander.Header> | |
| <Label Content="Naming Convention Description | |
| to go here." Margin="0,0,-1.6,0" Background="White" /> | |
| </Expander> | |
| </Border> | |
| <Label x:Name="Version" HorizontalAlignment="Left" Margin="25,500,0,0" VerticalAlignment="Top" Width="70" Height="27" FontSize="10"/> | |
| <Label x:Name="ErrorLabel" Content="" HorizontalAlignment="Left" Margin="100,495,0,0" VerticalAlignment="Top" Height="32" Width="572" FlowDirection="RightToLeft" FontSize="14" Foreground="Red"/> | |
| <Button x:Name="Continue" Content="Continue" HorizontalAlignment="Left" Margin="677,500,0,0" VerticalAlignment="Top" Width="75"/> | |
| </Grid> | |
| </Window> | |
| "@ | |
| #Copy file to disk | |
| $Data | Set-Content "$PSScriptRoot\MainWindow.xaml" -Force | |
| ################################################################################################################################### | |
| #Load XAML | |
| ################################################################################################################################### | |
| function Get-XamlObject { | |
| [CmdletBinding()] | |
| param( | |
| [Parameter(Position = 0, | |
| Mandatory = $true, | |
| ValuefromPipelineByPropertyName = $true, | |
| ValuefromPipeline = $true)] | |
| [Alias("FullName")] | |
| [System.String[]]$Path | |
| ) | |
| BEGIN | |
| { | |
| Set-StrictMode -Version Latest | |
| $expandedParams = $null | |
| $PSBoundParameters.GetEnumerator() | ForEach-Object { $expandedParams += ' -' + $_.key + ' '; $expandedParams += $_.value } | |
| Write-Verbose "Starting: $($MyInvocation.MyCommand.Name)$expandedParams" | |
| $output = @{ } | |
| Add-Type -AssemblyName presentationframework, presentationcore | |
| } #BEGIN | |
| PROCESS { | |
| try | |
| { | |
| foreach ($xamlFile in $Path) | |
| { | |
| #Change content of Xaml file to be a set of powershell GUI objects | |
| $inputXML = Get-Content -Path $xamlFile -ErrorAction Stop | |
| [xml]$xaml = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace 'x:Class=".*?"', '' -replace 'd:DesignHeight="\d*?"', '' -replace 'd:DesignWidth="\d*?"', '' | |
| $tempform = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $xaml -ErrorAction Stop)) | |
| #Grab named objects from tree and put in a flat structure using Xpath | |
| $namedNodes = $xaml.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | |
| $namedNodes | ForEach-Object { | |
| $output.Add($_.Name, $tempform.FindName($_.Name)) | |
| } #foreach-object | |
| } #foreach xamlpath | |
| } #try | |
| catch | |
| { | |
| throw $error[0] | |
| } #catch | |
| } #PROCESS | |
| END | |
| { | |
| Write-Output $output | |
| Write-Verbose "Finished: $($MyInvocation.Mycommand)" | |
| } #END | |
| } | |
| $path = "$PSScriptRoot" | |
| $script:syncHash = [hashtable]::Synchronized(@{ }) | |
| $script:syncHash = Get-ChildItem -Path $path -Filter *.xaml -file | Where-Object { $_.Name -ne 'App.xaml' } | Get-XamlObject | |
| # Hide PowerShell Console | |
| Add-Type -Name Window -Namespace Console -MemberDefinition ' | |
| [DllImport("Kernel32.dll")] | |
| public static extern IntPtr GetConsoleWindow(); | |
| [DllImport("user32.dll")] | |
| public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow); | |
| ' | |
| $consolePtr = [Console.Window]::GetConsoleWindow() | |
| [Console.Window]::ShowWindow($consolePtr, 0) | |
| ################################################################################################################################### | |
| #Load XAML End | |
| ################################################################################################################################### | |
| ################################################################################################################################### | |
| #Control Logic | |
| ################################################################################################################################### | |
| #Com Object for Read and Write Task Sequence Variables | |
| $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment | |
| ########### | |
| #XAML Display Variables | |
| ########### | |
| #Version | |
| $Synchash.Version.content = $Version | |
| #Notification Label | |
| $Synchash.NotificationLabel.Content = $NotificationLabel | |
| #Banner | |
| $Synchash.NCABanner.Source = "$PSScriptRoot\Banner.png" | |
| #Computer Name | |
| $Synchash.ComputerNameText.Text = $tsenv.Value("_SMSTSMachineName") | |
| ########### | |
| #XAML Display Variables End | |
| ########### | |
| #Continue Button | |
| $Synchash.Continue.Add_Click( { | |
| #Error Level | |
| $ErrorLevel = "false" | |
| #Computer Name Convention match Test (Sample Regex here | Requires any number of characters, followed by a hyphen and 5 numbers.) | |
| if ($Synchash.computerNameText.Text -cnotmatch '^([A-Z0-9]+)-([0-9]{5})$') { | |
| $ErrorLevel = "true" | |
| $Synchash.ErrorLabel.content = "The Computer Name Must use the Correct Naming Convention" | |
| } | |
| if ($Synchash.computerNameText.Text) { | |
| } | |
| else { | |
| $ErrorLevel = "true" | |
| $Synchash.ErrorLabel.content = "You Must Enter a Computer Name" | |
| } | |
| #Computer Name Convention exception (Start hostname with a Hash. This condition will remove the Hash in the resultant hostname) | |
| if ($Synchash.computerNameText.Text -like "#*") { | |
| $ErrorLevel = "false" | |
| $Synchash.computerNameText.Text = $Synchash.computerNameText.Text -replace "#", "" | |
| } | |
| #Set Computer Name as Task Sequence Variable | |
| $tsenv.Value("OSDComputerName") = $Synchash.ComputerNameText.Text | |
| #Build Type | Set variables to be used in Task Sequence | |
| if ($Synchash.BuildType2.IsChecked -eq "True") { | |
| if ($Synchash.BuildTypeComboBox1.IsSelected -eq "True") { | |
| $tsenv.Value("RestoreServer1") = "true" | |
| } | |
| if ($Synchash.BuildTypeComboBox2.IsSelected -eq "True") { | |
| $tsenv.Value("RestoreServer2") = "true" | |
| } | |
| if ($Synchash.BuildTypeComboBox3.IsSelected -eq "True") { | |
| $tsenv.Value("ExternalDrive") = "true" | |
| } | |
| } | |
| #Location | Set variables to be used in Task Sequence | |
| if ($Synchash.Location1.IsChecked -eq "True") { | |
| $tsenv.Value("Location1") = "true" | |
| } | |
| if ($Synchash.Location2.IsChecked -eq "True") { | |
| $tsenv.Value("Location2") = "true" | |
| } | |
| if ($Synchash.Location3.IsChecked -eq "True") { | |
| $tsenv.Value("Location3") = "true" | |
| } | |
| if ($Synchash.Location4.IsChecked -eq "True") { | |
| $tsenv.Value("Location4") = "true" | |
| } | |
| if ($Synchash.Location5.IsChecked -eq "True") { | |
| $tsenv.Value("Location5") = "true" | |
| } | |
| if ($ErrorLevel -eq "false") { | |
| Exit 0 | |
| } | |
| }) | |
| ################################################################################################################################### | |
| #Control Logic End | |
| ################################################################################################################################### | |
| $Null = $synchash.window.ShowDialog() |
