WIMWitch.ps1
<#PSScriptInfo
.VERSION 1.5.0 .GUID ee1ba506-ac68-45f8-9f37-4555f1902353 .AUTHOR Donna Ryan .COMPANYNAME @TheNotoriousDRR .COPYRIGHT .TAGS WIM,Servicing,Offline Image Servicing .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> <# .DESCRIPTION WIM Witch is a GUI driven tool used to update and customize Windows Image (WIM) files. It can also create WIM configuration templates and apply them either with the GUI or programatically for bulk creation. Version 1.5.0 -Added ability to pause build process after mount and before dismount -Added ability to run PowerShell script at after mount, before dismount, or on build completion version 1.4.1 -Added ability to save LP, LXP, and FOD configurations -Validated save file with GUI and CLI functionality -Updated out-grid titles for LP, LXP, and FOD Version 1.4.0 -Adds functionality to import and apply Language Packs, Features on Demand, and Local Experience Packs. -Bug fix for importing WIM and .Net from ISO files. #> #=========================================================================== # WIM Witch #=========================================================================== # # Written and maintained by: Donna Ryan # Twitter: @TheNotoriousDRR # www.TheNotoriousDRR.com # www.SCConfigMgr.com # # Current WIM Witch Doc (v1.4.0) # https://www.scconfigmgr.com/2020/02/05/wim-witch-v1-4-0-language-packs-features-on-demand-and-local-experience-packs/ # # Previous WIM Witch Doc (v1.3.0): # https://www.scconfigmgr.com/2019/12/08/wim-witch-v1-3-0-server-support-onedrive-and-command-line/ # # Previous WIM Witch Doc (v1.0): # https://www.scconfigmgr.com/2019/10/04/wim-witch-a-gui-driven-solution-for-image-customization/ # #=========================================================================== # # WIM Witch is a GUI driven tool used to update and customize Windows # Image (WIM) files. It can also create WIM configuration templates and # apply them either with the GUI or programatically for bulk creation. # # It currently supports the following functions: # # -Selecting the individual index to import # -Autopilot for existing devices # -Retrieve Autopilot deployment profiles from Intune # -Multi path driver importation # -Injection of updates from a self maintained local update cache # -Save and Load Configuration Templates # -Removal of AppX Modern Apps # -Create batch jobs for image catalog updating # -importing WIM and .Net binaries from an ISO file # -injecting .Net 3.5 binaries into image # -injecting Language Pack, Local Experience Pack, and FOD's # -Supports Windows 10 and Windows Server 2016/2019 # #============================================================================================================ Param( [parameter(mandatory = $false, HelpMessage = "enable auto")] #[ValidateSet("yes")] [switch]$auto, [parameter(mandatory = $false, HelpMessage = "config file")] [string]$autofile, [parameter(mandatory = $false, HelpMessage = "config path")] #[ValidateSet("$PSScriptRoot\configs")] [string]$autopath, #[parameter(mandatory = $false, HelpMessage = "Superseded updates")] #[ValidateSet("audit", "delete")] #[string]$Superseded, [parameter(mandatory = $false, HelpMessage = "Update Modules")] #[ValidateSet("update")] #$OSDSUS, [Switch]$UpdatePoShModules, [parameter(mandatory = $false, HelpMessage = "Enable Downloading Updates")] #[ValidateSet("yes")] #$updates [switch]$DownloadUpdates, [parameter(mandatory = $false, HelpMessage = "Win10 Version")] [ValidateSet("all", "1709", "1803", "1809", "1903", "1909")] #$DownUpdates, [string]$Win10Version = "none", [parameter(mandatory = $false, HelpMessage = "Windows Server 2016?")] [switch]$Server2016, [parameter(mandatory = $false, HelpMessage = "Windows Server 2019?")] [switch]$Server2019 ) $WWScriptVer = "1.5.0" #Your XAML goes here :) $inputXML = @" <Window x:Class="WIM_Witch_Tabbed.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:WIM_Witch_Tabbed" mc:Ignorable="d" Title="WIM Witch - v1.5.0" Height="500" Width="800" Background="#FF610536"> <Grid> <TabControl x:Name="TabControl" Margin="0,0,0,-0.5" Background="#FFACACAC" BorderBrush="#FF610536" Grid.ColumnSpan="2" > <TabItem Header="Import WIM + .Net" Height="20" MinWidth="100"> <Grid> <TextBox x:Name="ImportISOTextBox" HorizontalAlignment="Left" Height="42" Margin="26,85,0,0" Text="ISO to import from..." VerticalAlignment="Top" Width="500" IsEnabled="False" HorizontalScrollBarVisibility="Visible"/> <TextBlock HorizontalAlignment="Left" Margin="26,56,0,0" TextWrapping="Wrap" Text="Select a Windows 10 ISO:" VerticalAlignment="Top" Height="26" Width="353"/> <Button x:Name="ImportImportSelectButton" Content="Select" HorizontalAlignment="Left" Margin="451,135,0,0" VerticalAlignment="Top" Width="75"/> <TextBlock HorizontalAlignment="Left" Margin="26,159,0,0" TextWrapping="Wrap" Text="Select the item(s) to import:" VerticalAlignment="Top" Width="263"/> <CheckBox x:Name="ImportWIMCheckBox" Content="Install.wim" HorizontalAlignment="Left" Margin="44,191,0,0" VerticalAlignment="Top"/> <CheckBox x:Name="ImportDotNetCheckBox" Content=".Net Binaries" HorizontalAlignment="Left" Margin="44,211,0,0" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="26,268,0,0" TextWrapping="Wrap" Text="New name for the imported WIM:" VerticalAlignment="Top" Width="311"/> <TextBox x:Name="ImportNewNameTextBox" HorizontalAlignment="Left" Height="23" Margin="26,289,0,0" TextWrapping="Wrap" Text="Name for the imported WIM" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Button x:Name="ImportImportButton" Content="Import" HorizontalAlignment="Left" Margin="451,354,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> </Grid> </TabItem> <TabItem Header="Import LP+FOD" Margin="0" MinWidth="100"> <Grid> <TextBox x:Name="ImportOtherTBPath" HorizontalAlignment="Left" Height="23" Margin="49,92,0,0" TextWrapping="Wrap" Text="path to source" VerticalAlignment="Top" Width="339" IsEnabled="False"/> <Button x:Name="ImportOtherBSelectPath" Content="Select" HorizontalAlignment="Left" Margin="413,94,0,0" VerticalAlignment="Top" Width="75"/> <TextBlock HorizontalAlignment="Left" Margin="49,130,0,0" TextWrapping="Wrap" Text="Selected items" VerticalAlignment="Top"/> <ComboBox x:Name="ImportOtherCBWinOS" HorizontalAlignment="Left" Margin="228,51,0,0" VerticalAlignment="Top" Width="120"/> <ComboBox x:Name="ImportOtherCBWinVer" HorizontalAlignment="Left" Margin="371,50,0,0" VerticalAlignment="Top" Width="120"/> <Button x:Name="ImportOtherBImport" Content="Import" HorizontalAlignment="Left" Margin="417,317,0,0" VerticalAlignment="Top" Width="75"/> <ComboBox x:Name="ImportOtherCBType" HorizontalAlignment="Left" Margin="51,51,0,0" VerticalAlignment="Top" Width="160"/> <TextBlock HorizontalAlignment="Left" Margin="51,26,0,0" TextWrapping="Wrap" Text="Object Type" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="230,32,0,0" TextWrapping="Wrap" Text="Windows OS" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="372,31,0,0" TextWrapping="Wrap" Text="Version" VerticalAlignment="Top"/> <ListBox x:Name="ImportOtherLBList" HorizontalAlignment="Left" Height="149" Margin="49,151,0,0" VerticalAlignment="Top" Width="442"/> </Grid> </TabItem> <TabItem Header="Update Store" Height="20" MinWidth="100"> <Grid> <TextBlock HorizontalAlignment="Left" Margin="91,196,0,0" TextWrapping="Wrap" Text="Installed version " VerticalAlignment="Top"/> <TextBox x:Name="UpdatesOSDBVersion" HorizontalAlignment="Left" Height="23" Margin="91,218,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/> <Button x:Name="UpdateOSDBUpdateButton" Content="Install / Update" HorizontalAlignment="Left" Margin="218,291,0,0" VerticalAlignment="Top" Width="120"/> <TextBlock HorizontalAlignment="Left" Height="42" Margin="435,118,0,0" TextWrapping="Wrap" Text="Select which versions of Windows to download current patches for. Downloading will also purge superseded updates." VerticalAlignment="Top" Width="335"/> <CheckBox x:Name="UpdatesW10_1903" Content="1903" HorizontalAlignment="Left" Margin="535,193,0,0" VerticalAlignment="Top" IsEnabled="False"/> <CheckBox x:Name="UpdatesW10_1809" Content="1809" HorizontalAlignment="Left" Margin="594,193,0,0" VerticalAlignment="Top" IsEnabled="False"/> <CheckBox x:Name="UpdatesW10_1803" Content="1803" HorizontalAlignment="Left" Margin="652,193,0,0" VerticalAlignment="Top" IsEnabled="False"/> <CheckBox x:Name="UpdatesW10_1709" Content="1709" HorizontalAlignment="Left" Margin="707,193,0,0" VerticalAlignment="Top" IsEnabled="False"/> <Button x:Name="UpdatesDownloadNewButton" Content="Download" HorizontalAlignment="Left" Margin="680,268,0,0" VerticalAlignment="Top" Width="75"/> <TextBlock HorizontalAlignment="Left" Margin="20,142,0,0" TextWrapping="Wrap" Text="Update OSDeploy modules by using the button below. Updating will require PowerShell to be restarted." VerticalAlignment="Top" Height="34" Width="321"/> <TextBox x:Name="UpdatesOSDBCurrentVerTextBox" HorizontalAlignment="Left" Height="23" Margin="218,217,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/> <TextBlock HorizontalAlignment="Left" Margin="218,196,0,0" TextWrapping="Wrap" Text="Current Version" VerticalAlignment="Top"/> <TextBlock x:Name="UpdatesOSDBOutOfDateTextBlock" HorizontalAlignment="Left" Margin="20,315,0,0" TextWrapping="Wrap" Text="A software update module is out of date. Please click the "Install / Update" button to update it." VerticalAlignment="Top" RenderTransformOrigin="0.493,0.524" FontSize="20" Width="321" Visibility="Hidden" /> <TextBlock x:Name="UpdatesOSDBSupercededExistTextBlock" HorizontalAlignment="Left" Margin="417,303,0,0" TextWrapping="Wrap" Text="Superceded updates discovered. Please select the versions of Windows 10 you are supporting and click "Update"" VerticalAlignment="Top" FontSize="20" Width="375" Visibility="Hidden"/> <TextBlock x:Name="UpdatesOSDBClosePowerShellTextBlock" HorizontalAlignment="Left" Margin="435,28,0,0" TextWrapping="Wrap" Text="Please close all PowerShell windows, including WIM Witch, then relaunch app to continue" VerticalAlignment="Top" RenderTransformOrigin="0.493,0.524" FontSize="20" Width="321" Visibility="Hidden"/> <TextBlock HorizontalAlignment="Left" Margin="24,218,0,0" TextWrapping="Wrap" Text="OSDUpdate" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="26,255,0,0" TextWrapping="Wrap" Text="OSDSUS" VerticalAlignment="Top"/> <TextBox x:Name="UpdatesOSDSUSVersion" HorizontalAlignment="Left" Height="23" Margin="91,251,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/> <TextBox x:Name="UpdatesOSDSUSCurrentVerTextBox" HorizontalAlignment="Left" Height="23" Margin="218,251,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" IsEnabled="False"/> <CheckBox x:Name="UpdatesW10Main" Content="Windows 10" HorizontalAlignment="Left" Margin="450,167,0,0" VerticalAlignment="Top"/> <CheckBox x:Name="UpdatesS2016" Content="Windows Server 2016" HorizontalAlignment="Left" Margin="594,217,0,0" VerticalAlignment="Top"/> <CheckBox x:Name="UpdatesS2019" Content="Windows Server 2019" HorizontalAlignment="Left" Margin="448,217,0,0" VerticalAlignment="Top"/> <CheckBox x:Name="UpdatesW10_1909" Content="1909" HorizontalAlignment="Left" Margin="478,193,0,0" VerticalAlignment="Top" IsEnabled="False"/> </Grid> </TabItem> <TabItem Header="Drivers" Height="20" MinWidth="100"> <Grid> <TextBox x:Name="DriverDir1TextBox" HorizontalAlignment="Left" Height="25" Margin="26,144,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Label x:Name="DirverDirLabel" Content="Driver Source" HorizontalAlignment="Left" Height="25" Margin="26,114,0,0" VerticalAlignment="Top" Width="100"/> <Button x:Name="DriverDir1Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,144,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> <TextBlock HorizontalAlignment="Left" Margin="26,20,0,0" TextWrapping="Wrap" Text="Select the path to the driver source(s) that contains the drivers that will be injected." VerticalAlignment="Top" Height="42" Width="353"/> <CheckBox x:Name="DriverCheckBox" Content="Enable Driver Injection" HorizontalAlignment="Left" Margin="26,80,0,0" VerticalAlignment="Top"/> <TextBox x:Name="DriverDir2TextBox" HorizontalAlignment="Left" Height="25" Margin="26,189,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Button x:Name="DriverDir2Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,189,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> <TextBox x:Name="DriverDir3TextBox" HorizontalAlignment="Left" Height="25" Margin="26,234,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Button x:Name="DriverDir3Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,234,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> <TextBox x:Name="DriverDir4TextBox" HorizontalAlignment="Left" Height="25" Margin="26,281,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Button x:Name="DriverDir4Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,281,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> <TextBox x:Name="DriverDir5TextBox" HorizontalAlignment="Left" Height="25" Margin="26,328,0,0" TextWrapping="Wrap" Text="Select Driver Source Folder" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Button x:Name="DriverDir5Button" Content="Select" HorizontalAlignment="Left" Height="25" Margin="562,328,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> </Grid> </TabItem> <TabItem x:Name="AutopilotTab" Header="Autopilot" MinWidth="100"> <Grid> <TextBox x:Name="JSONTextBox" HorizontalAlignment="Left" Height="25" Margin="26,130,0,0" TextWrapping="Wrap" Text="Select JSON File" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Label x:Name="JSONLabel" Content="Source JSON" HorizontalAlignment="Left" Height="25" Margin="26,104,0,0" VerticalAlignment="Top" Width="100"/> <Button x:Name="JSONButton" Content="Select" HorizontalAlignment="Left" Height="25" Margin="451,165,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> <TextBlock HorizontalAlignment="Left" Margin="26,20,0,0" TextWrapping="Wrap" Text="Select a JSON file for use in deploying Autopilot systems. The file will be copied to processing folder during the build" VerticalAlignment="Top" Height="42" Width="353"/> <CheckBox x:Name="JSONEnableCheckBox" Content="Enable Autopilot " HorizontalAlignment="Left" Margin="26,80,0,0" VerticalAlignment="Top" ClickMode="Press"/> <TextBox x:Name="ZtdCorrelationId" HorizontalAlignment="Left" Height="23" Margin="129,176,0,0" TextWrapping="Wrap" Text="Select JSON File..." VerticalAlignment="Top" Width="236" IsEnabled="False"/> <TextBox x:Name="CloudAssignedTenantDomain" HorizontalAlignment="Left" Height="23" Margin="129,204,0,0" TextWrapping="Wrap" Text="Select JSON File..." VerticalAlignment="Top" Width="236" IsEnabled="False"/> <TextBox x:Name="Comment_File" HorizontalAlignment="Left" Height="23" Margin="129,232,0,0" TextWrapping="Wrap" Text="Select JSON File..." VerticalAlignment="Top" Width="236" IsEnabled="False"/> <TextBlock HorizontalAlignment="Left" Margin="24,178,0,0" TextWrapping="Wrap" Text="ZTD ID#" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="24,204,0,0" TextWrapping="Wrap" Text="Tenant Name" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="24,233,0,0" TextWrapping="Wrap" Text="Deployment Profile" VerticalAlignment="Top"/> <TextBox x:Name="JSONTextBoxSavePath" HorizontalAlignment="Left" Height="23" Margin="26,345,0,0" TextWrapping="Wrap" Text="$PSScriptRoot\Autopilot" VerticalAlignment="Top" Width="499" IsEnabled="False"/> <TextBlock HorizontalAlignment="Left" Margin="26,275,0,0" TextWrapping="Wrap" Text="To download a new Autopilot profile from Intune, click select to choose the folder to save the file to. Then click Retrieve Profile." VerticalAlignment="Top" Height="48" Width="331"/> <TextBlock HorizontalAlignment="Left" Margin="27,328,0,0" TextWrapping="Wrap" Text="Path to save file:" VerticalAlignment="Top"/> <Button x:Name="JSONButtonSavePath" Content="Select" HorizontalAlignment="Left" Margin="450,373,0,0" VerticalAlignment="Top" Width="75"/> <Button x:Name="JSONButtonRetrieve" Content="Retrieve Profile" HorizontalAlignment="Left" Margin="382,275,0,0" VerticalAlignment="Top" Width="130"/> </Grid> </TabItem> <TabItem Header="Source WIM" Margin="0" MinWidth="100"> <Grid> <TextBox x:Name="SourceWIMSelectWIMTextBox" HorizontalAlignment="Left" Height="25" Margin="26,98,0,0" TextWrapping="Wrap" Text="Select WIM File" VerticalAlignment="Top" Width="500" IsEnabled="False" Grid.ColumnSpan="2"/> <Label Content="Source Wim " HorizontalAlignment="Left" Height="25" Margin="26,70,0,0" VerticalAlignment="Top" Width="100"/> <TextBlock HorizontalAlignment="Left" Margin="26,20,0,0" TextWrapping="Wrap" Text="Select the WIM file, and then Edition, that will serve as the base for the custom WIM." VerticalAlignment="Top" Height="42" Width="353" Grid.ColumnSpan="2"/> <Button x:Name="SourceWIMSelectButton" Content="Select" HorizontalAlignment="Left" Height="25" Margin="450,142,0,0" VerticalAlignment="Top" Width="75"/> <TextBox x:Name="SourceWIMImgDesTextBox" HorizontalAlignment="Left" Height="23" Margin="94,155,0,0" TextWrapping="Wrap" Text="ImageDescription" VerticalAlignment="Top" Width="339" IsEnabled="False"/> <TextBox x:Name="SourceWimArchTextBox" HorizontalAlignment="Left" Height="23" Margin="94,183,0,0" TextWrapping="Wrap" Text="Architecture" VerticalAlignment="Top" Width="225" IsEnabled="False"/> <TextBox x:Name="SourceWimVerTextBox" HorizontalAlignment="Left" Height="23" Margin="94,211,0,0" TextWrapping="Wrap" Text="Version" VerticalAlignment="Top" Width="225" IsEnabled="False"/> <TextBox x:Name="SourceWimSPBuildTextBox" HorizontalAlignment="Left" Height="23" Margin="94,239,0,0" TextWrapping="Wrap" Text="SPBuild" VerticalAlignment="Top" Width="225" IsEnabled="False"/> <TextBox x:Name="SourceWimLangTextBox" HorizontalAlignment="Left" Height="23" Margin="94,267,0,0" TextWrapping="Wrap" Text="Languages" VerticalAlignment="Top" Width="225" IsEnabled="False"/> <Label Content="Edition" HorizontalAlignment="Left" Height="30" Margin="22,151,0,0" VerticalAlignment="Top" Width="68"/> <Label Content="Arch" HorizontalAlignment="Left" Height="30" Margin="22,183,0,0" VerticalAlignment="Top" Width="68"/> <Label Content="Version" HorizontalAlignment="Left" Height="30" Margin="22,211,0,0" VerticalAlignment="Top" Width="68"/> <Label Content="Patch Level" HorizontalAlignment="Left" Height="30" Margin="22,239,0,0" VerticalAlignment="Top" Width="68"/> <Label Content="Languages" HorizontalAlignment="Left" Height="30" Margin="22,267,0,0" VerticalAlignment="Top" Width="68"/> <TextBox x:Name="SourceWimIndexTextBox" HorizontalAlignment="Left" Height="23" Margin="94,297,0,0" TextWrapping="Wrap" Text="Index" VerticalAlignment="Top" Width="225" IsEnabled="False"/> <Label Content="Index" HorizontalAlignment="Left" Height="30" Margin="22,297,0,0" VerticalAlignment="Top" Width="68"/> </Grid> </TabItem> <TabItem Header="Customizations" Height="20" MinWidth="100"> <Grid> <CheckBox x:Name="CustomCBLangPacks" Content="Inject Language Packs" HorizontalAlignment="Left" Margin="29,37,0,0" VerticalAlignment="Top"/> <Button x:Name="CustomBLangPacksSelect" Content="Select" HorizontalAlignment="Left" Margin="251,37,0,0" VerticalAlignment="Top" Width="132" IsEnabled="False"/> <ListBox x:Name="CustomLBLangPacks" HorizontalAlignment="Left" Height="135" Margin="29,74,0,0" VerticalAlignment="Top" Width="355"/> <TextBlock HorizontalAlignment="Left" Margin="32,55,0,0" TextWrapping="Wrap" Text="Selected LP's" VerticalAlignment="Top" Width="206"/> <CheckBox x:Name="CustomCBFOD" Content="Inject Features on Demand" HorizontalAlignment="Left" Margin="419,126,0,0" VerticalAlignment="Top"/> <Button x:Name="CustomBFODSelect" Content="Select" HorizontalAlignment="Left" Margin="625,125,0,0" VerticalAlignment="Top" Width="133" IsEnabled="False"/> <ListBox x:Name="CustomLBFOD" HorizontalAlignment="Left" Height="224" Margin="419,171,0,0" VerticalAlignment="Top" Width="340"/> <TextBlock HorizontalAlignment="Left" Margin="421,147,0,0" TextWrapping="Wrap" Text="Select from imported Features" VerticalAlignment="Top" Width="206"/> <CheckBox x:Name="CustomCBLEP" Content="Inject Local Experience Packs" HorizontalAlignment="Left" Margin="32,217,0,0" VerticalAlignment="Top"/> <Button x:Name="CustomBLEPSelect" Content="Select" HorizontalAlignment="Left" Margin="251,218,0,0" VerticalAlignment="Top" Width="132" IsEnabled="False"/> <ListBox x:Name="CustomLBLEP" HorizontalAlignment="Left" Height="137" Margin="29,258,0,0" VerticalAlignment="Top" Width="355"/> <TextBlock HorizontalAlignment="Left" Margin="32,237,0,0" TextWrapping="Wrap" Text="Selected LXP's" VerticalAlignment="Top" Width="206"/> <CheckBox x:Name="MISDotNetCheckBox" Content="Inject .Net 3.5" HorizontalAlignment="Left" Margin="418,49,0,0" VerticalAlignment="Top"/> <CheckBox x:Name="MISOneDriveCheckBox" Content="Update OneDrive client" HorizontalAlignment="Left" Margin="418,74,0,0" VerticalAlignment="Top"/> <CheckBox x:Name="UpdatesEnableCheckBox" Content="Enable Updates" HorizontalAlignment="Left" Margin="580,49,0,0" VerticalAlignment="Top" ClickMode="Press"/> </Grid> </TabItem> <TabItem x:Name="AppTab" Header ="App Removal" Height="20" MinWidth="100"> <Grid> <TextBox x:Name="AppxTextBox" TextWrapping="Wrap" Text="Select the apps to remove..." Margin="21,85,252.2,22.8" VerticalScrollBarVisibility="Visible"/> <TextBlock HorizontalAlignment="Left" Margin="21,65,0,0" TextWrapping="Wrap" Text="Selected app packages to remove:" VerticalAlignment="Top" Height="15" Width="194"/> <CheckBox x:Name="AppxCheckBox" Content="Enable app removal" HorizontalAlignment="Left" Margin="21,33,0,0" VerticalAlignment="Top"/> <Button x:Name="AppxButton" Content="Select" HorizontalAlignment="Left" Margin="202,33,0,0" VerticalAlignment="Top" Width="75"/> </Grid> </TabItem> <TabItem x:Name="CustomTab" Header="Custom" MinWidth="100"> <Grid> <TextBox x:Name="CustomTBFile" HorizontalAlignment="Left" Height="23" Margin="49,157,0,0" TextWrapping="Wrap" Text="PowerShell Script" VerticalAlignment="Top" Width="501" IsEnabled="False"/> <TextBox x:Name="CustomTBParameters" HorizontalAlignment="Left" Height="23" Margin="49,207,0,0" TextWrapping="Wrap" Text="Parameters" VerticalAlignment="Top" Width="501" IsEnabled="False"/> <Button x:Name="CustomBSelectPath" Content="Select" HorizontalAlignment="Left" Margin="566,158,0,0" VerticalAlignment="Top" Width="75" IsEnabled="False"/> <CheckBox x:Name="CustomCBRunScript" Content="Run Script" HorizontalAlignment="Left" Margin="49,102,0,0" VerticalAlignment="Top"/> <ComboBox x:Name="CustomCBScriptTiming" HorizontalAlignment="Left" Margin="163,102,0,0" VerticalAlignment="Top" Width="172" IsEnabled="False"/> <CheckBox x:Name="MISCBPauseMount" Content="Pause after mounting" HorizontalAlignment="Left" Margin="49,42,0,0" VerticalAlignment="Top"/> <CheckBox x:Name="MISCBPauseDismount" Content="Pause before dismounting" HorizontalAlignment="Left" Margin="49,71,0,0" VerticalAlignment="Top"/> </Grid> </TabItem> <TabItem Header="Make It So" Height="20" MinWidth="100"> <Grid> <Button x:Name="MISFolderButton" Content="Select" HorizontalAlignment="Left" Margin="444,155,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="0.39,-2.647"/> <TextBox x:Name="MISWimNameTextBox" HorizontalAlignment="Left" Height="25" Margin="20,85,0,0" TextWrapping="Wrap" Text="Enter Target WIM Name" VerticalAlignment="Top" Width="500"/> <TextBox x:Name="MISDriverTextBox" HorizontalAlignment="Left" Height="23" Margin="136,345,0,0" TextWrapping="Wrap" Text="Driver Y/N" VerticalAlignment="Top" Width="120" IsEnabled="False"/> <Label Content="Driver injection?" HorizontalAlignment="Left" Height="30" Margin="29,343,0,0" VerticalAlignment="Top" Width="101"/> <TextBox x:Name="MISJSONTextBox" HorizontalAlignment="Left" Height="23" Margin="136,374,0,0" TextWrapping="Wrap" Text="JSON Select Y/N" VerticalAlignment="Top" Width="120" IsEnabled="False"/> <Label Content="JSON injection?" HorizontalAlignment="Left" Margin="29,372,0,0" VerticalAlignment="Top" Width="102"/> <TextBox x:Name="MISWimFolderTextBox" HorizontalAlignment="Left" Height="23" Margin="20,119,0,0" TextWrapping="Wrap" Text="$PSScriptRoot\CompletedWIMs" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <TextBlock HorizontalAlignment="Left" Margin="20,20,0,0" TextWrapping="Wrap" Text="Enter a name, and select a destination forlder, for the image to be created. Once complete, and build parameters verified, click "Make it so!" to start the build." VerticalAlignment="Top" Height="60" Width="353"/> <Button x:Name="MISMakeItSoButton" Content="Make it so!" HorizontalAlignment="Left" Margin="400,20,0,0" VerticalAlignment="Top" Width="120" Height="29" FontSize="16"/> <TextBox x:Name="MISMountTextBox" HorizontalAlignment="Left" Height="25" Margin="19,219,0,0" TextWrapping="Wrap" Text="$PSScriptRoot\Mount" VerticalAlignment="Top" Width="500" IsEnabled="False"/> <Label Content="Mount Path" HorizontalAlignment="Left" Margin="19,194,0,0" VerticalAlignment="Top" Height="25" Width="100"/> <Button x:Name="MISMountSelectButton" Content="Select" HorizontalAlignment="Left" Margin="444,255,0,0" VerticalAlignment="Top" Width="75" Height="25"/> <Label Content="Update injection?" HorizontalAlignment="Left" Margin="29,311,0,0" VerticalAlignment="Top" Width="109"/> <TextBox x:Name="MISUpdatesTextBox" HorizontalAlignment="Left" Height="23" Margin="136,314,0,0" TextWrapping="Wrap" Text="Updates Y/N" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.171,0.142" IsEnabled="False"/> <Label Content="App removal?" HorizontalAlignment="Left" Margin="29,280,0,0" VerticalAlignment="Top" Width="109"/> <TextBox x:Name="MISAppxTextBox" HorizontalAlignment="Left" Height="23" Margin="136,283,0,0" TextWrapping="Wrap" Text="Updates Y/N" VerticalAlignment="Top" Width="120" RenderTransformOrigin="0.171,0.142" IsEnabled="False"/> </Grid> </TabItem> <TabItem Header="Save/Load" Height="20" MinWidth="102"> <Grid> <TextBox x:Name="SLSaveFileName" HorizontalAlignment="Left" Height="25" Margin="26,85,0,0" TextWrapping="Wrap" Text="Name for saved configuration..." VerticalAlignment="Top" Width="500"/> <TextBlock HorizontalAlignment="Left" Margin="26,38,0,0" TextWrapping="Wrap" Text="Provide a name for the saved configuration" VerticalAlignment="Top" Height="42" Width="353"/> <Button x:Name="SLSaveButton" Content="Save" HorizontalAlignment="Left" Margin="451,127,0,0" VerticalAlignment="Top" Width="75"/> <Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Left" Height="1" Margin="0,216,0,0" VerticalAlignment="Top" Width="785"/> <TextBox x:Name="SLLoadTextBox" HorizontalAlignment="Left" Height="23" Margin="26,308,0,0" TextWrapping="Wrap" Text="Select configuration file to load" VerticalAlignment="Top" Width="500"/> <Button x:Name="SLLoadButton" Content="Load" HorizontalAlignment="Left" Margin="451,351,0,0" VerticalAlignment="Top" Width="75"/> <TextBlock HorizontalAlignment="Left" Margin="26,279,0,0" TextWrapping="Wrap" Text="Select configuration file to load" VerticalAlignment="Top" Width="353"/> </Grid> </TabItem> </TabControl> </Grid> <Window.TaskbarItemInfo> <TaskbarItemInfo/> </Window.TaskbarItemInfo> </Window> "@ $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace "x:N", 'N' -replace '^<Win.*', '<Window' [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [xml]$XAML = $inputXML #Read XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try { $Form = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning "Unable to parse XML, with error: $($Error[0])`n Ensure that there are NO SelectionChanged or TextChanged properties in your textboxes (PowerShell cannot process them)" throw } #=========================================================================== # Load XAML Objects In PowerShell #=========================================================================== $xaml.SelectNodes("//*[@Name]") | % { "trying item $($_.Name)" | out-null; try { Set-Variable -Name "WPF$($_.Name)" -Value $Form.FindName($_.Name) -ErrorAction Stop } catch { throw } } #Section to do the icon magic ################################################### $base64 = "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" # Create a streaming image by streaming the base64 string to a bitmap streamsource $bitmap = New-Object System.Windows.Media.Imaging.BitmapImage $bitmap.BeginInit() $bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($base64) $bitmap.EndInit() $bitmap.Freeze() # This is the icon in the upper left hand corner of the app $form.Icon = $bitmap # This is the toolbar icon and description $form.TaskbarItemInfo.Overlay = $bitmap $form.TaskbarItemInfo.Description = "WIM Witch - $wwscirptver" ################################################### Function Get-FormVariables { if ($global:ReadmeDisplay -ne $true) { Write-host "If you need to reference this display again, run Get-FormVariables" -ForegroundColor Yellow; $global:ReadmeDisplay = $true } #write-host "Found the following interactable elements from our form" -ForegroundColor Cyan get-variable WPF* } #Get-FormVariables #=========================================================================== # Functions for Controls #=========================================================================== #Funtion to select mounting directory Function SelectMountDir { Add-Type -AssemblyName System.Windows.Forms $browser = New-Object System.Windows.Forms.FolderBrowserDialog $browser.Description = "Select the mount folder" $null = $browser.ShowDialog() $MountDir = $browser.SelectedPath $WPFMISMountTextBox.text = $MountDir check-mountpath -path $WPFMISMountTextBox.text update-log -Data "Mount directory selected" -Class Information } #Function to select Source WIM Function SelectSourceWIM { $SourceWIM = New-Object System.Windows.Forms.OpenFileDialog -Property @{ #InitialDirectory = [Environment]::GetFolderPath('Desktop') InitialDirectory = "$PSScriptRoot\imports\wim" Filter = 'WIM (*.wim)|' } $null = $SourceWIM.ShowDialog() $WPFSourceWIMSelectWIMTextBox.text = $SourceWIM.FileName if ($SourceWIM.FileName -notlike "*.wim") { update-log -Data "A WIM file not selected. Please select a valid file to continue." -Class Warning return } #Select the index $ImageFull = @(get-windowsimage -ImagePath $WPFSourceWIMSelectWIMTextBox.text) $a = $ImageFull | Out-GridView -Title "Choose an Image Index" -Passthru $IndexNumber = $a.ImageIndex #write-host $IndexNumber if ($indexnumber -eq $null) { update-log -Data "Index not selected. Reselect the WIM file to select an index" -Class Warning return } import-wiminfo -IndexNumber $IndexNumber } function import-wiminfo($IndexNumber) { Update-Log -Data "Importing Source WIM Info" -Class Information try { #Gets WIM metadata to populate fields on the Source tab. $ImageInfo = get-windowsimage -ImagePath $WPFSourceWIMSelectWIMTextBox.text -index $IndexNumber -ErrorAction Stop } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "The WIM file selected may be borked. Try a different one" -Class Warning Return } $text = "WIM file selected: " + $SourceWIM.FileName Update-Log -data $text -Class Information $text = "Edition selected: " + $ImageInfo.ImageName Update-Log -data $text -Class Information $ImageIndex = $IndexNumber $WPFSourceWIMImgDesTextBox.text = $ImageInfo.ImageName $WPFSourceWimVerTextBox.Text = $ImageInfo.Version $WPFSourceWimSPBuildTextBox.text = $ImageInfo.SPBuild $WPFSourceWimLangTextBox.text = $ImageInfo.Languages $WPFSourceWimIndexTextBox.text = $ImageIndex if ($ImageInfo.Architecture -eq 9) { $WPFSourceWimArchTextBox.text = 'x64' } Else { $WPFSourceWimArchTextBox.text = 'x86' } if ($WPFSourceWIMImgDesTextBox.text -like "Windows Server*"){ $WPFJSONEnableCheckBox.IsChecked = $False $WPFAppxCheckBox.IsChecked = $False $WPFAppTab.IsEnabled = $False $WPFAutopilotTab.IsEnabled = $False $WPFMISAppxTextBox.text = "False" $WPFMISJSONTextBox.text = "False" $WPFMISOneDriveCheckBox.IsChecked = $False $WPFMISOneDriveCheckBox.IsEnabled = $False } Else{ $WPFAppTab.IsEnabled = $True $WPFAutopilotTab.IsEnabled = $True $WPFMISOneDriveCheckBox.IsEnabled = $True } } #Function to Select JSON File Function SelectJSONFile { $JSON = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = [Environment]::GetFolderPath('Desktop') Filter = 'JSON (*.JSON)|' } $null = $JSON.ShowDialog() $WPFJSONTextBox.Text = $JSON.FileName $text = "JSON file selected: " + $JSON.FileName update-log -Data $text -Class Information Parse-JSON -file $JSON.FileName } #Function to parse the JSON file for user valuable info Function Parse-JSON($file) { try { Update-Log -Data "Attempting to parse JSON file..." -Class Information $autopilotinfo = Get-Content $WPFJSONTextBox.Text | ConvertFrom-Json Update-Log -Data "Successfully parsed JSON file" -Class Information $WPFZtdCorrelationId.Text = $autopilotinfo.ZtdCorrelationId $WPFCloudAssignedTenantDomain.Text = $autopilotinfo.CloudAssignedTenantDomain $WPFComment_File.text = $autopilotinfo.Comment_File } catch { $WPFZtdCorrelationId.Text = "Bad file. Try Again." $WPFCloudAssignedTenantDomain.Text = "Bad file. Try Again." $WPFComment_File.text = "Bad file. Try Again." Update-Log -Data "Failed to parse JSON file. Try another" return } } #Function to select the paths for the driver fields Function SelectDriverSource($DriverTextBoxNumber) { Add-Type -AssemblyName System.Windows.Forms $browser = New-Object System.Windows.Forms.FolderBrowserDialog $browser.Description = "Select the Driver Source folder" $null = $browser.ShowDialog() $DriverDir = $browser.SelectedPath $DriverTextBoxNumber.Text = $DriverDir update-log -Data "Driver path selected: $DriverDir" -Class Information } #Function for the Make it So button Function MakeItSo ($appx) { #Check if new file name is valid, also append file extension if neccessary ###Starting MIS Preflight### check-mountpath -path $WPFMISMountTextBox.Text -clean True if (($WPFMISWimNameTextBox.Text -eq "") -or ($WPFMISWimNameTextBox.Text -eq "Enter Target WIM Name")) { update-log -Data "Enter a valid file name and then try again" -Class Error return } if ($auto -eq $false) { $checkresult = (check-name) if ($checkresult -eq "stop") { return } } if ($auto -eq $true) { $checkresult = (check-name -conflict append) if ($checkresult -eq "stop") { return } } #check for working directory, make if does not exist, delete files if they exist $FolderExist = Test-Path $PSScriptRoot\Staging -PathType Any update-log -Data "Checking to see if the staging path exists..." -Class Information try { if ($FolderExist = $False) { New-Item -ItemType Directory -Force -Path $PSScriptRoot\Staging -ErrorAction Stop update-log -Data "Path did not exist, but it does now :)" -Class Information -ErrorAction Stop } Else { Remove-Item –path $PSScriptRoot\Staging\* -Recurse -ErrorAction Stop update-log -Data "The path existed, and it has been purged." -Class Information -ErrorAction Stop } } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "Something is wrong with folder $PSScriptRoot\Staging. Try deleting manually if it exists" -Class Error return } if ($WPFJSONEnableCheckBox.IsChecked -eq $true) { Update-Log -Data "Validating existance of JSON file..." -Class Information $APJSONExists = (Test-Path $WPFJSONTextBox.Text) if ($APJSONExists -eq $true) { Update-Log -Data "JSON exists. Continuing..." -Class Information } else { Update-Log -Data "The Autopilot file could not be verified. Check it and try again." -Class Error return } } if ($WPFMISDotNetCheckBox.IsChecked -eq $true) { if ((check-dotnetexists) -eq $False) { return } } #####End of MIS Preflight################################################################### #Copy source WIM update-log -Data "Copying source WIM to the staging folder" -Class Information try { Copy-Item $WPFSourceWIMSelectWIMTextBox.Text -Destination "$PSScriptRoot\Staging" -ErrorAction Stop } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -Data "The file couldn't be copied. No idea what happened" -class Error return } update-log -Data "Source WIM has been copied to the source folder" -Class Information #Rename copied source WiM try { $wimname = Get-Item -Path $PSScriptRoot\Staging\*.wim -ErrorAction Stop Rename-Item -Path $wimname -NewName $WPFMISWimNameTextBox.Text -ErrorAction Stop update-log -Data "Copied source WIM has been renamed" -Class Information } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "The copied source file couldn't be renamed. This shouldn't have happened." -Class Error Update-Log -data "Go delete the WIM from $PSScriptRoot\Staging\, then try again" -Class Error return } #Remove the unwanted indexes remove-indexes #Mount the WIM File $wimname = Get-Item -Path $PSScriptRoot\Staging\*.wim update-log -Data "Mounting source WIM $wimname" -Class Information update-log -Data "to mount point:" -Class Information update-log -data $WPFMISMountTextBox.Text -Class Information try { Mount-WindowsImage -Path $WPFMISMountTextBox.Text -ImagePath $wimname -Index 1 -ErrorAction Stop | Out-Null } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "The WIM couldn't be mounted. Make sure the mount directory is empty" -Class Error Update-Log -Data "and that it isn't an active mount point" -Class Error return } #Pause after mounting If ($WPFMISCBPauseMount.IsChecked -eq $True){ update-log -Data "Pausing image building. Waiting on user to continue..." -Class Warning $Pause = pause-makeitso if ($Pause -eq "Yes"){update-log -data "Continuing on with making it so..." -Class Information } if ($Pause -eq "No"){update-log -data "Discarding build..." -Class Error update-log -Data "Discarding mounted WIM" -Class Warning Dismount-WindowsImage -Path $WPFMISMountTextBox.Text -discard -ErrorAction Stop | Out-Null update-log -Data "WIM has been discarded. Better luck next time." -Class Warning return } } #Run Script after mounting if (($WPFCustomCBRunScript.IsChecked -eq $True) -and ($WPFCustomCBScriptTiming.SelectedItem -eq "After image mount")){ update-log -data "Running PowerShell script..." -Class Information run-script -file $WPFCustomTBFile.text -parameter $WPFCustomTBParameters.text Update-Log -data "Script completed." -Class Information } #Language Packs and FOD if ($WPFCustomCBLangPacks.IsChecked -eq $true){ apply-LanguagePacks } else{ update-log -Data "Language Packs Injection not selected. Skipping..."} if ($WPFCustomCBLEP.IsChecked -eq $true){ apply-localexperiencepack} else{ update-log -Data "Local Experience Packs not selected. Skipping..."} if ($WPFCustomCBFOD.IsChecked -eq $true){ apply-FODs} else{ update-log -Data "Features On Demand not selected. Skipping..."} #Inject .Net Binaries if ($WPFMISDotNetCheckBox.IsChecked -eq $true) { inject-dotnet } #Copy the current OneDrive installer if ($WPFMISOneDriveCheckBox.IsChecked -eq $true) { copy-onedrive } else{ update-log -data "OneDrive agent update skipped as it was not selected" -Class Information } #Inject Autopilot JSON file if ($WPFJSONEnableCheckBox.IsChecked -eq $true) { update-log -Data "Injecting JSON file" -Class Information try { $autopilotdir = $WPFMISMountTextBox.Text + "\windows\Provisioning\Autopilot" Copy-Item $WPFJSONTextBox.Text -Destination $autopilotdir -ErrorAction Stop } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "JSON file couldn't be copied. Check to see if the correct SKU" -Class Error Update-Log -Data "of Windows has been selected" -Class Error Update-log -Data "The WIM is still mounted. You'll need to clean that up manually until" -Class Error Update-Log -data "I get around to handling that error more betterer" -Class Error Update-Log -data "- <3 Donna" -Class Error return } } else { update-log -Data "JSON not selected. Skipping JSON Injection" -Class Information } #Inject Drivers If ($WPFDriverCheckBox.IsChecked -eq $true) { DriverInjection -Folder $WPFDriverDir1TextBox.text DriverInjection -Folder $WPFDriverDir2TextBox.text DriverInjection -Folder $WPFDriverDir3TextBox.text DriverInjection -Folder $WPFDriverDir4TextBox.text DriverInjection -Folder $WPFDriverDir5TextBox.text } Else { update-log -Data "Drivers were not selected for injection. Skipping." -Class Information } #Apply Updates If ($WPFUpdatesEnableCheckBox.IsChecked -eq $true) { Apply-Updates -class "SSU" Apply-Updates -class "LCU" Apply-Updates -class "AdobeSU" Apply-Updates -class "DotNet" Apply-Updates -class "DotNetCU" } Else { Update-Log -Data "Updates not enabled" -Class Information } #Remove AppX Packages if ($WPFAppxCheckBox.IsChecked -eq $true) { remove-appx -array $appx } Else { Update-Log -Data "App removal not enabled" -Class Information } #Run Script before dismount if (($WPFCustomCBRunScript.IsChecked -eq $True) -and ($WPFCustomCBScriptTiming.SelectedItem -eq "Before image dismount")){ run-script -file $WPFCustomTBFile.text -parameter $WPFCustomTBParameters.text } #Pause before dismounting If ($WPFMISCBPauseDismount.IsChecked -eq $True){ update-log -Data "Pausing image building. Waiting on user to continue..." -Class Warning $Pause = pause-makeitso if ($Pause -eq "Yes"){update-log -data "Continuing on with making it so..." -Class Information } if ($Pause -eq "No"){update-log -data "Discarding build..." -Class Error update-log -Data "Discarding mounted WIM" -Class Warning Dismount-WindowsImage -Path $WPFMISMountTextBox.Text -discard -ErrorAction Stop | Out-Null update-log -Data "WIM has been discarded. Better luck next time." -Class Warning return } } #Copy log to mounted WIM try { update-log -Data "Attempting to copy log to mounted image" -Class Information $mountlogdir = $WPFMISMountTextBox.Text + "\windows\" Copy-Item $PSScriptRoot\logging\WIMWitch.log -Destination $mountlogdir -ErrorAction Stop $CopyLogExist = Test-Path $mountlogdir\WIMWitch.log -PathType Leaf if ($CopyLogExist -eq $true) { update-log -Data "Log filed copied successfully" -Class Information } } catch { Update-Log -data $_.Exception.Message -class Error update-log -data "Coudn't copy the log file to the mounted image." -class Error } #Dismount, commit, and move WIM update-log -Data "Dismounting WIM file, committing changes" -Class Information try { Dismount-WindowsImage -Path $WPFMISMountTextBox.Text -save -ErrorAction Stop | Out-Null } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "The WIM couldn't save. You will have to manually discard the" -Class Error Update-Log -data "mounted image manually" -Class Error return } update-log -Data "WIM dismounted" -Class Information try { update-log -Data "Exporting WIM file" -Class Information Export-WindowsImage -SourceImagePath $wimname -SourceIndex 1 -DestinationImagePath ($WPFMISWimFolderTextBox.Text + '\' + $WPFMISWimNameTextBox.Text) -DestinationName ('WW - ' + $WPFSourceWIMImgDesTextBox.text) |Out-Null } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "The WIM couldn't be exported. You can still retrieve it from staging path." -Class Error Update-Log -data "The file will be deleted when the tool is rerun." -Class Error return } update-log -Data "WIM successfully exported to target folder" -Class Information #Run Script when build complete if (($WPFCustomCBRunScript.IsChecked -eq $True) -and ($WPFCustomCBScriptTiming.SelectedItem -eq "On build completion")){ run-script -file $WPFCustomTBFile.text -parameter $WPFCustomTBParameters.text } #Copy log here try { update-log -Data "Copying build log to target folder" -Class Information Copy-Item -Path $PSScriptRoot\logging\WIMWitch.log -Destination $WPFMISWimFolderTextBox.Text -ErrorAction Stop $logold = $WPFMISWimFolderTextBox.Text + "\WIMWitch.log" $lognew = $WPFMISWimFolderTextBox.Text + "\" + $WPFMISWimNameTextBox.Text + ".log" #Put log detection code here if ((test-path -Path $lognew) -eq $true) { Update-Log -Data "A preexisting log file contains the same name. Renaming old log..." -Class Warning replace-name -file $lognew -extension ".log" } #Put log detection code here Rename-Item $logold -NewName $lognew -Force -ErrorAction Stop Update-Log -Data "Log copied successfully" -Class Information } catch { Update-Log -data $_.Exception.Message -class Error Update-Log -data "The log file couldn't be copied and renamed. You can still snag it from the source." -Class Error update-log -Data "Job's done." -Class Information return } update-log -Data "Job's done." -Class Information } #Function to assign the target directory Function SelectTargetDir { Add-Type -AssemblyName System.Windows.Forms $browser = New-Object System.Windows.Forms.FolderBrowserDialog $browser.Description = "Select the target folder" $null = $browser.ShowDialog() $TargetDir = $browser.SelectedPath $WPFMISWimFolderTextBox.text = $TargetDir #I SCREWED UP THIS VARIABLE update-log -Data "Target directory selected" -Class Information } #Function to enable logging and folder check Function Update-Log { Param( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0 )] [string]$Data, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0 )] [string]$Solution = $Solution, [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1 )] [validateset('Information', 'Warning', 'Error')] [string]$Class = "Information" ) $global:ScriptLogFilePath = $Log $LogString = "$(Get-Date) $Class - $Data" $HostString = "$(Get-Date) $Class - $Data" Add-Content -Path $Log -Value $LogString switch ($Class) { 'Information' { Write-Host $HostString -ForegroundColor Gray } 'Warning' { Write-Host $HostString -ForegroundColor Yellow } 'Error' { Write-Host $HostString -ForegroundColor Red } Default { } } #The below line is for a logging tab that was removed. If it gets put back in, reenable the line # $WPFLoggingTextBox.text = Get-Content -Path $Log -Delimiter "\n" } #Removes old log and creates all folders if does not exist Function Set-Logging { #logging folder $FileExist = Test-Path -Path $PSScriptRoot\logging\WIMWitch.Log -PathType Leaf if ($FileExist -eq $False) { New-Item -ItemType Directory -Force -Path $PSScriptRoot\Logging | Out-Null New-Item -Path $PSScriptRoot\logging -Name "WIMWitch.log" -ItemType "file" -Value "***Logging Started***" | Out-Null } Else { Remove-Item -Path $PSScriptRoot\logging\WIMWitch.log New-Item -Path $PSScriptRoot\logging -Name "WIMWitch.log" -ItemType "file" -Value "***Logging Started***" | Out-Null } #updates folder $FileExist = Test-Path -Path $PSScriptRoot\updates #-PathType Leaf if ($FileExist -eq $False) { Update-Log -Data "Updates folder does not exist. Creating..." -Class Warning New-Item -ItemType Directory -Force -Path $PSScriptRoot\updates | Out-Null Update-Log -Data "Updates folder created" -Class Information } if ($FileExist -eq $True) { Update-Log -Data "Updates folder exists" -Class Information } #staging folder $FileExist = Test-Path -Path $PSScriptRoot\Staging #-PathType Leaf if ($FileExist -eq $False) { Update-Log -Data "Staging folder does not exist. Creating..." -Class Warning New-Item -ItemType Directory -Force -Path $PSScriptRoot\Staging | Out-Null Update-Log -Data "Staging folder created" -Class Information } if ($FileExist -eq $True) { Update-Log -Data "Staging folder exists" -Class Information } #Mount folder $FileExist = Test-Path -Path $PSScriptRoot\Mount #-PathType Leaf if ($FileExist -eq $False) { Update-Log -Data "Mount folder does not exist. Creating..." -Class Warning New-Item -ItemType Directory -Force -Path $PSScriptRoot\Mount | Out-Null Update-Log -Data "Mount folder created" -Class Information } if ($FileExist -eq $True) { Update-Log -Data "Mount folder exists" -Class Information } #Completed WIMs folder $FileExist = Test-Path -Path $PSScriptRoot\CompletedWIMs #-PathType Leaf if ($FileExist -eq $False) { Update-Log -Data "CompletedWIMs folder does not exist. Creating..." -Class Warning New-Item -ItemType Directory -Force -Path $PSScriptRoot\CompletedWIMs | Out-Null Update-Log -Data "CompletedWIMs folder created" -Class Information } if ($FileExist -eq $True) { Update-Log -Data "CompletedWIMs folder exists" -Class Information } #Configurations XML folder $FileExist = Test-Path -Path $PSScriptRoot\Configs #-PathType Leaf if ($FileExist -eq $False) { Update-Log -Data "Configs folder does not exist. Creating..." -Class Warning New-Item -ItemType Directory -Force -Path $PSScriptRoot\Configs | Out-Null Update-Log -Data "Configs folder created" -Class Information } if ($FileExist -eq $True) { Update-Log -Data "Configs folder exists" -Class Information } } #Function for injecting drivers into the mounted WIM Function DriverInjection($Folder) { Function ApplyDriver($drivertoapply) { try { add-windowsdriver -Path $WPFMISMountTextBox.Text -Driver $drivertoapply -ErrorAction Stop | Out-Null Update-Log -Data "Applied $drivertoapply" -Class Information } catch { update-log -Data "Couldn't apply $drivertoapply" -Class Warning } } #This filters out invalid paths, such as the default value $testpath = Test-Path $folder -PathType Container If ($testpath -eq $false) { return } If ($testpath -eq $true) { update-log -data "Applying drivers from $folder" -class Information Get-ChildItem $Folder -Recurse -Filter "*inf" | ForEach-Object { applydriver $_.FullName } update-log -Data "Completed driver injection from $folder" -Class Information } } #Function to retrieve OSDUpdate Version Function Get-OSDBInstallation { update-log -Data "Getting OSD Installation information" -Class Information try { Import-Module -name OSDUpdate -ErrorAction Stop } catch { $WPFUpdatesOSDBVersion.Text = "Not Installed" Update-Log -Data "OSD Update is not installed" -Class Warning Return } try { $OSDBVersion = get-module -name OSDUpdate -ErrorAction Stop $WPFUpdatesOSDBVersion.Text = $OSDBVersion.Version $text = $osdbversion.version Update-Log -data "Installed version of OSD Update is $text" -Class Information Return } catch { Update-Log -Data "Whatever you were hoping for, you didn’t get :)" -Class Error Return } } #Function to retrieve OSDSUS Version Function Get-OSDSUSInstallation { update-log -Data "Getting OSDSUS Installation information" -Class Information try { Import-Module -name OSDSUS -ErrorAction Stop } catch { $WPFUpdatesOSDSUSVersion.Text = "Not Installed" Update-Log -Data "OSDSUS is not installed" -Class Warning Return } try { $OSDSUSVersion = get-module -name OSDSUS -ErrorAction Stop $WPFUpdatesOSDSUSVersion.Text = $OSDSUSVersion.Version $text = $osdsusversion.version Update-Log -data "Installed version of OSDSUS is $text" -Class Information Return } catch { Update-Log -Data "Whatever you were hoping for, you didn’t get :)" -Class Error Return } } #Function to retrieve current OSDUpdate Version Function Get-OSDBCurrentVer { Update-Log -Data "Checking for the most current OSDUpdate version available" -Class Information try { $OSDBCurrentVer = find-module -name OSDUpdate -ErrorAction Stop $WPFUpdatesOSDBCurrentVerTextBox.Text = $OSDBCurrentVer.version $text = $OSDBCurrentVer.version update-log -data "$text is the most current version" -class Information Return } catch { $WPFUpdatesOSDBCurrentVerTextBox.Text = "Network Error" Return } } #Function to retrieve current OSDUSUS Version Function Get-OSDSUSCurrentVer { Update-Log -Data "Checking for the most current OSDSUS version available" -Class Information try { $OSDSUSCurrentVer = find-module -name OSDSUS -ErrorAction Stop $WPFUpdatesOSDSUSCurrentVerTextBox.Text = $OSDSUSCurrentVer.version $text = $OSDSUSCurrentVer.version update-log -data "$text is the most current version" -class Information Return } catch { $WPFUpdatesOSDSUSCurrentVerTextBox.Text = "Network Error" Return } } #Function to update or install OSDUpdate Function update-OSDB { if ($WPFUpdatesOSDBVersion.Text -eq "Not Installed") { Update-Log -Data "Attempting to install and import OSD Update" -Class Information try { Install-Module OSDUpdate -Force -ErrorAction Stop #Write-Host "Installed module" Update-Log -data "OSD Update module has been installed" -Class Information Import-Module -Name OSDUpdate -Force -ErrorAction Stop #Write-Host "Imported module" Update-Log -Data "OSD Update module has been imported" -Class Information Update-Log -Data "****************************************************************************" -Class Warning Update-Log -Data "Please close WIM Witch and all PowerShell windows, then rerun to continue..." -Class Warning Update-Log -Data "****************************************************************************" -Class Warning $WPFUpdatesOSDBClosePowerShellTextBlock.visibility = "Visible" Return } catch { $WPFUpdatesOSDBVersion.Text = "Inst Fail" Update-Log -Data "Couldn't install OSD Update" -Class Error Update-Log -data $_.Exception.Message -class Error Return } } If ($WPFUpdatesOSDBVersion.Text -gt "1.0.0") { Update-Log -data "Attempting to update OSD Update" -class Information try { Update-ModuleOSDUpdate -ErrorAction Stop Update-Log -Data "Updated OSD Update" -Class Information Update-Log -Data "****************************************************************************" -Class Warning Update-Log -Data "Please close WIM Witch and all PowerShell windows, then rerun to continue..." -Class Warning Update-Log -Data "****************************************************************************" -Class Warning $WPFUpdatesOSDBClosePowerShellTextBlock.visibility = "Visible" get-OSDBInstallation return } catch { $WPFUpdatesOSDBCurrentVerTextBox.Text = "OSDB Err" Return } } } #Function to update or install OSDSUS Function update-OSDSUS { if ($WPFUpdatesOSDSUSVersion.Text -eq "Not Installed") { Update-Log -Data "Attempting to install and import OSDSUS" -Class Information try { Install-Module OSDUpdate -Force -ErrorAction Stop Update-Log -data "OSDSUS module has been installed" -Class Information Import-Module -Name OSDUpdate -Force -ErrorAction Stop Update-Log -Data "OSDSUS module has been imported" -Class Information Update-Log -Data "****************************************************************************" -Class Warning Update-Log -Data "Please close WIM Witch and all PowerShell windows, then rerun to continue..." -Class Warning Update-Log -Data "****************************************************************************" -Class Warning $WPFUpdatesOSDBClosePowerShellTextBlock.visibility = "Visible" Return } catch { $WPFUpdatesOSDSUSVersion.Text = "Inst Fail" Update-Log -Data "Couldn't install OSDSUS" -Class Error Update-Log -data $_.Exception.Message -class Error Return } } If ($WPFUpdatesOSDSUSVersion.Text -gt "1.0.0") { Update-Log -data "Attempting to update OSDSUS" -class Information try { uninstall-module -Name osdsus -AllVersions -force install-module -name osdsus -force Update-Log -Data "Updated OSDSUS" -Class Information Update-Log -Data "****************************************************************************" -Class Warning Update-Log -Data "Please close WIM Witch and all PowerShell windows, then rerun to continue..." -Class Warning Update-Log -Data "****************************************************************************" -Class Warning $WPFUpdatesOSDBClosePowerShellTextBlock.visibility = "Visible" get-OSDSUSInstallation return } catch { $WPFUpdatesOSDSUSCurrentVerTextBox.Text = "OSDSUS Err" Return } } } #Function to compare OSDBuilder Versions Function compare-OSDBuilderVer { Update-Log -data "Comparing OSD Update module versions" -Class Information if ($WPFUpdatesOSDBVersion.Text -eq "Not Installed") { Return } If ($WPFUpdatesOSDBVersion.Text -eq $WPFUpdatesOSDBCurrentVerTextBox.Text) { Update-Log -Data "OSD Update is up to date" -class Information Return } $WPFUpdatesOSDBOutOfDateTextBlock.Visibility = "Visible" Update-Log -Data "OSD Update appears to be out of date. Run the upgrade function from within WIM Witch to resolve" -class Warning Return } #Function to compare OSDSUS Versions Function compare-OSDSUSVer { Update-Log -data "Comparing OSDSUS module versions" -Class Information if ($WPFUpdatesOSDSUSVersion.Text -eq "Not Installed") { Return } If ($WPFUpdatesOSDSUSVersion.Text -eq $WPFUpdatesOSDSUSCurrentVerTextBox.Text) { Update-Log -Data "OSDSUS is up to date" -class Information Return } $WPFUpdatesOSDBOutOfDateTextBlock.Visibility = "Visible" Update-Log -Data "OSDSUS appears to be out of date. Run the upgrade function from within WIM Witch to resolve" -class Warning Return } #Function to check for superceded updates Function check-superceded($action, $OS, $Build) { Update-Log -Data "Checking WIM Witch Update store for superseded updates" -Class Information $path = $PSScriptRoot + '\updates\' + $OS + '\' + $Build + '\' #sets base path if ((Test-Path -Path $path) -eq $false){ update-log -Data "No updates found, likely not yet downloaded. Skipping supersedense check..." -Class Warning return} $Children = Get-ChildItem -Path $path #query sub directories foreach ($Children in $Children) { $path1 = $path + $Children $sprout = Get-ChildItem -Path $path1 foreach ($sprout in $sprout) { $path3 = $path1 + '\' + $sprout $fileinfo = get-childitem -path $path3 foreach ($file in $fileinfo){ $StillCurrent = Get-OSDUpdate | Where-Object { $_.FileName -eq $file } If ($StillCurrent -eq $null) { update-log -data "$file no longer current" -Class Warning if ($action -eq 'delete') { Update-Log -data "Deleting $path3" -class Warning remove-item -path $path3 -Recurse -Force } if ($action -eq 'audit') { $WPFUpdatesOSDBSupercededExistTextBlock.Visibility = "Visible" Return } } else { Update-Log -data "$file is stil current" -Class Information } } } } Update-Log -data "Supersedense check complete." -Class Information } #Function to download new patches Function download-patches($build,$OS) { Update-Log -Data "Downloading SSU updates for $OS $build" -Class Information Get-OSDUpdate | Where-Object { $_.UpdateOS -eq $OS -and $_.UpdateArch -eq 'x64' -and $_.UpdateBuild -eq $build -and $_.UpdateGroup -eq 'SSU' } | Get-DownOSDUpdate -DownloadPath $PSScriptRoot\updates\$OS\$build\SSU Update-Log -Data "Downloading AdobeSU updates for $OS $build" -Class Information Get-OSDUpdate | Where-Object { $_.UpdateOS -eq $OS -and $_.UpdateArch -eq 'x64' -and $_.UpdateBuild -eq $build -and $_.UpdateGroup -eq 'AdobeSU' } | Get-DownOSDUpdate -DownloadPath $PSScriptRoot\updates\$OS\$build\AdobeSU Update-Log -Data "Downloading LCU updates for $OS $build" -Class Information Get-OSDUpdate | Where-Object { $_.UpdateOS -eq $OS -and $_.UpdateArch -eq 'x64' -and $_.UpdateBuild -eq $build -and $_.UpdateGroup -eq 'LCU' } | Get-DownOSDUpdate -DownloadPath $PSScriptRoot\updates\$OS\$build\LCU Update-Log -Data "Downloading .Net updates for $OS $build" -Class Information Get-OSDUpdate | Where-Object { $_.UpdateOS -eq $OS -and $_.UpdateArch -eq 'x64' -and $_.UpdateBuild -eq $build -and $_.UpdateGroup -eq 'DotNet' } | Get-DownOSDUpdate -DownloadPath $PSScriptRoot\updates\$OS\$build\DotNet Update-Log -Data "Downloading .Net CU updates for $OS $build" -Class Information Get-OSDUpdate | Where-Object { $_.UpdateOS -eq $OS -and $_.UpdateArch -eq 'x64' -and $_.UpdateBuild -eq $build -and $_.UpdateGroup -eq 'DotNetCU' } | Get-DownOSDUpdate -DownloadPath $PSScriptRoot\updates\$OS\$build\DotNetCU Update-Log -Data "Downloading completed for $OS $build" -Class Information } #Function to remove superceded updates and initate new patch download Function update-patchsource { Update-Log -Data "attempting to start download function" -Class Information if ($WPFUpdatesW10Main.IsChecked -eq $true){ if ($WPFUpdatesW10_1909.IsChecked -eq $true){ check-superceded -action delete -build 1909 -OS "Windows 10" download-patches -build 1909 -OS "Windows 10"} if ($WPFUpdatesW10_1903.IsChecked -eq $true){ check-superceded -action delete -build 1903 -OS "Windows 10" download-patches -build 1903 -OS "Windows 10"} if ($WPFUpdatesW10_1809.IsChecked -eq $true){ check-superceded -action delete -build 1809 -OS "Windows 10" download-patches -build 1809 -OS "Windows 10"} if ($WPFUpdatesW10_1803.IsChecked -eq $true){ check-superceded -action delete -build 1803 -OS "Windows 10" download-patches -build 1803 -OS "Windows 10"} if ($WPFUpdatesW10_1709.IsChecked -eq $true){ check-superceded -action delete -build 1709 -OS "Windows 10" download-patches -build 1709 -OS "Windows 10"} download-onedrive } if ($WPFUpdatesS2019.IsChecked -eq $true){ check-superceded -action delete -build 1809 -OS "Windows Server 2019" download-patches -build 1809 -OS "Windows Server 2019"} if ($WPFUpdatesS2016.IsChecked -eq $true){ check-superceded -action delete -build 1607 -OS "Windows Server 2016" download-patches -build 1607 -OS "Windows Server 2016"} } #Function to apply updates to mounted WIM Function Apply-Updates($class) { if (($class -eq 'AdobeSU') -and ($WPFSourceWIMImgDesTextBox.text -like "Windows Server 20*") -and ($WPFSourceWIMImgDesTextBox.text -notlike "*(Desktop Experience)")){ update-log -Data "Skipping Adobe updates for Server Core build" -Class Information return} If ($WPFSourceWIMImgDesTextBox.text -like "Windows Server 2016*"){$OS = "Windows Server 2016"} If ($WPFSourceWIMImgDesTextBox.text -like "Windows Server 2019*"){$OS = "Windows Server 2019"} If ($WPFSourceWIMImgDesTextBox.text -like "Windows 10*"){$OS = "Windows 10"} If ($WPFSourceWimVerTextBox.text -like "10.0.14393.*") { $buildnum = 1607 } If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $buildnum = 1809 } If ($WPFSourceWimVerTextBox.text -like "10.0.17134.*") { $buildnum = 1803 } If ($WPFSourceWimVerTextBox.text -like "10.0.16299.*") { $buildnum = 1709 } If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { $mountdir = $WPFMISMountTextBox.Text reg LOAD HKLM\OFFLINE $mountdir\Windows\System32\Config\SOFTWARE | Out-Null $regvalues = (Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\OFFLINE\Microsoft\Windows NT\CurrentVersion\" ) $buildnum = $regvalues.ReleaseId reg UNLOAD HKLM\OFFLINE | Out-Null} $path = $PSScriptRoot + '\updates\' + $OS + '\' + $buildnum + '\' + $class + '\' $Children = Get-ChildItem -Path $path foreach ($Children in $Children) { $compound = $path + $Children update-log -Data "Applying $Children" -Class Information Add-WindowsPackage -path $WPFMISMountTextBox.Text -PackagePath $compound | Out-Null } } #Function to select AppX packages to yank Function Select-Appx { $appx1903 = @("Microsoft.BingWeather_4.25.20211.0_neutral_~_8wekyb3d8bbwe" "Microsoft.DesktopAppInstaller_2019.125.2243.0_neutral_~_8wekyb3d8bbwe" "Microsoft.GetHelp_10.1706.13331.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Getstarted_7.3.20251.0_neutral_~_8wekyb3d8bbwe" "Microsoft.HEIFImageExtension_1.0.13472.0_x64__8wekyb3d8bbwe" "Microsoft.Messaging_2019.125.32.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Microsoft3DViewer_5.1902.20012.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftOfficeHub_18.1901.1141.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftSolitaireCollection_4.2.11280.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftStickyNotes_3.1.53.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MixedReality.Portal_2000.19010.1151.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MSPaint_2019.213.1858.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Office.OneNote_16001.11126.20076.0_neutral_~_8wekyb3d8bbwe" "Microsoft.OneConnect_5.1902.361.0_neutral_~_8wekyb3d8bbwe" "Microsoft.People_2019.123.2346.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Print3D_3.3.311.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ScreenSketch_2018.1214.231.0_neutral_~_8wekyb3d8bbwe" "Microsoft.SkypeApp_14.35.152.0_neutral_~_kzf8qxf38zg5c" "Microsoft.StorePurchaseApp_11811.1001.1813.0_neutral_~_8wekyb3d8bbwe" "Microsoft.VP9VideoExtensions_1.0.13333.0_x64__8wekyb3d8bbwe" "Microsoft.Wallet_2.4.18324.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WebMediaExtensions_1.0.13321.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WebpImageExtension_1.0.12821.0_x64__8wekyb3d8bbwe" "Microsoft.Windows.Photos_2019.18114.19418.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsAlarms_2019.105.629.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsCalculator_2019.105.612.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsCamera_2018.826.78.0_neutral_~_8wekyb3d8bbwe" "Microsoft.windowscommunicationsapps_16005.11029.20108.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsFeedbackHub_2019.226.2324.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsMaps_2019.108.627.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsSoundRecorder_2019.105.618.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsStore_11811.1001.1813.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Xbox.TCUI_1.23.28002.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxApp_48.48.7001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxGameOverlay_1.32.17005.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxGamingOverlay_2.26.14003.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxIdentityProvider_12.50.6001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxSpeechToTextOverlay_1.17.29001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.YourPhone_2018.1128.231.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ZuneMusic_2019.18111.17311.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ZuneVideo_2019.18111.17311.0_neutral_~_8wekyb3d8bbwe") $appx1809 = @( "Microsoft.BingWeather_4.25.12127.0_neutral_~_8wekyb3d8bbwe" "Microsoft.DesktopAppInstaller_2018.720.2137.0_neutral_~_8wekyb3d8bbwe" "Microsoft.GetHelp_10.1706.10441.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Getstarted_6.13.11581.0_neutral_~_8wekyb3d8bbwe" "Microsoft.HEIFImageExtension_1.0.11792.0_x64__8wekyb3d8bbwe" "Microsoft.Messaging_2018.727.1430.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Microsoft3DViewer_4.1808.15012.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftOfficeHub_2017.1219.520.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftSolitaireCollection_4.1.5252.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftStickyNotes_2.0.13.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MixedReality.Portal_2000.18081.1242.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MSPaint_4.1807.12027.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Office.OneNote_16001.10228.20003.0_neutral_~_8wekyb3d8bbwe" "Microsoft.OneConnect_5.1807.1991.0_neutral_~_8wekyb3d8bbwe" "Microsoft.People_2018.516.2011.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Print3D_3.0.1521.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ScreenSketch_2018.731.48.0_neutral_~_8wekyb3d8bbwe" "Microsoft.SkypeApp_14.26.95.0_neutral_~_kzf8qxf38zg5c" "Microsoft.StorePurchaseApp_11805.1001.813.0_neutral_~_8wekyb3d8bbwe" "Microsoft.VP9VideoExtensions_1.0.12342.0_x64__8wekyb3d8bbwe" "Microsoft.Wallet_2.2.18179.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WebMediaExtensions_1.0.12341.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WebpImageExtension_1.0.11551.0_x64__8wekyb3d8bbwe" "Microsoft.Windows.Photos_2018.18051.21218.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsAlarms_2018.516.2059.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsCalculator_2018.501.612.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsCamera_2018.425.120.0_neutral_~_8wekyb3d8bbwe" "Microsoft.windowscommunicationsapps_2015.9330.21365.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsFeedbackHub_2018.822.2.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsMaps_2018.523.2143.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsSoundRecorder_2018.713.2154.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsStore_11805.1001.4913.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Xbox.TCUI_1.11.28003.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxApp_41.41.18001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxGameOverlay_1.32.17005.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxGamingOverlay_2.20.22001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxIdentityProvider_12.44.20001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxSpeechToTextOverlay_1.17.29001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.YourPhone_2018.727.2137.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ZuneMusic_2019.18052.20211.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ZuneVideo_2019.18052.20211.0_neutral_~_8wekyb3d8bbwe" ) $appx1803 = @( "Microsoft.BingWeather_4.22.3254.0_neutral_~_8wekyb3d8bbwe" "Microsoft.DesktopAppInstaller_1.8.15011.0_neutral_~_8wekyb3d8bbwe" "Microsoft.GetHelp_10.1706.10441.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Getstarted_6.9.10602.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Messaging_2018.222.2231.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Microsoft3DViewer_2.1803.8022.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftOfficeHub_2017.1219.520.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftSolitaireCollection_4.0.1301.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MicrosoftStickyNotes_2.0.13.0_neutral_~_8wekyb3d8bbwe" "Microsoft.MSPaint_3.1803.5027.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Office.OneNote_2015.8827.20991.0_neutral_~_8wekyb3d8bbwe" "Microsoft.OneConnect_4.1801.521.0_neutral_~_8wekyb3d8bbwe" "Microsoft.People_2018.215.110.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Print3D_2.0.3621.0_neutral_~_8wekyb3d8bbwe" "Microsoft.SkypeApp_12.13.274.0_neutral_~_kzf8qxf38zg5c" "Microsoft.StorePurchaseApp_11712.1801.10024.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Wallet_2.1.18009.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WebMediaExtensions_1.0.3102.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Windows.Photos_2018.18011.15918.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsAlarms_2018.302.1846.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsCalculator_2018.302.144.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsCamera_2017.1117.80.0_neutral_~_8wekyb3d8bbwe" "Microsoft.windowscommunicationsapps_2015.8827.22055.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsFeedbackHub_2018.302.2011.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsMaps_2018.209.2206.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsSoundRecorder_2018.302.1842.0_neutral_~_8wekyb3d8bbwe" "Microsoft.WindowsStore_11712.1001.2313.0_neutral_~_8wekyb3d8bbwe" "Microsoft.Xbox.TCUI_1.11.28003.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxApp_38.38.14002.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxGameOverlay_1.26.6001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxGamingOverlay_1.15.1001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxIdentityProvider_12.36.15002.0_neutral_~_8wekyb3d8bbwe" "Microsoft.XboxSpeechToTextOverlay_1.17.29001.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ZuneMusic_2019.17112.19011.0_neutral_~_8wekyb3d8bbwe" "Microsoft.ZuneVideo_2019.17112.19011.0_neutral_~_8wekyb3d8bbwe" ) $appx1709 = @( "Microsoft.BingWeather_4.21.2492.0_neutral_~_8wekyb3d8bbwe", "Microsoft.DesktopAppInstaller_1.8.4001.0_neutral_~_8wekyb3d8bbwe", "Microsoft.GetHelp_10.1706.1811.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Getstarted_5.11.1641.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Messaging_2017.815.2052.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Microsoft3DViewer_1.1707.26019.0_neutral_~_8wekyb3d8bbwe", "Microsoft.MicrosoftOfficeHub_2017.715.118.0_neutral_~_8wekyb3d8bbwe", "Microsoft.MicrosoftSolitaireCollection_3.17.8162.0_neutral_~_8wekyb3d8bbwe", "Microsoft.MicrosoftStickyNotes_1.8.2.0_neutral_~_8wekyb3d8bbwe", "Microsoft.MSPaint_2.1709.4027.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Office.OneNote_2015.8366.57611.0_neutral_~_8wekyb3d8bbwe", "Microsoft.OneConnect_3.1708.2224.0_neutral_~_8wekyb3d8bbwe", "Microsoft.People_2017.823.2207.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Print3D_1.0.2422.0_neutral_~_8wekyb3d8bbwe", "Microsoft.SkypeApp_11.18.596.0_neutral_~_kzf8qxf38zg5c", "Microsoft.StorePurchaseApp_11706.1707.7104.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Wallet_1.0.16328.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Windows.Photos_2017.37071.16410.0_neutral_~_8wekyb3d8bbwe", "Microsoft.WindowsAlarms_2017.828.2050.0_neutral_~_8wekyb3d8bbwe", "Microsoft.WindowsCalculator_2017.828.2012.0_neutral_~_8wekyb3d8bbwe", "Microsoft.WindowsCamera_2017.727.20.0_neutral_~_8wekyb3d8bbwe", "Microsoft.windowscommunicationsapps_2015.8241.41275.0_neutral_~_8wekyb3d8bbwe", "Microsoft.WindowsFeedbackHub_1.1705.2121.0_neutral_~_8wekyb3d8bbwe", "Microsoft.WindowsMaps_2017.814.2249.0_neutral_~_8wekyb3d8bbwe", "Microsoft.WindowsSoundRecorder_2017.605.2103.0_neutral_~_8wekyb3d8bbwe", "Microsoft.WindowsStore_11706.1002.94.0_neutral_~_8wekyb3d8bbwe", "Microsoft.Xbox.TCUI_1.8.24001.0_neutral_~_8wekyb3d8bbwe", "Microsoft.XboxApp_31.32.16002.0_neutral_~_8wekyb3d8bbwe", "Microsoft.XboxGameOverlay_1.20.25002.0_neutral_~_8wekyb3d8bbwe", "Microsoft.XboxIdentityProvider_2017.605.1240.0_neutral_~_8wekyb3d8bbwe", "Microsoft.XboxSpeechToTextOverlay_1.17.29001.0_neutral_~_8wekyb3d8bbwe", "Microsoft.ZuneMusic_2019.17063.24021.0_neutral_~_8wekyb3d8bbwe", "Microsoft.ZuneVideo_2019.17063.24021.0_neutral_~_8wekyb3d8bbwe" ) If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { $exappxs = write-output $appx1903 | out-gridview -title "Select apps to remove" -passthru } If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $exappxs = write-output $appx1809 | out-gridview -title "Select apps to remove" -passthru } If ($WPFSourceWimVerTextBox.text -like "10.0.17134.*") { $exappxs = write-output $appx1803 | out-gridview -title "Select apps to remove" -passthru } If ($WPFSourceWimVerTextBox.text -like "10.0.16299.*") { $exappxs = write-output $appx1709 | out-gridview -title "Select apps to remove" -passthru } if ($exappxs -eq $null) { Update-Log -Data "No apps were selected" -Class Warning } if ($exappxs -ne $null) { Update-Log -data "The following apps were selected for removal:" -Class Information Foreach ($exappx in $exappxs) { Update-Log -Data $exappx -Class Information } $WPFAppxTextBox.Text = $exappxs return $exappxs } } #Function to remove appx packages function remove-appx($array) { $exappxs = $array update-log -data "Starting AppX removal" -class Information foreach ($exappx in $exappxs) { Remove-AppxProvisionedPackage -Path $WPFMISMountTextBox.Text -PackageName $exappx | Out-Null update-log -data "Removing $exappx" -Class Information } return } #Function to remove unwanted image indexes Function remove-indexes { Update-Log -Data "Attempting to remove unwanted image indexes" -Class Information $wimname = Get-Item -Path $PSScriptRoot\Staging\*.wim Update-Log -Data "Found Image $wimname" -Class Information $IndexesAll = Get-WindowsImage -ImagePath $wimname | foreach { $_.ImageName } $IndexSelected = $WPFSourceWIMImgDesTextBox.Text foreach ($Index in $IndexesAll) { Update-Log -data "$Index is being evaluated" If ($Index -eq $IndexSelected) { Update-Log -Data "$Index is the index we want to keep. Skipping." -Class Information | Out-Null } else { update-log -data "Deleting $Index from WIM" -Class Information Remove-WindowsImage -ImagePath $wimname -Name $Index -InformationAction SilentlyContinue | Out-Null } } } #Function to select which folder to save Autopilot JSON file to Function SelectNewJSONDir { Add-Type -AssemblyName System.Windows.Forms $browser = New-Object System.Windows.Forms.FolderBrowserDialog $browser.Description = "Select the folder to save JSON" $null = $browser.ShowDialog() $SaveDir = $browser.SelectedPath $WPFJSONTextBoxSavePath.text = $SaveDir $text = "Autopilot profile save path selected: $SaveDir" update-log -Data $text -Class Information } #Function to retrieve autopilot profile from intune function get-WWAutopilotProfile ($login, $path) { function update-autopilot{ Update-Log -Data "Uninstalling old WindowsAutopilotIntune module..." -Class Warning Uninstall-Module -Name WindowsAutopilotIntune -AllVersions Update-Log -Data "Installing new WindowsAutopilotIntune module..." -Class Warning Install-Module -Name WindowsAutopilotIntune -force $AutopilotUpdate = ([System.Windows.MessageBox]::Show("WIM Witch needs to close and PowerShell needs to be restarted. Click OK to close WIM Witch.",'Updating complete.','OK','warning')) if ($AutopilotUpdate -eq "OK"){ $form.Close() exit } } Update-Log -data "Checking dependencies for Autopilot profile retrieval..." -Class Information try { Import-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -ErrorAction Stop Update-Log -Data "NuGet is installed" -Class Information } catch { Update-Log -data "NuGet is not installed. Installing now..." -Class Warning Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force Update-Log -data "NuGet is now installed" -Class Information } try { Import-Module -name AzureAD -ErrorAction Stop | Out-Null Update-Log -data "AzureAD Module is installed" -Class Information } catch { Update-Log -data "AzureAD Module is not installed. Installing now..." -Class Warning Install-Module AzureAD -Force Update-Log -data "AzureAD is now installed" -class Information } try { Import-Module -Name WindowsAutopilotIntune -ErrorAction Stop Update-Log -data "WindowsAutopilotIntune module is installed" -Class Information } catch { Update-Log -data "WindowsAutopilotIntune module is not installed. Installing now..." -Class Warning Install-Module WindowsAutopilotIntune -Force update-log -data "WindowsAutopilotIntune module is now installed." -class Information } $AutopilotInstalledVer = (get-module -name windowsautopilotintune).Version Update-Log -Data "The currently installed version of the WindowsAutopilotIntune module is $AutopilotInstalledVer" -Class Information $AutopilotLatestVersion = (find-module -Name windowsautopilotintune).version update-log -data "The latest available version of the WindowsAutopilotIntune module is $AutopilotLatestVersion" -Class Information if ($AutopilotInstalledVer -eq $AutopilotLatestVersion){ update-log -data "WindowsAutopilotIntune module is current. Continuing..." -Class Information} else{ Update-Log -data "WindowsAutopilotIntune module is out of date. Prompting the user to upgrade..." $UpgradeAutopilot = ([System.Windows.MessageBox]::Show("Would you like to update the WindowsAutopilotIntune module to version $AutopilotLatestVersion now?",'Update Autopilot Module?','YesNo','warning')) } if ($UpgradeAutopilot -eq "Yes"){ update-log -Data "User has chosen to update WindowsAutopilotIntune module" -Class Warning update-autopilot} elseif($AutopilotInstalledVer -ne $AutopilotLatestVersion){ Update-Log -data "User declined to update WindowsAutopilotIntune module. Continuing..." -Class Warning} Update-Log -data "Connecting to Intune..." -Class Information if ($AutopilotInstalledVer -lt 3.9){Connect-AutopilotIntune | out-null} else{ Connect-MSGraph | Out-Null} Update-Log -data "Connected to Intune" -Class Information Update-Log -data "Retrieving profile..." -Class Information Get-AutoPilotProfile | Out-GridView -title "Select Autopilot profile" -PassThru | ConvertTo-AutoPilotConfigurationJSON | Out-File $path\AutopilotConfigurationFile.json -Encoding ASCII $text = $path + "\AutopilotConfigurationFile.json" Update-Log -data "Profile successfully created at $text" -Class Information } #Function to save current configuration function save-config($filename) { $CurrentConfig = @{ SourcePath = $WPFSourceWIMSelectWIMTextBox.text SourceIndex = $WPFSourceWimIndexTextBox.text SourceEdition = $WPFSourceWIMImgDesTextBox.text UpdatesEnabled = $WPFUpdatesEnableCheckBox.IsChecked AutopilotEnabled = $WPFJSONEnableCheckBox.IsChecked AutopilotPath = $WPFJSONTextBox.text DriversEnabled = $WPFDriverCheckBox.IsChecked DriverPath1 = $WPFDriverDir1TextBox.text DriverPath2 = $WPFDriverDir2TextBox.text DriverPath3 = $WPFDriverDir3TextBox.text DriverPath4 = $WPFDriverDir4TextBox.text DriverPath5 = $WPFDriverDir5TextBox.text AppxIsEnabled = $WPFAppxCheckBox.IsChecked AppxSelected = $WPFAppxTextBox.Text WIMName = $WPFMISWimNameTextBox.text WIMPath = $WPFMISWimFolderTextBox.text MountPath = $WPFMISMountTextBox.text DotNetEnabled = $WPFMISDotNetCheckBox.IsChecked OneDriveEnabled = $WPFMISOneDriveCheckBox.IsChecked LPsEnabled = $WPFCustomCBLangPacks.IsChecked LXPsEnabled = $WPFCustomCBLEP.IsChecked FODsEnabled = $WPFCustomCBFOD.IsChecked LPListBox = $WPFCustomLBLangPacks.items LXPListBox = $WPFCustomLBLEP.Items FODListBox = $WPFCustomLBFOD.Items } Update-Log -data "Saving configuration file $filename" -Class Information try { $CurrentConfig | Export-Clixml -Path $PSScriptRoot\Configs\$filename -ErrorAction Stop update-log -data "file saved" -Class Information } catch { Update-Log -data "Couldn't save file" -Class Error } } #Function to import configurations from file function load-config($filename) { update-log -data "Importing config from $filename" -Class Information try { $settings = Import-Clixml -Path $filename -ErrorAction Stop update-log -data "Config file read..." -Class Information $WPFSourceWIMSelectWIMTextBox.text = $settings.SourcePath $WPFSourceWimIndexTextBox.text = $settings.SourceIndex $WPFSourceWIMImgDesTextBox.text = $settings.SourceEdition $WPFUpdatesEnableCheckBox.IsChecked = $settings.UpdatesEnabled $WPFJSONEnableCheckBox.IsChecked = $settings.AutopilotEnabled $WPFJSONTextBox.text = $settings.AutopilotPath $WPFDriverCheckBox.IsChecked = $settings.DriversEnabled $WPFDriverDir1TextBox.text = $settings.DriverPath1 $WPFDriverDir2TextBox.text = $settings.DriverPath2 $WPFDriverDir3TextBox.text = $settings.DriverPath3 $WPFDriverDir4TextBox.text = $settings.DriverPath4 $WPFDriverDir5TextBox.text = $settings.DriverPath5 $WPFAppxCheckBox.IsChecked = $settings.AppxIsEnabled $WPFAppxTextBox.text = $settings.AppxSelected -split " " $WPFMISWimNameTextBox.text = $settings.WIMName $WPFMISWimFolderTextBox.text = $settings.WIMPath $WPFMISMountTextBox.text = $settings.MountPath $global:SelectedAppx = $settings.AppxSelected -split " " $WPFMISDotNetCheckBox.IsChecked = $settings.DotNetEnabled $WPFMISOneDriveCheckBox.IsChecked = $settings.OneDriveEnabled $WPFCustomCBLangPacks.IsChecked = $settings.LPsEnabled $WPFCustomCBLEP.IsChecked = $settings.LXPsEnabled $WPFCustomCBFOD.IsChecked = $settings.FODsEnabled $LEPs = $settings.LPListBox $LXPs = $settings.LXPListBox $FODs = $settings.FODListBox update-log -data "Configration set" -class Information update-log -data "Populating list boxes..." -class Information foreach ($LEP in $LEPs){$WPFCustomLBLangPacks.Items.Add($LEP) | out-null} foreach ($LXP in $LXPs){$WPFCustomLBLEP.Items.Add($LXP) | out-null} foreach ($FOD in $FODs){$WPFCustomLBFOD.Items.Add($FOD) | out-null} import-wiminfo -IndexNumber $WPFSourceWimIndexTextBox.text if ($WPFJSONEnableCheckBox.IsChecked -eq $true) { Parse-JSON -file $WPFJSONTextBox.text } reset-MISCheckBox Update-Log -data "Config file loaded successfully" -Class Information } catch { update-log -data "Could not import from $filename" -Class Error } } #Function to select configuration file Function select-config { $SourceXML = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = "$PSScriptRoot\Configs" Filter = 'XML (*.XML)|' } $null = $SourceXML.ShowDialog() $WPFSLLoadTextBox.text = $SourceXML.FileName load-config -filename $WPFSLLoadTextBox.text } #Function to reset reminder values from check boxes on the MIS tab when loading a config function reset-MISCheckBox { update-log -data "Refreshing MIS Values..." -class Information If ($WPFJSONEnableCheckBox.IsChecked -eq $true) { $WPFJSONButton.IsEnabled = $True $WPFMISJSONTextBox.Text = "True" } If ($WPFDriverCheckBox.IsChecked -eq $true) { $WPFDriverDir1Button.IsEnabled = $True $WPFDriverDir2Button.IsEnabled = $True $WPFDriverDir3Button.IsEnabled = $True $WPFDriverDir4Button.IsEnabled = $True $WPFDriverDir5Button.IsEnabled = $True $WPFMISDriverTextBox.Text = "True" } If ($WPFUpdatesEnableCheckBox.IsChecked -eq $true) { $WPFMISUpdatesTextBox.Text = "True" } If ($WPFAppxCheckBox.IsChecked -eq $true) { $WPFAppxButton.IsEnabled = $True $WPFMISAppxTextBox.Text = "True" } } #Function to run WIM Witch from a config file function run-configfile($filename) { Update-Log -Data "Loading the config file: $filename" -Class Information load-config -filename $filename Update-Log -Data "Starting auto mode with the config file $filename" -Class Information MakeItSo -appx $global:SelectedAppx } #Function to display text on closing of the script or wpf window function display-closingtext { #Before you start bitching about write-host, write-output doesn't work with the exiting function. Suggestions are welcome. Write-Host " " Write-Host "##########################################################" Write-Host " " Write-Host "Thank you for using WIM Witch. If you have any questions," Write-Host "comments, or suggestions, please reach out to me!" Write-Host " " Write-Host "-Donna Ryan" Write-Host " " Write-Host "twitter: @TheNotoriousDRR" Write-Host "www.SCConfigMgr.com" Write-Host "www.TheNotoriousDRR.com" Write-Host " " Write-Host "##########################################################" } #Function to display opening text function display-openingtext { cls Write-Output "##########################################################" Write-Output " " Write-Output " ***** Starting WIM Witch *****" Write-Output " version $WWScriptVer" Write-Output " " Write-Output "##########################################################" Write-Output " " } #Function to check suitability of the proposed mount point folder function check-mountpath { param( [parameter(mandatory = $true, HelpMessage = "mount path")] $path, [parameter(mandatory = $false, HelpMessage = "clear out the crapola")] [ValidateSet($true)] $clean ) $IsMountPoint = $null $HasFiles = $null $currentmounts = get-windowsimage -Mounted foreach ($currentmount in $currentmounts) { if ($currentmount.path -eq $path) { $IsMountPoint = $true } } if ($IsMountPoint -eq $null) { if ( (Get-ChildItem $path | Measure-Object).Count -gt 0) { $HasFiles = $true } } if ($HasFiles -eq $true) { Update-Log -Data "Folder is not empty" -Class Warning if ($clean -eq $true) { try { Update-Log -Data "Cleaning folder..." -Class Warning Remove-Item -Path $path\* -Recurse -Force -ErrorAction Stop Update-Log -Data "$path cleared" -Class Warning } catch { Update-Log -Data "Couldn't delete contents of $path" -Class Error Update-Log -Data "Select a different folder to continue." -Class Error return } } } if ($IsMountPoint -eq $true) { Update-Log -Data "$path is currently a mount point" -Class Warning if (($IsMountPoint -eq $true) -and ($clean -eq $true)) { try { Update-Log -Data "Attempting to dismount image from mount point" -Class Warning Dismount-WindowsImage -Path $path -Discard | Out-Null -ErrorAction Stop $IsMountPoint = $null Update-Log -Data "Dismounting was successful" -Class Warning } catch { Update-Log -Data "Couldn't completely dismount the folder. Ensure" -Class Error update-log -data "all connections to the path are closed, then try again" -Class Error return } } } if (($IsMountPoint -eq $null) -and ($HasFiles -eq $null)) { Update-Log -Data "$path is suitable for mounting" -Class Information } } #Function to check the name of the target file and remediate if necessary function check-name { Param( [parameter(mandatory = $false, HelpMessage = "what to do")] [ValidateSet("stop", "append", "backup", "overwrite")] $conflict = "stop" ) If ($WPFMISWimNameTextBox.Text -like "*.wim") { #$WPFLogging.Focus() #update-log -Data "New WIM name is valid" -Class Information } If ($WPFMISWimNameTextBox.Text -notlike "*.wim") { $WPFMISWimNameTextBox.Text = $WPFMISWimNameTextBox.Text + ".wim" update-log -Data "Appending new file name with an extension" -Class Information } $WIMpath = $WPFMISWimFolderTextBox.text + "\" + $WPFMISWimNameTextBox.Text $FileCheck = Test-Path -Path $WIMpath #append,overwrite,stop if ($FileCheck -eq $false) { update-log -data "Target WIM file name not in use. Continuing..." -class Information } else { if ($conflict -eq "append") { $renamestatus = (replace-name -file $WIMpath -extension ".wim") if ($renamestatus -eq "stop") { return "stop" } } if ($conflict -eq "overwrite") { Write-Host "overwrite action" return } if ($conflict -eq "stop") { $string = $WPFMISWimNameTextBox.Text + " already exists. Rename the target WIM and try again" update-log -Data $string -Class Warning return "stop" } } update-log -Data "New WIM name is valid" -Class Information } #Function to rename existing target wim file if the target WIM name already exists function replace-name($file, $extension) { $text = "Renaming existing " + $extension + " file..." Update-Log -Data $text -Class Warning $filename = (Split-Path -leaf $file) $dateinfo = (get-item -Path $file).LastWriteTime -replace (" ", "_") -replace ("/", "_") -replace (":", "_") $filename = $filename -replace ($extension, "") $filename = $filename + $dateinfo + $extension try { rename-Item -Path $file -NewName $filename -ErrorAction Stop $text = $file + " has been renamed to " + $filename Update-Log -Data $text -Class Warning } catch { Update-Log -data "Couldn't rename file. Stopping..." -force -Class Error return "stop" } } #Function to see if the folder WIM Witch was started in is an installation folder. If not, prompt for installation function check-install { function select-installfolder { $installselect = New-Object System.Windows.Forms.FolderBrowserDialog $installselect.Description = "Select the installation folder" $null = $installselect.ShowDialog() if ($installselect.SelectedPath -eq "") { write-output "User Cancelled or invalid entry" exit 0 } return $installselect.SelectedPath } function install-wimwitch { Write-Output "Would you like to install WIM Witch here?" $yesno = Read-Host -Prompt "(Y/N)" Write-Output $yesno if (($yesno -ne "Y") -and ($yesno -ne "N")) { Write-Output "Invalid entry, try again." install-wimwitch } if (($yesno -eq "y") -and ($PSScriptRoot -notlike "*WindowsPowerShell\Scripts*")){ foreach ($subfolder in $subfolders) { New-Item -Path $subfolder -ItemType Directory | Out-Null Write-Output "Created folder: $subfolder" } } if (($yesno -eq "y") -and ($PSScriptRoot -like "*WindowsPowerShell\Scripts*")){ Write-Output " " write-output "You cannot install WIM Witch in the script repository folder." Write-Output "Also, you probably shouldn't install this in My Downloads, or My Desktop" write-output "Please select another folder" $yesno = "n" } if ($yesno -eq "n") { Write-Output "Select an installation folder" $installpath = select-installfolder if ($installpath -like "*WindowsPowerShell\Scripts*"){ Write-Output "You cannot install WIM Witch in the script repository folder" Write-Output "Exiting installer. Please try again" exit 0 } Write-Output "Installing WIM Witch in: $installpath" Copy-Item -Path $MyInvocation.ScriptName -Destination $installpath -Force Write-Output "WIM Witch script copied to installation path" Set-Location -Path $installpath foreach ($subfolder in $subfolders) { if ((Test-Path -Path "$subfolder") -eq $true) { Write-Host "$subfolder exists" } if ((Test-Path -Path "$subfolder") -eq $false) { New-Item -Path $subfolder -ItemType Directory | out-null Write-Output "Created folder: $subfolder" } } Write-Output "=============================================" Write-Output "WIM Witch has been installed to $installpath" Write-Output "Start WIM witch from that folder to continue." Write-Output " " Write-Output "Exiting..." break } } $subfolders = @( "CompletedWIMs" "Configs" "drivers" "jobs" "logging" "Mount" "Staging" "updates" "imports" "imports\WIM" "imports\DotNet" "Autopilot" "backup" ) if ((Get-WmiObject win32_operatingsystem).version -like '10.0.*') { Write-Output "WIM Witch is running on a supported OS" } else { Write-Output "Current OS not supported" Write-Output "Please run WIM Witch on Windows 10 / Server 2016+" exit 0 } $count = $null set-location -path $PSScriptRoot Write-Output "WIM Witch starting in $PSScriptRoot" Write-Output "Checking for installation status" foreach ($subfolder in $subfolders) { if ((Test-Path -Path .\$subfolder) -eq $true) { $count = $count + 1 } } if ($count -eq $null) { Write-Output "WIM Witch does not appear to be installed in this location." install-wimwitch } if ($count -ne $null) { Write-Output "WIM Witch is installed" Write-Output "Remediating for missing folders if they exist" foreach ($subfolder in $subfolders) { if ((Test-Path -Path "$subfolder") -eq $false) { New-Item -Path $subfolder -ItemType Directory | Out-Null Write-Output "Created folder: $subfolder" } } write-output "Preflight complete. Starting WIM Witch" } } #Function to import WIM and .Net binaries from an iso file function import-iso($file, $type, $newname) { function set-version($wimversion) { if ($wimversion -like '10.0.16299.*') { $version = "1709" } if ($wimversion -like '10.0.17134.*') { $version = "1803" } if ($wimversion -like '10.0.17763.*') { $version = "1809" } if ($wimversion -like '10.0.18362.*') { $version = "1903" } if ($wimversion -like '10.0.14393.*') { $version = "1607" } return $version } #Check to see if destination WIM already exists if (($type -eq "all") -or ($type -eq "wim")) { update-log -data "Checking to see if the destination WIM file exists..." -Class Information #check to see if the new name for the imported WIM is valid if (($WPFImportNewNameTextBox.Text -eq "") -or ($WPFImportNewNameTextBox.Text -eq "Name for the imported WIM")) { update-log -Data "Enter a valid file name for the imported WIM and then try again" -Class Error return } If ($newname -notlike "*.wim") { $newname = $newname + ".wim" update-log -Data "Appending new file name with an extension" -Class Information } if ((Test-Path -Path $PSScriptRoot\Imports\WIM\$newname) -eq $true) { Update-Log -Data "Destination WIM name already exists. Provide a new name and try again." -Class Error return } else { update-log -Data "Name appears to be good. Continuing..." -Class Information } } Update-Log -Data "Mounting ISO..." -Class Information $isomount = Mount-DiskImage -ImagePath $file -NoDriveLetter -PassThru $iso = $isomount.devicepath $windowsver = Get-WindowsImage -ImagePath $iso\sources\install.wim -Index 1 $version = set-version -wimversion $windowsver.version if ($version -eq 1903){ $Vardate = (Get-Date -Year 2019 -Month 10 -Day 01) if ($windowsver.CreatedTime -gt $vardate){$version = 1909} } #Copy out WIM file if (($type -eq "all") -or ($type -eq "wim")) { #Copy out the WIM file from the selected ISO try { update-log -data "Purging staging folder..." -Class Information Remove-Item -Path $PSScriptRoot\staging\*.* -Force update-log -data "Purge complete." -Class Information Update-Log -Data "Copying WIM file to the staging folder..." -Class Information Copy-Item -Path $iso\sources\install.wim -Destination $PSScriptRoot\staging -Force -ErrorAction Stop -PassThru } catch { Update-Log -data "Couldn't copy from the source" -Class Error return } #Change file attribute to normal Update-Log -Data "Setting file attribute of install.wim to Normal" -Class Information $attrib = Get-Item $PSScriptRoot\staging\install.wim $attrib.Attributes = 'Normal' #Rename install.wim to the new name try { $text = "Renaming install.wim to " + $newname Update-Log -Data $text -Class Information Rename-Item -Path $PSScriptRoot\Staging\install.wim -NewName $newname -ErrorAction Stop } catch { Update-Log -data "Couldn't rename the copied file. Most likely a weird permissions issues." -Class Error return } #Move the imported WIM to the imports folder try { Update-Log -data "Moving $newname to imports folder..." -Class Information Move-Item -Path $PSScriptRoot\Staging\$newname -Destination $PSScriptRoot\Imports\WIM -ErrorAction Stop } catch { Update-Log -Data "Couldn't move the new WIM to the staging folder." -Class Error return } } #Copy DotNet binaries if (($type -eq "all") -or ($type -eq "Dotnet")) { if ((Test-Path -Path $PSScriptRoot\Imports\DotNet\$version) -eq $false) { try { Update-Log -Data "Creating folders..." -Class Warning New-Item -Path $PSScriptRoot\Imports\DotNet\ -Name $version -ItemType Directory -ErrorAction stop | Out-Null } catch { Update-Log -Data "Couldn't creating new folder in DotNet imports folder" -Class Error return } } try { Update-Log -Data "Copying .Net binaries..." -Class Information Copy-Item -Path $iso\sources\sxs\*netfx3* -Destination $PSScriptRoot\Imports\DotNet\$version -Force -ErrorAction Stop } catch { Update-Log -Data "Couldn't copy the .Net binaries" -Class Error return } } try { Update-Log -Data "Dismount!" -Class Information Dismount-DiskImage -ImagePath $file -ErrorAction Stop | Out-Null } catch { Update-Log -Data "Couldn't dismount the ISO. WIM Witch uses a file mount option that does not" -Class Error Update-Log -Data "provision a drive letter. Use the Dismount-DiskImage command to manaully dismount." -Class Error } update-log -data "Importing complete" -class Information } #function to select ISO for import function select-iso { $SourceISO = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = [Environment]::GetFolderPath('Desktop') Filter = 'ISO (*.iso)|' } $null = $SourceISO.ShowDialog() $WPFImportISOTextBox.text = $SourceISO.FileName if ($SourceISO.FileName -notlike "*.iso") { update-log -Data "An ISO file not selected. Please select a valid file to continue." -Class Warning return } $text = $WPFImportISOTextBox.text + " selected as the ISO to import from" Update-Log -Data $text -class Information } #function to inject the .Net 3.5 binaries from the import folder function inject-dotnet { If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $buildnum = 1809 } If ($WPFSourceWimVerTextBox.text -like "10.0.17134.*") { $buildnum = 1803 } If ($WPFSourceWimVerTextBox.text -like "10.0.16299.*") { $buildnum = 1709 } if ($WPFSourceWimVerTextBox.text -like "10.0.14393.*") { $buildnum = 1607 } If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { $mountdir = $WPFMISMountTextBox.Text reg LOAD HKLM\OFFLINE $mountdir\Windows\System32\Config\SOFTWARE | out-null #Fount it $regvalues = (Get-ItemProperty -Path "Registry::HKEY_LOCAL_MACHINE\OFFLINE\Microsoft\Windows NT\CurrentVersion\" ) $buildnum = $regvalues.ReleaseId reg UNLOAD HKLM\OFFLINE | out-null}#Found it $DotNetFiles = $PSScriptRoot + '\imports\DotNet\' + $buildnum try { $text = "Injecting .Net 3.5 binaries from " + $DotNetFiles Update-Log -Data $text -Class Information Add-WindowsPackage -PackagePath $DotNetFiles -Path $WPFMISMountTextBox.Text -ErrorAction Continue | Out-Null } catch { Update-Log -Data "Couldn't inject .Net Binaries" -Class Warning return } Update-Log -Data ".Net 3.5 injection complete" -Class Information } #function to see if the .Net binaries for the select Win10 version exist function check-dotnetexists { If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { $buildnum = 1903 } If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $buildnum = 1809 } If ($WPFSourceWimVerTextBox.text -like "10.0.17134.*") { $buildnum = 1803 } If ($WPFSourceWimVerTextBox.text -like "10.0.16299.*") { $buildnum = 1709 } If ($WPFSourceWimVerTextBox.text -like "10.0.14393.*") { $buildnum = 1607 } $windowsver = (get-windowsimage -ImagePath $WPFSourceWIMSelectWIMTextBox.text -index 1) if ($buildnum -eq 1903){ $Vardate = (Get-Date -Year 2019 -Month 10 -Day 01) #$Vardate is an arbitrary date that is before the 1909 creation date and after the #last 1903 release. It's hokey, but it works. - <3 Donna if ($windowsver.CreatedTime -gt $Vardate){$buildnum = 1909} } $DotNetFiles = $PSScriptRoot + '\imports\DotNet\' + $buildnum + '\' Test-Path -Path $DotNetFiles\* if ((Test-Path -Path $DotNetFiles\*) -eq $false) { $text = ".Net 3.5 Binaries are not present for " + $buildnum update-log -Data $text -Class Warning update-log -data "Import .Net from an ISO or disable injection to continue" -Class Warning return $false } } #Function to check installed version of WIM Witch and update if available Function Check-WIMWitchVer{ function upgrade-wimwitch { Write-Output "Would you like to upgrade WIM Witch?" $yesno = Read-Host -Prompt "(Y/N)" Write-Output $yesno if (($yesno -ne "Y") -and ($yesno -ne "N")) { Write-Output "Invalid entry, try again." upgrade-wimwitch } if ($yesno -eq "y") { Backup-WIMWitch try{ Save-Script -Name "WIMWitch" -Path $PSScriptRoot -Force -ErrorAction Stop Write-Output "New version has been applied. WIM Witch will now exit." Write-Output "Please restart WIM Witch" exit} catch{ Write-Output "Couldn't upgrade. Try again when teh tubes are clear" return} } if ($yesno -eq "n") { Write-Output "You'll want to upgrade at some point." Update-Log -Data "Upgrade to new version was declined" -Class Warning Update-Log -Data "Continuing to start WIM Witch..." -Class Warning } } Update-Log -Data "The currently installed version of WIM Witch is $WWScriptVer" -Class Information Update-Log -data "Checking for updates from PowerShell Gallery..." -Class Information try{ $WWCurrentVer = (Find-Script -Name "WIMWitch" -ErrorAction Stop).version Update-Log -Data "The latest version from the Gallery is $WWCurrentVer" -Class Information } catch{ Update-Log -Data "Couldn't retreive script info from the PowerShell Gallery" -Class Warning Update-Log -data "Try rebooting the internet and trying again" -Class Warning Update-Log -data "Continuing on with loading WIM Witch..." -Class Warning return } If (($WWCurrentVer -gt $WWScriptVer) -and ($auto -eq $false)){upgrade-wimwitch} if (($WWCurrentVer -gt $WWScriptVer) -and ($auto -eq $true)){update-log -data "Skipping WIM Witch upgrade because she is in auto-mode. Please launch WIM Witch in GUI mode to update." -class warning} If ($WWCurrentVer -eq $WWScriptVer){Update-Log -data "WIM Witch is up to date. Starting WIM Witch" -Class Information} If ($WWCurrentVer -lt $WWScriptVer){ Update-Log -Data "The local copy of WIM Witch is more current that the most current" -class Warning Update-Log -Data "version available. Did you violate the Temporal Prime Directive?" -class Warning Update-Log -data "Starting WIM Witch anyway..." -class warning } } #Function to backup WIM Witch script file during upgrade function Backup-WIMWitch{ Update-log -data "Backing up existing WIM Witch script..." -Class Information $scriptname = split-path $MyInvocation.PSCommandPath -Leaf #Find local script name Update-Log -data "The script to be backed up is: " -Class Information Update-Log -data $MyInvocation.PSCommandPath -Class Information try{ Update-Log -data "Copy script to backup folder..." -Class Information Copy-Item -Path $scriptname -Destination $PSScriptRoot\backup -ErrorAction Stop Update-Log -Data "Successfully copied..." -Class Information } catch{ Update-Log -data "Couldn't copy the WIM Witch script. My guess is a permissions issue" -Class Error Update-Log -Data "Exiting out of an over abundance of caution" -Class Error exit } try { Update-Log -data "Renaming archived script..." -Class Information replace-name -file $PSScriptRoot\backup\$scriptname -extension ".ps1" Update-Log -data "Backup successfully renamed for archiving" -class Information } catch { Update-Log -Data "Backed-up script couldn't be renamed. This isn't a critical error" -Class Warning Update-Log -Data "You may want to change it's name so it doesn't get overwritten." -Class Warning Update-Log -Data "Continuing with WIM Witch upgrade..." -Class Warning } } #Function to download current OneDrive client #Most of this was stolen from David Segura @SeguraOSD function download-onedrive{ update-log -Data "Downloading latest OneDrive agent installer..." -class Information $DownloadUrl = 'https://go.microsoft.com/fwlink/p/?LinkId=248256' $DownloadPath = "$PSScriptRoot\updates\OneDrive" $DownloadFile = 'OneDriveSetup.exe' if (!(Test-Path "$DownloadPath")) {New-Item -Path $DownloadPath -ItemType Directory -Force | Out-Null} Invoke-WebRequest -Uri $DownloadUrl -OutFile "$DownloadPath\$DownloadFile" if (Test-Path "$DownloadPath\$DownloadFile") { Update-Log -Data 'OneDrive Download Complete' -Class Information } else { Update-log -Data 'OneDrive could not be downloaded' -Class Error } } #function to copy new OneDrive client installer to mount path function copy-onedrive{ try{ update-log -Data "Setting ACL on the original OneDriveSetup.exe file" -Class Information $mountpath = $WPFMISMountTextBox.text $user = $env:USERNAME $Acl = Get-Acl "$mountpath\Windows\SysWOW64\OneDriveSetup.exe" $AclBAK = Get-Acl "$mountpath\Windows\SysWOW64\OneDriveSetup.exe" $Ar = New-Object System.Security.AccessControl.FileSystemAccessRule($user, "FullControl", "Allow") $Acl.SetAccessRule($Ar) Set-Acl "$mountpath\Windows\SysWOW64\OneDriveSetup.exe" $Acl -ErrorAction Stop |out-null update-log -Data "ACL successfully updated. Continuing..." } catch{ Update-Log -data "Couldn't set the ACL on the original file" -Class Error return } try{ Update-Log -data "Copying updated OneDrive agent installer..." -Class Information copy-item "$PSScriptRoot\updates\OneDrive\OneDriveSetup.exe" -Destination "$mountpath\Windows\SysWOW64" -Force -ErrorAction Stop Update-Log -Data "OneDrive installer successfully copied." -Class Information } catch{ Update-Log -data "Couldn't copy the OneDrive installer file." -class Error return } try{ update-log -data "Restoring original ACL to OneDrive installer." -Class Information Set-Acl "$mountpath\Windows\SysWOW64\OneDriveSetup.exe" $AclBAK -ErrorAction Stop |out-null update-log -data "Restoration complete" -Class Information } catch{ Update-Log "Couldn't restore original ACLs. Continuing." -Class Error } } #Function to call the next three functions. This determines WinOS and WinVer and calls the function function select-LPFODCriteria($Type){ if ($WPFSourceWIMImgDesTextBox.text -like '*10*'){$WinOS = "Windows 10"} Else {$WinOS = "Windows Server"} If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $WinVer = "1809" } If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { if ((get-windowsimage -ImagePath $WPFSourceWIMSelectWIMTextBox.text -Index 1).CreatedTime -gt (Get-Date -Year 2019 -Month 09 -Day 02)){$WinVer = "1909"} else{ $WinVer = "1909"} } if ($type -eq "LP"){ if ((test-path -Path $PSScriptRoot\imports\Lang\$WinOS\$Winver\LanguagePacks) -eq $false){ update-log -Data "Source not found. Please import some language packs and try again" -Class Error return} select-LanguagePacks -winver $Winver -WinOS $WinOS } If ($type -eq "LXP"){ if ((test-path -Path $PSScriptRoot\imports\Lang\$WinOS\$Winver\localexperiencepack) -eq $false){ update-log -Data "Source not found. Please import some Local Experience Packs and try again" -Class Error return} select-localexperiencepack -winver $Winver -WinOS $WinOS} if ($type -eq "FOD"){ if ((test-path -Path $PSScriptRoot\imports\FODs\$WinOS\$Winver\) -eq $false){ update-log -Data "Source not found. Please import some Demanding Features and try again" -Class Error return} select-FODs -winver $Winver -WinOS $WinOS} } #Function to select langauge packs for injection function select-LanguagePacks($winver,$WinOS){ $LPSourceFolder = $PSScriptRoot + '\imports\lang\' + $WinOS + '\' + $winver + '\'+ 'LanguagePacks' + '\' # write-host $LPSourceFolder $items = (Get-ChildItem -path $LPSourceFolder | Select-Object -Property Name | Out-GridView -title "Select Language Packs" -PassThru) foreach ($item in $items){$WPFCustomLBLangPacks.Items.Add($item.name)} } #Function to select LXP packs for injection function select-localexperiencepack($winver,$WinOS){ $LPSourceFolder = $PSScriptRoot + '\imports\lang\' + $WinOS + '\' + $winver + '\'+ 'localexperiencepack' + '\' # write-host $LPSourceFolder $items = (Get-ChildItem -path $LPSourceFolder | Select-Object -Property Name | Out-GridView -title "Select Local Experience Packs" -PassThru) foreach ($item in $items){$WPFCustomLBLEP.Items.Add($item.name)} } #Function to select FODs for injection function select-FODs($winver,$WinOS){ $Win10_1909_FODs = @("Accessibility.Braille~~~~0.0.1.0", "Analog.Holographic.Desktop~~~~0.0.1.0", "App.Support.QuickAssist~~~~0.0.1.0", "Browser.InternetExplorer~~~~0.0.11.0", "Hello.Face.18330~~~~0.0.1.0", "Hello.Face.Migration.18330~~~~0.0.1.0", "Language.Basic~~~af-ZA~0.0.1.0", "Language.Basic~~~ar-SA~0.0.1.0", "Language.Basic~~~as-IN~0.0.1.0", "Language.Basic~~~az-LATN-AZ~0.0.1.0", "Language.Basic~~~ba-RU~0.0.1.0", "Language.Basic~~~be-BY~0.0.1.0", "Language.Basic~~~bg-BG~0.0.1.0", "Language.Basic~~~bn-BD~0.0.1.0", "Language.Basic~~~bn-IN~0.0.1.0", "Language.Basic~~~bs-LATN-BA~0.0.1.0", "Language.Basic~~~ca-ES~0.0.1.0", "Language.Basic~~~cs-CZ~0.0.1.0", "Language.Basic~~~cy-GB~0.0.1.0", "Language.Basic~~~da-DK~0.0.1.0", "Language.Basic~~~de-CH~0.0.1.0", "Language.Basic~~~de-DE~0.0.1.0", "Language.Basic~~~el-GR~0.0.1.0", "Language.Basic~~~en-AU~0.0.1.0", "Language.Basic~~~en-CA~0.0.1.0", "Language.Basic~~~en-GB~0.0.1.0", "Language.Basic~~~en-IN~0.0.1.0", "Language.Basic~~~en-US~0.0.1.0", "Language.Basic~~~es-ES~0.0.1.0", "Language.Basic~~~es-MX~0.0.1.0", "Language.Basic~~~es-US~0.0.1.0", "Language.Basic~~~et-EE~0.0.1.0", "Language.Basic~~~eu-ES~0.0.1.0", "Language.Basic~~~fa-IR~0.0.1.0", "Language.Basic~~~fi-FI~0.0.1.0", "Language.Basic~~~fil-PH~0.0.1.0", "Language.Basic~~~fr-BE~0.0.1.0", "Language.Basic~~~fr-CA~0.0.1.0", "Language.Basic~~~fr-CH~0.0.1.0", "Language.Basic~~~fr-FR~0.0.1.0", "Language.Basic~~~ga-IE~0.0.1.0", "Language.Basic~~~gd-GB~0.0.1.0", "Language.Basic~~~gl-ES~0.0.1.0", "Language.Basic~~~gu-IN~0.0.1.0", "Language.Basic~~~ha-LATN-NG~0.0.1.0", "Language.Basic~~~haw-US~0.0.1.0", "Language.Basic~~~he-IL~0.0.1.0", "Language.Basic~~~hi-IN~0.0.1.0", "Language.Basic~~~hr-HR~0.0.1.0", "Language.Basic~~~hu-HU~0.0.1.0", "Language.Basic~~~hy-AM~0.0.1.0", "Language.Basic~~~id-ID~0.0.1.0", "Language.Basic~~~ig-NG~0.0.1.0", "Language.Basic~~~is-IS~0.0.1.0", "Language.Basic~~~it-IT~0.0.1.0", "Language.Basic~~~ja-JP~0.0.1.0", "Language.Basic~~~ka-GE~0.0.1.0", "Language.Basic~~~kk-KZ~0.0.1.0", "Language.Basic~~~kl-GL~0.0.1.0", "Language.Basic~~~kn-IN~0.0.1.0", "Language.Basic~~~ko-KR~0.0.1.0", "Language.Basic~~~kok-DEVA-IN~0.0.1.0", "Language.Basic~~~ky-KG~0.0.1.0", "Language.Basic~~~lb-LU~0.0.1.0", "Language.Basic~~~lt-LT~0.0.1.0", "Language.Basic~~~lv-LV~0.0.1.0", "Language.Basic~~~mi-NZ~0.0.1.0", "Language.Basic~~~mk-MK~0.0.1.0", "Language.Basic~~~ml-IN~0.0.1.0", "Language.Basic~~~mn-MN~0.0.1.0", "Language.Basic~~~mr-IN~0.0.1.0", "Language.Basic~~~ms-BN~0.0.1.0", "Language.Basic~~~ms-MY~0.0.1.0", "Language.Basic~~~mt-MT~0.0.1.0", "Language.Basic~~~nb-NO~0.0.1.0", "Language.Basic~~~ne-NP~0.0.1.0", "Language.Basic~~~nl-NL~0.0.1.0", "Language.Basic~~~nn-NO~0.0.1.0", "Language.Basic~~~nso-ZA~0.0.1.0", "Language.Basic~~~or-IN~0.0.1.0", "Language.Basic~~~pa-IN~0.0.1.0", "Language.Basic~~~pl-PL~0.0.1.0", "Language.Basic~~~ps-AF~0.0.1.0", "Language.Basic~~~pt-BR~0.0.1.0", "Language.Basic~~~pt-PT~0.0.1.0", "Language.Basic~~~rm-CH~0.0.1.0", "Language.Basic~~~ro-RO~0.0.1.0", "Language.Basic~~~ru-RU~0.0.1.0", "Language.Basic~~~rw-RW~0.0.1.0", "Language.Basic~~~sah-RU~0.0.1.0", "Language.Basic~~~si-LK~0.0.1.0", "Language.Basic~~~sk-SK~0.0.1.0", "Language.Basic~~~sl-SI~0.0.1.0", "Language.Basic~~~sq-AL~0.0.1.0", "Language.Basic~~~sr-CYRL-RS~0.0.1.0", "Language.Basic~~~sr-LATN-RS~0.0.1.0", "Language.Basic~~~sv-SE~0.0.1.0", "Language.Basic~~~sw-KE~0.0.1.0", "Language.Basic~~~ta-IN~0.0.1.0", "Language.Basic~~~te-IN~0.0.1.0", "Language.Basic~~~tg-CYRL-TJ~0.0.1.0", "Language.Basic~~~th-TH~0.0.1.0", "Language.Basic~~~tk-TM~0.0.1.0", "Language.Basic~~~tn-ZA~0.0.1.0", "Language.Basic~~~tr-TR~0.0.1.0", "Language.Basic~~~tt-RU~0.0.1.0", "Language.Basic~~~ug-CN~0.0.1.0", "Language.Basic~~~uk-UA~0.0.1.0", "Language.Basic~~~ur-PK~0.0.1.0", "Language.Basic~~~uz-LATN-UZ~0.0.1.0", "Language.Basic~~~vi-VN~0.0.1.0", "Language.Basic~~~wo-SN~0.0.1.0", "Language.Basic~~~xh-ZA~0.0.1.0", "Language.Basic~~~yo-NG~0.0.1.0", "Language.Basic~~~zh-CN~0.0.1.0", "Language.Basic~~~zh-HK~0.0.1.0", "Language.Basic~~~zh-TW~0.0.1.0", "Language.Basic~~~zu-ZA~0.0.1.0", "Language.Fonts.Arab~~~und-ARAB~0.0.1.0", "Language.Fonts.Beng~~~und-BENG~0.0.1.0", "Language.Fonts.Cans~~~und-CANS~0.0.1.0", "Language.Fonts.Cher~~~und-CHER~0.0.1.0", "Language.Fonts.Deva~~~und-DEVA~0.0.1.0", "Language.Fonts.Ethi~~~und-ETHI~0.0.1.0", "Language.Fonts.Gujr~~~und-GUJR~0.0.1.0", "Language.Fonts.Guru~~~und-GURU~0.0.1.0", "Language.Fonts.Hans~~~und-HANS~0.0.1.0", "Language.Fonts.Hant~~~und-HANT~0.0.1.0", "Language.Fonts.Hebr~~~und-HEBR~0.0.1.0", "Language.Fonts.Jpan~~~und-JPAN~0.0.1.0", "Language.Fonts.Khmr~~~und-KHMR~0.0.1.0", "Language.Fonts.Knda~~~und-KNDA~0.0.1.0", "Language.Fonts.Kore~~~und-KORE~0.0.1.0", "Language.Fonts.Laoo~~~und-LAOO~0.0.1.0", "Language.Fonts.Mlym~~~und-MLYM~0.0.1.0", "Language.Fonts.Orya~~~und-ORYA~0.0.1.0", "Language.Fonts.PanEuropeanSupplementalFonts~~~~0.0.1.0", "Language.Fonts.Sinh~~~und-SINH~0.0.1.0", "Language.Fonts.Syrc~~~und-SYRC~0.0.1.0", "Language.Fonts.Taml~~~und-TAML~0.0.1.0", "Language.Fonts.Telu~~~und-TELU~0.0.1.0", "Language.Fonts.Thai~~~und-THAI~0.0.1.0", "Language.Handwriting~~~af-ZA~0.0.1.0", "Language.Handwriting~~~bs-LATN-BA~0.0.1.0", "Language.Handwriting~~~ca-ES~0.0.1.0", "Language.Handwriting~~~cs-CZ~0.0.1.0", "Language.Handwriting~~~cy-GB~0.0.1.0", "Language.Handwriting~~~da-DK~0.0.1.0", "Language.Handwriting~~~de-DE~0.0.1.0", "Language.Handwriting~~~el-GR~0.0.1.0", "Language.Handwriting~~~en-GB~0.0.1.0", "Language.Handwriting~~~en-US~0.0.1.0", "Language.Handwriting~~~es-ES~0.0.1.0", "Language.Handwriting~~~es-MX~0.0.1.0", "Language.Handwriting~~~eu-ES~0.0.1.0", "Language.Handwriting~~~fi-FI~0.0.1.0", "Language.Handwriting~~~fr-FR~0.0.1.0", "Language.Handwriting~~~ga-IE~0.0.1.0", "Language.Handwriting~~~gd-GB~0.0.1.0", "Language.Handwriting~~~gl-ES~0.0.1.0", "Language.Handwriting~~~hi-IN~0.0.1.0", "Language.Handwriting~~~hr-HR~0.0.1.0", "Language.Handwriting~~~id-ID~0.0.1.0", "Language.Handwriting~~~it-IT~0.0.1.0", "Language.Handwriting~~~ja-JP~0.0.1.0", "Language.Handwriting~~~ko-KR~0.0.1.0", "Language.Handwriting~~~lb-LU~0.0.1.0", "Language.Handwriting~~~mi-NZ~0.0.1.0", "Language.Handwriting~~~ms-BN~0.0.1.0", "Language.Handwriting~~~ms-MY~0.0.1.0", "Language.Handwriting~~~nb-NO~0.0.1.0", "Language.Handwriting~~~nl-NL~0.0.1.0", "Language.Handwriting~~~nn-NO~0.0.1.0", "Language.Handwriting~~~nso-ZA~0.0.1.0", "Language.Handwriting~~~pl-PL~0.0.1.0", "Language.Handwriting~~~pt-BR~0.0.1.0", "Language.Handwriting~~~pt-PT~0.0.1.0", "Language.Handwriting~~~rm-CH~0.0.1.0", "Language.Handwriting~~~ro-RO~0.0.1.0", "Language.Handwriting~~~ru-RU~0.0.1.0", "Language.Handwriting~~~rw-RW~0.0.1.0", "Language.Handwriting~~~sk-SK~0.0.1.0", "Language.Handwriting~~~sl-SI~0.0.1.0", "Language.Handwriting~~~sq-AL~0.0.1.0", "Language.Handwriting~~~sr-CYRL-RS~0.0.1.0", "Language.Handwriting~~~sr-LATN-RS~0.0.1.0", "Language.Handwriting~~~sv-SE~0.0.1.0", "Language.Handwriting~~~sw-KE~0.0.1.0", "Language.Handwriting~~~tn-ZA~0.0.1.0", "Language.Handwriting~~~tr-TR~0.0.1.0", "Language.Handwriting~~~wo-SN~0.0.1.0", "Language.Handwriting~~~xh-ZA~0.0.1.0", "Language.Handwriting~~~zh-CN~0.0.1.0", "Language.Handwriting~~~zh-HK~0.0.1.0", "Language.Handwriting~~~zh-TW~0.0.1.0", "Language.Handwriting~~~zu-ZA~0.0.1.0", "Language.OCR~~~ar-SA~0.0.1.0", "Language.OCR~~~bg-BG~0.0.1.0", "Language.OCR~~~bs-LATN-BA~0.0.1.0", "Language.OCR~~~cs-CZ~0.0.1.0", "Language.OCR~~~da-DK~0.0.1.0", "Language.OCR~~~de-DE~0.0.1.0", "Language.OCR~~~el-GR~0.0.1.0", "Language.OCR~~~en-GB~0.0.1.0", "Language.OCR~~~en-US~0.0.1.0", "Language.OCR~~~es-ES~0.0.1.0", "Language.OCR~~~es-MX~0.0.1.0", "Language.OCR~~~fi-FI~0.0.1.0", "Language.OCR~~~fr-CA~0.0.1.0", "Language.OCR~~~fr-FR~0.0.1.0", "Language.OCR~~~hr-HR~0.0.1.0", "Language.OCR~~~hu-HU~0.0.1.0", "Language.OCR~~~it-IT~0.0.1.0", "Language.OCR~~~ja-JP~0.0.1.0", "Language.OCR~~~ko-KR~0.0.1.0", "Language.OCR~~~nb-NO~0.0.1.0", "Language.OCR~~~nl-NL~0.0.1.0", "Language.OCR~~~pl-PL~0.0.1.0", "Language.OCR~~~pt-BR~0.0.1.0", "Language.OCR~~~pt-PT~0.0.1.0", "Language.OCR~~~ro-RO~0.0.1.0", "Language.OCR~~~ru-RU~0.0.1.0", "Language.OCR~~~sk-SK~0.0.1.0", "Language.OCR~~~sl-SI~0.0.1.0", "Language.OCR~~~sr-CYRL-RS~0.0.1.0", "Language.OCR~~~sr-LATN-RS~0.0.1.0", "Language.OCR~~~sv-SE~0.0.1.0", "Language.OCR~~~tr-TR~0.0.1.0", "Language.OCR~~~zh-CN~0.0.1.0", "Language.OCR~~~zh-HK~0.0.1.0", "Language.OCR~~~zh-TW~0.0.1.0", "Language.Speech~~~da-DK~0.0.1.0", "Language.Speech~~~de-DE~0.0.1.0", "Language.Speech~~~en-AU~0.0.1.0", "Language.Speech~~~en-CA~0.0.1.0", "Language.Speech~~~en-GB~0.0.1.0", "Language.Speech~~~en-IN~0.0.1.0", "Language.Speech~~~en-US~0.0.1.0", "Language.Speech~~~es-ES~0.0.1.0", "Language.Speech~~~es-MX~0.0.1.0", "Language.Speech~~~fr-CA~0.0.1.0", "Language.Speech~~~fr-FR~0.0.1.0", "Language.Speech~~~it-IT~0.0.1.0", "Language.Speech~~~ja-JP~0.0.1.0", "Language.Speech~~~pt-BR~0.0.1.0", "Language.Speech~~~zh-CN~0.0.1.0", "Language.Speech~~~zh-HK~0.0.1.0", "Language.Speech~~~zh-TW~0.0.1.0", "Language.TextToSpeech~~~ar-EG~0.0.1.0", "Language.TextToSpeech~~~ar-SA~0.0.1.0", "Language.TextToSpeech~~~bg-BG~0.0.1.0", "Language.TextToSpeech~~~ca-ES~0.0.1.0", "Language.TextToSpeech~~~cs-CZ~0.0.1.0", "Language.TextToSpeech~~~da-DK~0.0.1.0", "Language.TextToSpeech~~~de-AT~0.0.1.0", "Language.TextToSpeech~~~de-CH~0.0.1.0", "Language.TextToSpeech~~~de-DE~0.0.1.0", "Language.TextToSpeech~~~el-GR~0.0.1.0", "Language.TextToSpeech~~~en-AU~0.0.1.0", "Language.TextToSpeech~~~en-CA~0.0.1.0", "Language.TextToSpeech~~~en-GB~0.0.1.0", "Language.TextToSpeech~~~en-IE~0.0.1.0", "Language.TextToSpeech~~~en-IN~0.0.1.0", "Language.TextToSpeech~~~en-US~0.0.1.0", "Language.TextToSpeech~~~es-ES~0.0.1.0", "Language.TextToSpeech~~~es-MX~0.0.1.0", "Language.TextToSpeech~~~fi-FI~0.0.1.0", "Language.TextToSpeech~~~fr-CA~0.0.1.0", "Language.TextToSpeech~~~fr-CH~0.0.1.0", "Language.TextToSpeech~~~fr-FR~0.0.1.0", "Language.TextToSpeech~~~he-IL~0.0.1.0", "Language.TextToSpeech~~~hi-IN~0.0.1.0", "Language.TextToSpeech~~~hr-HR~0.0.1.0", "Language.TextToSpeech~~~hu-HU~0.0.1.0", "Language.TextToSpeech~~~id-ID~0.0.1.0", "Language.TextToSpeech~~~it-IT~0.0.1.0", "Language.TextToSpeech~~~ja-JP~0.0.1.0", "Language.TextToSpeech~~~ko-KR~0.0.1.0", "Language.TextToSpeech~~~ms-MY~0.0.1.0", "Language.TextToSpeech~~~nb-NO~0.0.1.0", "Language.TextToSpeech~~~nl-BE~0.0.1.0", "Language.TextToSpeech~~~nl-NL~0.0.1.0", "Language.TextToSpeech~~~pl-PL~0.0.1.0", "Language.TextToSpeech~~~pt-BR~0.0.1.0", "Language.TextToSpeech~~~pt-PT~0.0.1.0", "Language.TextToSpeech~~~ro-RO~0.0.1.0", "Language.TextToSpeech~~~ru-RU~0.0.1.0", "Language.TextToSpeech~~~sk-SK~0.0.1.0", "Language.TextToSpeech~~~sl-SI~0.0.1.0", "Language.TextToSpeech~~~sv-SE~0.0.1.0", "Language.TextToSpeech~~~ta-IN~0.0.1.0", "Language.TextToSpeech~~~th-TH~0.0.1.0", "Language.TextToSpeech~~~tr-TR~0.0.1.0", "Language.TextToSpeech~~~vi-VN~0.0.1.0", "Language.TextToSpeech~~~zh-CN~0.0.1.0", "Language.TextToSpeech~~~zh-HK~0.0.1.0", "Language.TextToSpeech~~~zh-TW~0.0.1.0", "MathRecognizer~~~~0.0.1.0", "Media.WindowsMediaPlayer~~~~0.0.12.0", "Microsoft.Onecore.StorageManagement~~~~0.0.1.0", "Microsoft.WebDriver~~~~0.0.1.0", "Microsoft.Windows.StorageManagement~~~~0.0.1.0", "Msix.PackagingTool.Driver~~~~0.0.1.0", "NetFX3~~~~", "Network.Irda~~~~0.0.1.0", "OneCoreUAP.OneSync~~~~0.0.1.0", "OpenSSH.Client~~~~0.0.1.0", "OpenSSH.Server~~~~0.0.1.0", "RasCMAK.Client~~~~0.0.1.0", "RIP.Listener~~~~0.0.1.0", "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0", "Rsat.BitLocker.Recovery.Tools~~~~0.0.1.0", "Rsat.CertificateServices.Tools~~~~0.0.1.0", "Rsat.DHCP.Tools~~~~0.0.1.0", "Rsat.Dns.Tools~~~~0.0.1.0", "Rsat.FailoverCluster.Management.Tools~~~~0.0.1.0", "Rsat.FileServices.Tools~~~~0.0.1.0", "Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0", "Rsat.IPAM.Client.Tools~~~~0.0.1.0", "Rsat.LLDP.Tools~~~~0.0.1.0", "Rsat.NetworkController.Tools~~~~0.0.1.0", "Rsat.NetworkLoadBalancing.Tools~~~~0.0.1.0", "Rsat.RemoteAccess.Management.Tools~~~~0.0.1.0", "Rsat.RemoteDesktop.Services.Tools~~~~0.0.1.0", "Rsat.ServerManager.Tools~~~~0.0.1.0", "Rsat.Shielded.VM.Tools~~~~0.0.1.0", "Rsat.StorageMigrationService.Management.Tools~~~~0.0.1.0", "Rsat.StorageReplica.Tools~~~~0.0.1.0", "Rsat.SystemInsights.Management.Tools~~~~0.0.1.0", "Rsat.VolumeActivation.Tools~~~~0.0.1.0", "Rsat.WSUS.Tools~~~~0.0.1.0", "SNMP.Client~~~~0.0.1.0", "Tools.DeveloperMode.Core~~~~0.0.1.0", "Tools.DTrace.Platform~~~~0.0.1.0", "Tools.Graphics.DirectX~~~~0.0.1.0", "WMI-SNMP-Provider.Client~~~~0.0.1.0", "XPS.Viewer~~~~0.0.1.0") $Win10_1903_FODs = @("Accessibility.Braille~~~~0.0.1.0", "Analog.Holographic.Desktop~~~~0.0.1.0", "App.Support.QuickAssist~~~~0.0.1.0", "Browser.InternetExplorer~~~~0.0.11.0", "Hello.Face.17658~~~~0.0.1.0", "Hello.Face.Migration.17658~~~~0.0.1.0", "Language.Basic~~~af-ZA~0.0.1.0", "Language.Basic~~~ar-SA~0.0.1.0", "Language.Basic~~~as-IN~0.0.1.0", "Language.Basic~~~az-LATN-AZ~0.0.1.0", "Language.Basic~~~ba-RU~0.0.1.0", "Language.Basic~~~be-BY~0.0.1.0", "Language.Basic~~~bg-BG~0.0.1.0", "Language.Basic~~~bn-BD~0.0.1.0", "Language.Basic~~~bn-IN~0.0.1.0", "Language.Basic~~~bs-LATN-BA~0.0.1.0", "Language.Basic~~~ca-ES~0.0.1.0", "Language.Basic~~~cs-CZ~0.0.1.0", "Language.Basic~~~cy-GB~0.0.1.0", "Language.Basic~~~da-DK~0.0.1.0", "Language.Basic~~~de-DE~0.0.1.0", "Language.Basic~~~el-GR~0.0.1.0", "Language.Basic~~~en-GB~0.0.1.0", "Language.Basic~~~en-US~0.0.1.0", "Language.Basic~~~es-ES~0.0.1.0", "Language.Basic~~~es-MX~0.0.1.0", "Language.Basic~~~et-EE~0.0.1.0", "Language.Basic~~~eu-ES~0.0.1.0", "Language.Basic~~~fa-IR~0.0.1.0", "Language.Basic~~~fi-FI~0.0.1.0", "Language.Basic~~~fil-PH~0.0.1.0", "Language.Basic~~~fr-CA~0.0.1.0", "Language.Basic~~~fr-FR~0.0.1.0", "Language.Basic~~~ga-IE~0.0.1.0", "Language.Basic~~~gd-GB~0.0.1.0", "Language.Basic~~~gl-ES~0.0.1.0", "Language.Basic~~~gu-IN~0.0.1.0", "Language.Basic~~~ha-LATN-NG~0.0.1.0", "Language.Basic~~~haw-US~0.0.1.0", "Language.Basic~~~he-IL~0.0.1.0", "Language.Basic~~~hi-IN~0.0.1.0", "Language.Basic~~~hr-HR~0.0.1.0", "Language.Basic~~~hu-HU~0.0.1.0", "Language.Basic~~~hy-AM~0.0.1.0", "Language.Basic~~~id-ID~0.0.1.0", "Language.Basic~~~ig-NG~0.0.1.0", "Language.Basic~~~is-IS~0.0.1.0", "Language.Basic~~~it-IT~0.0.1.0", "Language.Basic~~~ja-JP~0.0.1.0", "Language.Basic~~~ka-GE~0.0.1.0", "Language.Basic~~~kk-KZ~0.0.1.0", "Language.Basic~~~kl-GL~0.0.1.0", "Language.Basic~~~kn-IN~0.0.1.0", "Language.Basic~~~ko-KR~0.0.1.0", "Language.Basic~~~kok-DEVA-IN~0.0.1.0", "Language.Basic~~~ky-KG~0.0.1.0", "Language.Basic~~~lb-LU~0.0.1.0", "Language.Basic~~~lt-LT~0.0.1.0", "Language.Basic~~~lv-LV~0.0.1.0", "Language.Basic~~~mi-NZ~0.0.1.0", "Language.Basic~~~ml-IN~0.0.1.0", "Language.Basic~~~mk-MK~0.0.1.0", "Language.Basic~~~mn-MN~0.0.1.0", "Language.Basic~~~mr-IN~0.0.1.0", "Language.Basic~~~ms-BN~0.0.1.0", "Language.Basic~~~ms-MY~0.0.1.0", "Language.Basic~~~mt-MT~0.0.1.0", "Language.Basic~~~nb-NO~0.0.1.0", "Language.Basic~~~ne-NP~0.0.1.0", "Language.Basic~~~nl-NL~0.0.1.0", "Language.Basic~~~nn-NO~0.0.1.0", "Language.Basic~~~nso-ZA~0.0.1.0", "Language.Basic~~~or-IN~0.0.1.0", "Language.Basic~~~pa-IN~0.0.1.0", "Language.Basic~~~pl-PL~0.0.1.0", "Language.Basic~~~ps-AF~0.0.1.0", "Language.Basic~~~pt-BR~0.0.1.0", "Language.Basic~~~pt-PT~0.0.1.0", "Language.Basic~~~rm-CH~0.0.1.0", "Language.Basic~~~ro-RO~0.0.1.0", "Language.Basic~~~ru-RU~0.0.1.0", "Language.Basic~~~rw-RW~0.0.1.0", "Language.Basic~~~sah-RU~0.0.1.0", "Language.Basic~~~si-LK~0.0.1.0", "Language.Basic~~~sk-SK~0.0.1.0", "Language.Basic~~~sl-SI~0.0.1.0", "Language.Basic~~~sq-AL~0.0.1.0", "Language.Basic~~~sr-CYRL-RS~0.0.1.0", "Language.Basic~~~sr-LATN-RS~0.0.1.0", "Language.Basic~~~sv-SE~0.0.1.0", "Language.Basic~~~sw-KE~0.0.1.0", "Language.Basic~~~ta-IN~0.0.1.0", "Language.Basic~~~te-IN~0.0.1.0", "Language.Basic~~~tg-CYRL-TJ~0.0.1.0", "Language.Basic~~~th-TH~0.0.1.0", "Language.Basic~~~tk-TM~0.0.1.0", "Language.Basic~~~tn-ZA~0.0.1.0", "Language.Basic~~~tr-TR~0.0.1.0", "Language.Basic~~~tt-RU~0.0.1.0", "Language.Basic~~~ug-CN~0.0.1.0", "Language.Basic~~~uk-UA~0.0.1.0", "Language.Basic~~~ur-PK~0.0.1.0", "Language.Basic~~~uz-LATN-UZ~0.0.1.0", "Language.Basic~~~vi-VN~0.0.1.0", "Language.Basic~~~wo-SN~0.0.1.0", "Language.Basic~~~xh-ZA~0.0.1.0", "Language.Basic~~~yo-NG~0.0.1.0", "Language.Basic~~~zh-CN~0.0.1.0", "Language.Basic~~~zh-HK~0.0.1.0", "Language.Basic~~~zh-TW~0.0.1.0", "Language.Basic~~~zu-ZA~0.0.1.0", "Language.Fonts.Arab~~~und-ARAB~0.0.1.0", "Language.Fonts.Beng~~~und-BENG~0.0.1.0", "Language.Fonts.Cans~~~und-CANS~0.0.1.0", "Language.Fonts.Cher~~~und-CHER~0.0.1.0", "Language.Fonts.Deva~~~und-DEVA~0.0.1.0", "Language.Fonts.Ethi~~~und-ETHI~0.0.1.0", "Language.Fonts.Gujr~~~und-GUJR~0.0.1.0", "Language.Fonts.Guru~~~und-GURU~0.0.1.0", "Language.Fonts.Hans~~~und-HANS~0.0.1.0", "Language.Fonts.Hant~~~und-HANT~0.0.1.0", "Language.Fonts.Hebr~~~und-HEBR~0.0.1.0", "Language.Fonts.Jpan~~~und-JPAN~0.0.1.0", "Language.Fonts.Khmr~~~und-KHMR~0.0.1.0", "Language.Fonts.Knda~~~und-KNDA~0.0.1.0", "Language.Fonts.Kore~~~und-KORE~0.0.1.0", "Language.Fonts.Laoo~~~und-LAOO~0.0.1.0", "Language.Fonts.Mlym~~~und-MLYM~0.0.1.0", "Language.Fonts.Orya~~~und-ORYA~0.0.1.0", "Language.Fonts.PanEuropeanSupplementalFonts~~~~0.0.1.0", "Language.Fonts.Sinh~~~und-SINH~0.0.1.0", "Language.Fonts.Syrc~~~und-SYRC~0.0.1.0", "Language.Fonts.Taml~~~und-TAML~0.0.1.0", "Language.Fonts.Telu~~~und-TELU~0.0.1.0", "Language.Fonts.Thai~~~und-THAI~0.0.1.0", "Language.Handwriting~~~af-ZA~0.0.1.0", "Language.Handwriting~~~bs-LATN-BA~0.0.1.0", "Language.Handwriting~~~ca-ES~0.0.1.0", "Language.Handwriting~~~cs-CZ~0.0.1.0", "Language.Handwriting~~~cy-GB~0.0.1.0", "Language.Handwriting~~~da-DK~0.0.1.0", "Language.Handwriting~~~de-DE~0.0.1.0", "Language.Handwriting~~~el-GR~0.0.1.0", "Language.Handwriting~~~en-GB~0.0.1.0", "Language.Handwriting~~~en-US~0.0.1.0", "Language.Handwriting~~~es-ES~0.0.1.0", "Language.Handwriting~~~es-MX~0.0.1.0", "Language.Handwriting~~~eu-ES~0.0.1.0", "Language.Handwriting~~~fi-FI~0.0.1.0", "Language.Handwriting~~~fr-FR~0.0.1.0", "Language.Handwriting~~~ga-IE~0.0.1.0", "Language.Handwriting~~~gd-GB~0.0.1.0", "Language.Handwriting~~~gl-ES~0.0.1.0", "Language.Handwriting~~~hi-IN~0.0.1.0", "Language.Handwriting~~~hr-HR~0.0.1.0", "Language.Handwriting~~~id-ID~0.0.1.0", "Language.Handwriting~~~it-IT~0.0.1.0", "Language.Handwriting~~~ja-JP~0.0.1.0", "Language.Handwriting~~~ko-KR~0.0.1.0", "Language.Handwriting~~~lb-LU~0.0.1.0", "Language.Handwriting~~~mi-NZ~0.0.1.0", "Language.Handwriting~~~ms-BN~0.0.1.0", "Language.Handwriting~~~ms-MY~0.0.1.0", "Language.Handwriting~~~nb-NO~0.0.1.0", "Language.Handwriting~~~nl-NL~0.0.1.0", "Language.Handwriting~~~nn-NO~0.0.1.0", "Language.Handwriting~~~nso-ZA~0.0.1.0", "Language.Handwriting~~~pl-PL~0.0.1.0", "Language.Handwriting~~~pt-BR~0.0.1.0", "Language.Handwriting~~~pt-PT~0.0.1.0", "Language.Handwriting~~~rm-CH~0.0.1.0", "Language.Handwriting~~~ro-RO~0.0.1.0", "Language.Handwriting~~~ru-RU~0.0.1.0", "Language.Handwriting~~~rw-RW~0.0.1.0", "Language.Handwriting~~~sk-SK~0.0.1.0", "Language.Handwriting~~~sl-SI~0.0.1.0", "Language.Handwriting~~~sq-AL~0.0.1.0", "Language.Handwriting~~~sr-CYRL-RS~0.0.1.0", "Language.Handwriting~~~sr-LATN-RS~0.0.1.0", "Language.Handwriting~~~sv-SE~0.0.1.0", "Language.Handwriting~~~sw-KE~0.0.1.0", "Language.Handwriting~~~tn-ZA~0.0.1.0", "Language.Handwriting~~~tr-TR~0.0.1.0", "Language.Handwriting~~~wo-SN~0.0.1.0", "Language.Handwriting~~~xh-ZA~0.0.1.0", "Language.Handwriting~~~zh-CN~0.0.1.0", "Language.Handwriting~~~zh-HK~0.0.1.0", "Language.Handwriting~~~zh-TW~0.0.1.0", "Language.Handwriting~~~zu-ZA~0.0.1.0", "Language.OCR~~~ar-SA~0.0.1.0", "Language.OCR~~~bg-BG~0.0.1.0", "Language.OCR~~~bs-LATN-BA~0.0.1.0", "Language.OCR~~~cs-CZ~0.0.1.0", "Language.OCR~~~da-DK~0.0.1.0", "Language.OCR~~~de-DE~0.0.1.0", "Language.OCR~~~el-GR~0.0.1.0", "Language.OCR~~~en-GB~0.0.1.0", "Language.OCR~~~en-US~0.0.1.0", "Language.OCR~~~es-ES~0.0.1.0", "Language.OCR~~~es-MX~0.0.1.0", "Language.OCR~~~fi-FI~0.0.1.0", "Language.OCR~~~fr-CA~0.0.1.0", "Language.OCR~~~fr-FR~0.0.1.0", "Language.OCR~~~hr-HR~0.0.1.0", "Language.OCR~~~hu-HU~0.0.1.0", "Language.OCR~~~it-IT~0.0.1.0", "Language.OCR~~~ja-JP~0.0.1.0", "Language.OCR~~~ko-KR~0.0.1.0", "Language.OCR~~~nb-NO~0.0.1.0", "Language.OCR~~~nl-NL~0.0.1.0", "Language.OCR~~~pl-PL~0.0.1.0", "Language.OCR~~~pt-BR~0.0.1.0", "Language.OCR~~~pt-PT~0.0.1.0", "Language.OCR~~~ro-RO~0.0.1.0", "Language.OCR~~~ru-RU~0.0.1.0", "Language.OCR~~~sk-SK~0.0.1.0", "Language.OCR~~~sl-SI~0.0.1.0", "Language.OCR~~~sr-CYRL-RS~0.0.1.0", "Language.OCR~~~sr-LATN-RS~0.0.1.0", "Language.OCR~~~sv-SE~0.0.1.0", "Language.OCR~~~tr-TR~0.0.1.0", "Language.OCR~~~zh-CN~0.0.1.0", "Language.OCR~~~zh-HK~0.0.1.0", "Language.OCR~~~zh-TW~0.0.1.0", "Language.Speech~~~de-DE~0.0.1.0", "Language.Speech~~~en-AU~0.0.1.0", "Language.Speech~~~en-CA~0.0.1.0", "Language.Speech~~~en-GB~0.0.1.0", "Language.Speech~~~en-IN~0.0.1.0", "Language.Speech~~~en-US~0.0.1.0", "Language.Speech~~~es-ES~0.0.1.0", "Language.Speech~~~es-MX~0.0.1.0", "Language.Speech~~~fr-CA~0.0.1.0", "Language.Speech~~~fr-FR~0.0.1.0", "Language.Speech~~~it-IT~0.0.1.0", "Language.Speech~~~ja-JP~0.0.1.0", "Language.Speech~~~pt-BR~0.0.1.0", "Language.Speech~~~zh-CN~0.0.1.0", "Language.Speech~~~zh-HK~0.0.1.0", "Language.Speech~~~zh-TW~0.0.1.0", "Language.TextToSpeech~~~ar-EG~0.0.1.0", "Language.TextToSpeech~~~ar-SA~0.0.1.0", "Language.TextToSpeech~~~bg-BG~0.0.1.0", "Language.TextToSpeech~~~ca-ES~0.0.1.0", "Language.TextToSpeech~~~cs-CZ~0.0.1.0", "Language.TextToSpeech~~~da-DK~0.0.1.0", "Language.TextToSpeech~~~de-AT~0.0.1.0", "Language.TextToSpeech~~~de-CH~0.0.1.0", "Language.TextToSpeech~~~de-DE~0.0.1.0", "Language.TextToSpeech~~~el-GR~0.0.1.0", "Language.TextToSpeech~~~en-AU~0.0.1.0", "Language.TextToSpeech~~~en-CA~0.0.1.0", "Language.TextToSpeech~~~en-GB~0.0.1.0", "Language.TextToSpeech~~~en-IE~0.0.1.0", "Language.TextToSpeech~~~en-IN~0.0.1.0", "Language.TextToSpeech~~~en-US~0.0.1.0", "Language.TextToSpeech~~~es-ES~0.0.1.0", "Language.TextToSpeech~~~es-MX~0.0.1.0", "Language.TextToSpeech~~~fi-FI~0.0.1.0", "Language.TextToSpeech~~~fr-CA~0.0.1.0", "Language.TextToSpeech~~~fr-CH~0.0.1.0", "Language.TextToSpeech~~~fr-FR~0.0.1.0", "Language.TextToSpeech~~~he-IL~0.0.1.0", "Language.TextToSpeech~~~hi-IN~0.0.1.0", "Language.TextToSpeech~~~hr-HR~0.0.1.0", "Language.TextToSpeech~~~hu-HU~0.0.1.0", "Language.TextToSpeech~~~id-ID~0.0.1.0", "Language.TextToSpeech~~~it-IT~0.0.1.0", "Language.TextToSpeech~~~ja-JP~0.0.1.0", "Language.TextToSpeech~~~ko-KR~0.0.1.0", "Language.TextToSpeech~~~ms-MY~0.0.1.0", "Language.TextToSpeech~~~nb-NO~0.0.1.0", "Language.TextToSpeech~~~nl-BE~0.0.1.0", "Language.TextToSpeech~~~nl-NL~0.0.1.0", "Language.TextToSpeech~~~pl-PL~0.0.1.0", "Language.TextToSpeech~~~pt-BR~0.0.1.0", "Language.TextToSpeech~~~pt-PT~0.0.1.0", "Language.TextToSpeech~~~ro-RO~0.0.1.0", "Language.TextToSpeech~~~ru-RU~0.0.1.0", "Language.TextToSpeech~~~sk-SK~0.0.1.0", "Language.TextToSpeech~~~sl-SI~0.0.1.0", "Language.TextToSpeech~~~sv-SE~0.0.1.0", "Language.TextToSpeech~~~ta-IN~0.0.1.0", "Language.TextToSpeech~~~th-TH~0.0.1.0", "Language.TextToSpeech~~~tr-TR~0.0.1.0", "Language.TextToSpeech~~~vi-VN~0.0.1.0", "Language.TextToSpeech~~~zh-CN~0.0.1.0", "Language.TextToSpeech~~~zh-HK~0.0.1.0", "Language.TextToSpeech~~~zh-TW~0.0.1.0", "MathRecognizer~~~~0.0.1.0", "Media.WindowsMediaPlayer~~~~0.0.12.0", "Microsoft.Onecore.StorageManagement~~~~0.0.1.0", "Microsoft.WebDriver~~~~0.0.1.0", "Microsoft.Windows.StorageManagement~~~~0.0.1.0", "Msix.PackagingTool.Driver~~~~0.0.1.0", "NetFX3~~~~", "OneCoreUAP.OneSync~~~~0.0.1.0", "OpenSSH.Client~~~~0.0.1.0", "OpenSSH.Server~~~~0.0.1.0", "RasCMAK.Client~~~~0.0.1.0", "RIP.Listener~~~~0.0.1.0", "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0", "Rsat.BitLocker.Recovery.Tools~~~~0.0.1.0", "Rsat.CertificateServices.Tools~~~~0.0.1.0", "Rsat.DHCP.Tools~~~~0.0.1.0", "Rsat.Dns.Tools~~~~0.0.1.0", "Rsat.FailoverCluster.Management.Tools~~~~0.0.1.0", "Rsat.FileServices.Tools~~~~0.0.1.0", "Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0", "Rsat.IPAM.Client.Tools~~~~0.0.1.0", "Rsat.LLDP.Tools~~~~0.0.1.0", "Rsat.NetworkController.Tools~~~~0.0.1.0", "Rsat.NetworkLoadBalancing.Tools~~~~0.0.1.0", "Rsat.RemoteAccess.Management.Tools~~~~0.0.1.0", "Rsat.RemoteDesktop.Services.Tools~~~~0.0.1.0", "Rsat.ServerManager.Tools~~~~0.0.1.0", "Rsat.Shielded.VM.Tools~~~~0.0.1.0", "Rsat.StorageMigrationService.Management.Tools~~~~0.0.1.0", "Rsat.StorageReplica.Tools~~~~0.0.1.0", "Rsat.SystemInsights.Management.Tools~~~~0.0.1.0", "Rsat.VolumeActivation.Tools~~~~0.0.1.0", "Rsat.WSUS.Tools~~~~0.0.1.0", "SNMP.Client~~~~0.0.1.0", "Tools.DeveloperMode.Core~~~~0.0.1.0", "Tools.DTrace.Platform~~~~0.0.1.0", "Tools.Graphics.DirectX~~~~0.0.1.0", "WMI-SNMP-Provider.Client~~~~0.0.1.0", "XPS.Viewer~~~~0.0.1.0") $Win10_1809_FODs = @("Accessibility.Braille~~~~0.0.1.0", "Analog.Holographic.Desktop~~~~0.0.1.0", "App.Support.QuickAssist~~~~0.0.1.0", "Browser.InternetExplorer~~~~0.0.11.0", "Hello.Face.17658~~~~0.0.1.0", "Hello.Face.Migration.17658~~~~0.0.1.0", "Language.Basic~~~af-ZA~0.0.1.0", "Language.Basic~~~ar-SA~0.0.1.0", "Language.Basic~~~as-IN~0.0.1.0", "Language.Basic~~~az-LATN-AZ~0.0.1.0", "Language.Basic~~~ba-RU~0.0.1.0", "Language.Basic~~~be-BY~0.0.1.0", "Language.Basic~~~bg-BG~0.0.1.0", "Language.Basic~~~bn-BD~0.0.1.0", "Language.Basic~~~bn-IN~0.0.1.0", "Language.Basic~~~bs-LATN-BA~0.0.1.0", "Language.Basic~~~ca-ES~0.0.1.0", "Language.Basic~~~cs-CZ~0.0.1.0", "Language.Basic~~~cy-GB~0.0.1.0", "Language.Basic~~~da-DK~0.0.1.0", "Language.Basic~~~de-DE~0.0.1.0", "Language.Basic~~~el-GR~0.0.1.0", "Language.Basic~~~en-GB~0.0.1.0", "Language.Basic~~~en-US~0.0.1.0", "Language.Basic~~~es-ES~0.0.1.0", "Language.Basic~~~es-MX~0.0.1.0", "Language.Basic~~~et-EE~0.0.1.0", "Language.Basic~~~eu-ES~0.0.1.0", "Language.Basic~~~fa-IR~0.0.1.0", "Language.Basic~~~fi-FI~0.0.1.0", "Language.Basic~~~fil-PH~0.0.1.0", "Language.Basic~~~fr-CA~0.0.1.0", "Language.Basic~~~fr-FR~0.0.1.0", "Language.Basic~~~ga-IE~0.0.1.0", "Language.Basic~~~gd-GB~0.0.1.0", "Language.Basic~~~gl-ES~0.0.1.0", "Language.Basic~~~gu-IN~0.0.1.0", "Language.Basic~~~ha-LATN-NG~0.0.1.0", "Language.Basic~~~haw-US~0.0.1.0", "Language.Basic~~~he-IL~0.0.1.0", "Language.Basic~~~hi-IN~0.0.1.0", "Language.Basic~~~hr-HR~0.0.1.0", "Language.Basic~~~hu-HU~0.0.1.0", "Language.Basic~~~hy-AM~0.0.1.0", "Language.Basic~~~id-ID~0.0.1.0", "Language.Basic~~~ig-NG~0.0.1.0", "Language.Basic~~~is-IS~0.0.1.0", "Language.Basic~~~it-IT~0.0.1.0", "Language.Basic~~~ja-JP~0.0.1.0", "Language.Basic~~~ka-GE~0.0.1.0", "Language.Basic~~~kk-KZ~0.0.1.0", "Language.Basic~~~kl-GL~0.0.1.0", "Language.Basic~~~kn-IN~0.0.1.0", "Language.Basic~~~ko-KR~0.0.1.0", "Language.Basic~~~kok-DEVA-IN~0.0.1.0", "Language.Basic~~~ky-KG~0.0.1.0", "Language.Basic~~~lb-LU~0.0.1.0", "Language.Basic~~~lt-LT~0.0.1.0", "Language.Basic~~~lv-LV~0.0.1.0", "Language.Basic~~~mi-NZ~0.0.1.0", "Language.Basic~~~ml-IN~0.0.1.0", "Language.Basic~~~mk-MK~0.0.1.0", "Language.Basic~~~mn-MN~0.0.1.0", "Language.Basic~~~mr-IN~0.0.1.0", "Language.Basic~~~ms-BN~0.0.1.0", "Language.Basic~~~ms-MY~0.0.1.0", "Language.Basic~~~mt-MT~0.0.1.0", "Language.Basic~~~nb-NO~0.0.1.0", "Language.Basic~~~ne-NP~0.0.1.0", "Language.Basic~~~nl-NL~0.0.1.0", "Language.Basic~~~nn-NO~0.0.1.0", "Language.Basic~~~nso-ZA~0.0.1.0", "Language.Basic~~~or-IN~0.0.1.0", "Language.Basic~~~pa-IN~0.0.1.0", "Language.Basic~~~pl-PL~0.0.1.0", "Language.Basic~~~ps-AF~0.0.1.0", "Language.Basic~~~pt-BR~0.0.1.0", "Language.Basic~~~pt-PT~0.0.1.0", "Language.Basic~~~rm-CH~0.0.1.0", "Language.Basic~~~ro-RO~0.0.1.0", "Language.Basic~~~ru-RU~0.0.1.0", "Language.Basic~~~rw-RW~0.0.1.0", "Language.Basic~~~sah-RU~0.0.1.0", "Language.Basic~~~si-LK~0.0.1.0", "Language.Basic~~~sk-SK~0.0.1.0", "Language.Basic~~~sl-SI~0.0.1.0", "Language.Basic~~~sq-AL~0.0.1.0", "Language.Basic~~~sr-CYRL-RS~0.0.1.0", "Language.Basic~~~sr-LATN-RS~0.0.1.0", "Language.Basic~~~sv-SE~0.0.1.0", "Language.Basic~~~sw-KE~0.0.1.0", "Language.Basic~~~ta-IN~0.0.1.0", "Language.Basic~~~te-IN~0.0.1.0", "Language.Basic~~~tg-CYRL-TJ~0.0.1.0", "Language.Basic~~~th-TH~0.0.1.0", "Language.Basic~~~tk-TM~0.0.1.0", "Language.Basic~~~tn-ZA~0.0.1.0", "Language.Basic~~~tr-TR~0.0.1.0", "Language.Basic~~~tt-RU~0.0.1.0", "Language.Basic~~~ug-CN~0.0.1.0", "Language.Basic~~~uk-UA~0.0.1.0", "Language.Basic~~~ur-PK~0.0.1.0", "Language.Basic~~~uz-LATN-UZ~0.0.1.0", "Language.Basic~~~vi-VN~0.0.1.0", "Language.Basic~~~wo-SN~0.0.1.0", "Language.Basic~~~xh-ZA~0.0.1.0", "Language.Basic~~~yo-NG~0.0.1.0", "Language.Basic~~~zh-CN~0.0.1.0", "Language.Basic~~~zh-HK~0.0.1.0", "Language.Basic~~~zh-TW~0.0.1.0", "Language.Basic~~~zu-ZA~0.0.1.0", "Language.Fonts.Arab~~~und-ARAB~0.0.1.0", "Language.Fonts.Beng~~~und-BENG~0.0.1.0", "Language.Fonts.Cans~~~und-CANS~0.0.1.0", "Language.Fonts.Cher~~~und-CHER~0.0.1.0", "Language.Fonts.Deva~~~und-DEVA~0.0.1.0", "Language.Fonts.Ethi~~~und-ETHI~0.0.1.0", "Language.Fonts.Gujr~~~und-GUJR~0.0.1.0", "Language.Fonts.Guru~~~und-GURU~0.0.1.0", "Language.Fonts.Hans~~~und-HANS~0.0.1.0", "Language.Fonts.Hant~~~und-HANT~0.0.1.0", "Language.Fonts.Hebr~~~und-HEBR~0.0.1.0", "Language.Fonts.Jpan~~~und-JPAN~0.0.1.0", "Language.Fonts.Khmr~~~und-KHMR~0.0.1.0", "Language.Fonts.Knda~~~und-KNDA~0.0.1.0", "Language.Fonts.Kore~~~und-KORE~0.0.1.0", "Language.Fonts.Laoo~~~und-LAOO~0.0.1.0", "Language.Fonts.Mlym~~~und-MLYM~0.0.1.0", "Language.Fonts.Orya~~~und-ORYA~0.0.1.0", "Language.Fonts.PanEuropeanSupplementalFonts~~~~0.0.1.0", "Language.Fonts.Sinh~~~und-SINH~0.0.1.0", "Language.Fonts.Syrc~~~und-SYRC~0.0.1.0", "Language.Fonts.Taml~~~und-TAML~0.0.1.0", "Language.Fonts.Telu~~~und-TELU~0.0.1.0", "Language.Fonts.Thai~~~und-THAI~0.0.1.0", "Language.Handwriting~~~af-ZA~0.0.1.0", "Language.Handwriting~~~bs-LATN-BA~0.0.1.0", "Language.Handwriting~~~ca-ES~0.0.1.0", "Language.Handwriting~~~cs-CZ~0.0.1.0", "Language.Handwriting~~~cy-GB~0.0.1.0", "Language.Handwriting~~~da-DK~0.0.1.0", "Language.Handwriting~~~de-DE~0.0.1.0", "Language.Handwriting~~~el-GR~0.0.1.0", "Language.Handwriting~~~en-GB~0.0.1.0", "Language.Handwriting~~~en-US~0.0.1.0", "Language.Handwriting~~~es-ES~0.0.1.0", "Language.Handwriting~~~es-MX~0.0.1.0", "Language.Handwriting~~~eu-ES~0.0.1.0", "Language.Handwriting~~~fi-FI~0.0.1.0", "Language.Handwriting~~~fr-FR~0.0.1.0", "Language.Handwriting~~~ga-IE~0.0.1.0", "Language.Handwriting~~~gd-GB~0.0.1.0", "Language.Handwriting~~~gl-ES~0.0.1.0", "Language.Handwriting~~~hi-IN~0.0.1.0", "Language.Handwriting~~~hr-HR~0.0.1.0", "Language.Handwriting~~~id-ID~0.0.1.0", "Language.Handwriting~~~it-IT~0.0.1.0", "Language.Handwriting~~~ja-JP~0.0.1.0", "Language.Handwriting~~~ko-KR~0.0.1.0", "Language.Handwriting~~~lb-LU~0.0.1.0", "Language.Handwriting~~~mi-NZ~0.0.1.0", "Language.Handwriting~~~ms-BN~0.0.1.0", "Language.Handwriting~~~ms-MY~0.0.1.0", "Language.Handwriting~~~nb-NO~0.0.1.0", "Language.Handwriting~~~nl-NL~0.0.1.0", "Language.Handwriting~~~nn-NO~0.0.1.0", "Language.Handwriting~~~nso-ZA~0.0.1.0", "Language.Handwriting~~~pl-PL~0.0.1.0", "Language.Handwriting~~~pt-BR~0.0.1.0", "Language.Handwriting~~~pt-PT~0.0.1.0", "Language.Handwriting~~~rm-CH~0.0.1.0", "Language.Handwriting~~~ro-RO~0.0.1.0", "Language.Handwriting~~~ru-RU~0.0.1.0", "Language.Handwriting~~~rw-RW~0.0.1.0", "Language.Handwriting~~~sk-SK~0.0.1.0", "Language.Handwriting~~~sl-SI~0.0.1.0", "Language.Handwriting~~~sq-AL~0.0.1.0", "Language.Handwriting~~~sr-CYRL-RS~0.0.1.0", "Language.Handwriting~~~sr-LATN-RS~0.0.1.0", "Language.Handwriting~~~sv-SE~0.0.1.0", "Language.Handwriting~~~sw-KE~0.0.1.0", "Language.Handwriting~~~tn-ZA~0.0.1.0", "Language.Handwriting~~~tr-TR~0.0.1.0", "Language.Handwriting~~~wo-SN~0.0.1.0", "Language.Handwriting~~~xh-ZA~0.0.1.0", "Language.Handwriting~~~zh-CN~0.0.1.0", "Language.Handwriting~~~zh-HK~0.0.1.0", "Language.Handwriting~~~zh-TW~0.0.1.0", "Language.Handwriting~~~zu-ZA~0.0.1.0", "Language.OCR~~~ar-SA~0.0.1.0", "Language.OCR~~~bg-BG~0.0.1.0", "Language.OCR~~~bs-LATN-BA~0.0.1.0", "Language.OCR~~~cs-CZ~0.0.1.0", "Language.OCR~~~da-DK~0.0.1.0", "Language.OCR~~~de-DE~0.0.1.0", "Language.OCR~~~el-GR~0.0.1.0", "Language.OCR~~~en-GB~0.0.1.0", "Language.OCR~~~en-US~0.0.1.0", "Language.OCR~~~es-ES~0.0.1.0", "Language.OCR~~~es-MX~0.0.1.0", "Language.OCR~~~fi-FI~0.0.1.0", "Language.OCR~~~fr-CA~0.0.1.0", "Language.OCR~~~fr-FR~0.0.1.0", "Language.OCR~~~hr-HR~0.0.1.0", "Language.OCR~~~hu-HU~0.0.1.0", "Language.OCR~~~it-IT~0.0.1.0", "Language.OCR~~~ja-JP~0.0.1.0", "Language.OCR~~~ko-KR~0.0.1.0", "Language.OCR~~~nb-NO~0.0.1.0", "Language.OCR~~~nl-NL~0.0.1.0", "Language.OCR~~~pl-PL~0.0.1.0", "Language.OCR~~~pt-BR~0.0.1.0", "Language.OCR~~~pt-PT~0.0.1.0", "Language.OCR~~~ro-RO~0.0.1.0", "Language.OCR~~~ru-RU~0.0.1.0", "Language.OCR~~~sk-SK~0.0.1.0", "Language.OCR~~~sl-SI~0.0.1.0", "Language.OCR~~~sr-CYRL-RS~0.0.1.0", "Language.OCR~~~sr-LATN-RS~0.0.1.0", "Language.OCR~~~sv-SE~0.0.1.0", "Language.OCR~~~tr-TR~0.0.1.0", "Language.OCR~~~zh-CN~0.0.1.0", "Language.OCR~~~zh-HK~0.0.1.0", "Language.OCR~~~zh-TW~0.0.1.0", "Language.Speech~~~de-DE~0.0.1.0", "Language.Speech~~~en-AU~0.0.1.0", "Language.Speech~~~en-CA~0.0.1.0", "Language.Speech~~~en-GB~0.0.1.0", "Language.Speech~~~en-IN~0.0.1.0", "Language.Speech~~~en-US~0.0.1.0", "Language.Speech~~~es-ES~0.0.1.0", "Language.Speech~~~es-MX~0.0.1.0", "Language.Speech~~~fr-CA~0.0.1.0", "Language.Speech~~~fr-FR~0.0.1.0", "Language.Speech~~~it-IT~0.0.1.0", "Language.Speech~~~ja-JP~0.0.1.0", "Language.Speech~~~pt-BR~0.0.1.0", "Language.Speech~~~zh-CN~0.0.1.0", "Language.Speech~~~zh-HK~0.0.1.0", "Language.Speech~~~zh-TW~0.0.1.0", "Language.TextToSpeech~~~ar-EG~0.0.1.0", "Language.TextToSpeech~~~ar-SA~0.0.1.0", "Language.TextToSpeech~~~bg-BG~0.0.1.0", "Language.TextToSpeech~~~ca-ES~0.0.1.0", "Language.TextToSpeech~~~cs-CZ~0.0.1.0", "Language.TextToSpeech~~~da-DK~0.0.1.0", "Language.TextToSpeech~~~de-AT~0.0.1.0", "Language.TextToSpeech~~~de-CH~0.0.1.0", "Language.TextToSpeech~~~de-DE~0.0.1.0", "Language.TextToSpeech~~~el-GR~0.0.1.0", "Language.TextToSpeech~~~en-AU~0.0.1.0", "Language.TextToSpeech~~~en-CA~0.0.1.0", "Language.TextToSpeech~~~en-GB~0.0.1.0", "Language.TextToSpeech~~~en-IE~0.0.1.0", "Language.TextToSpeech~~~en-IN~0.0.1.0", "Language.TextToSpeech~~~en-US~0.0.1.0", "Language.TextToSpeech~~~es-ES~0.0.1.0", "Language.TextToSpeech~~~es-MX~0.0.1.0", "Language.TextToSpeech~~~fi-FI~0.0.1.0", "Language.TextToSpeech~~~fr-CA~0.0.1.0", "Language.TextToSpeech~~~fr-CH~0.0.1.0", "Language.TextToSpeech~~~fr-FR~0.0.1.0", "Language.TextToSpeech~~~he-IL~0.0.1.0", "Language.TextToSpeech~~~hi-IN~0.0.1.0", "Language.TextToSpeech~~~hr-HR~0.0.1.0", "Language.TextToSpeech~~~hu-HU~0.0.1.0", "Language.TextToSpeech~~~id-ID~0.0.1.0", "Language.TextToSpeech~~~it-IT~0.0.1.0", "Language.TextToSpeech~~~ja-JP~0.0.1.0", "Language.TextToSpeech~~~ko-KR~0.0.1.0", "Language.TextToSpeech~~~ms-MY~0.0.1.0", "Language.TextToSpeech~~~nb-NO~0.0.1.0", "Language.TextToSpeech~~~nl-BE~0.0.1.0", "Language.TextToSpeech~~~nl-NL~0.0.1.0", "Language.TextToSpeech~~~pl-PL~0.0.1.0", "Language.TextToSpeech~~~pt-BR~0.0.1.0", "Language.TextToSpeech~~~pt-PT~0.0.1.0", "Language.TextToSpeech~~~ro-RO~0.0.1.0", "Language.TextToSpeech~~~ru-RU~0.0.1.0", "Language.TextToSpeech~~~sk-SK~0.0.1.0", "Language.TextToSpeech~~~sl-SI~0.0.1.0", "Language.TextToSpeech~~~sv-SE~0.0.1.0", "Language.TextToSpeech~~~ta-IN~0.0.1.0", "Language.TextToSpeech~~~th-TH~0.0.1.0", "Language.TextToSpeech~~~tr-TR~0.0.1.0", "Language.TextToSpeech~~~vi-VN~0.0.1.0", "Language.TextToSpeech~~~zh-CN~0.0.1.0", "Language.TextToSpeech~~~zh-HK~0.0.1.0", "Language.TextToSpeech~~~zh-TW~0.0.1.0", "MathRecognizer~~~~0.0.1.0", "Media.WindowsMediaPlayer~~~~0.0.12.0", "Microsoft.Onecore.StorageManagement~~~~0.0.1.0", "Microsoft.WebDriver~~~~0.0.1.0", "Microsoft.Windows.StorageManagement~~~~0.0.1.0", "Msix.PackagingTool.Driver~~~~0.0.1.0", "NetFX3~~~~" "OneCoreUAP.OneSync~~~~0.0.1.0", "OpenSSH.Client~~~~0.0.1.0", "OpenSSH.Server~~~~0.0.1.0", "RasCMAK.Client~~~~0.0.1.0", "RIP.Listener~~~~0.0.1.0", "Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0", "Rsat.BitLocker.Recovery.Tools~~~~0.0.1.0", "Rsat.CertificateServices.Tools~~~~0.0.1.0", "Rsat.DHCP.Tools~~~~0.0.1.0", "Rsat.Dns.Tools~~~~0.0.1.0", "Rsat.FailoverCluster.Management.Tools~~~~0.0.1.0", "Rsat.FileServices.Tools~~~~0.0.1.0", "Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0", "Rsat.IPAM.Client.Tools~~~~0.0.1.0", "Rsat.LLDP.Tools~~~~0.0.1.0", "Rsat.NetworkController.Tools~~~~0.0.1.0", "Rsat.NetworkLoadBalancing.Tools~~~~0.0.1.0", "Rsat.RemoteAccess.Management.Tools~~~~0.0.1.0", "Rsat.RemoteDesktop.Services.Tools~~~~0.0.1.0", "Rsat.ServerManager.Tools~~~~0.0.1.0", "Rsat.Shielded.VM.Tools~~~~0.0.1.0", "Rsat.StorageMigrationService.Management.Tools~~~~0.0.1.0", "Rsat.StorageReplica.Tools~~~~0.0.1.0", "Rsat.SystemInsights.Management.Tools~~~~0.0.1.0", "Rsat.VolumeActivation.Tools~~~~0.0.1.0", "Rsat.WSUS.Tools~~~~0.0.1.0", "SNMP.Client~~~~0.0.1.0", "Tools.DeveloperMode.Core~~~~0.0.1.0", "Tools.DTrace.Platform~~~~0.0.1.0", "Tools.Graphics.DirectX~~~~0.0.1.0", "WMI-SNMP-Provider.Client~~~~0.0.1.0", "XPS.Viewer~~~~0.0.1.0" ) If ($WinOS -eq "Windows 10"){ If ($Winver -eq "1909"){$items = ($Win10_1909_FODs | Out-GridView -title "Select Features On Demand" -PassThru) } If ($Winver -eq "1903"){$items = ($Win10_1903_FODs | Out-GridView -title "Select Features On Demand" -PassThru) } If ($Winver -eq "1809"){$items = ($Win10_1809_FODs | Out-GridView -title "Select Features On Demand" -PassThru) } } foreach ($item in $items){$WPFCustomLBFOD.Items.Add($item)} } #Function to apply the selected Langauge Packs to the mounted WIM function apply-LanguagePacks{ Update-Log -data "Applying Language Packs..." -Class Information if ($WPFSourceWIMImgDesTextBox.text -like '*10*'){$WinOS = "Windows 10"} Else {$WinOS = "Windows Server"} If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { $WinVer = "1909" } If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $WinVer = "1809" } $mountdir = $WPFMISMountTextBox.text $LPSourceFolder = $PSScriptRoot + '\imports\Lang\' + $WinOS + '\' + $winver + '\LanguagePacks\' $items = $WPFCustomLBLangPacks.items foreach ($item in $items){ $source = $LPSourceFolder + $item # write-host $source $text = 'Applying ' + $item Update-Log -Data $text -Class Information Add-WindowsPackage -PackagePath $source -Path $mountdir | out-null Update-Log -Data "Injection Successful" -Class Information } Update-Log -Data "Language Pack injections complete" -Class Information } #Function to apply selected LXPs to the mounted WIM function apply-localexperiencepack{ Update-Log -data "Applying Local Experience Packs..." -Class Information if ($WPFSourceWIMImgDesTextBox.text -like '*10*'){$WinOS = "Windows 10"} Else {$WinOS = "Windows Server"} If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { $WinVer = "1909" } If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $WinVer = "1809" } $mountdir = $WPFMISMountTextBox.text $LPSourceFolder = $PSScriptRoot + '\imports\Lang\' + $WinOS + '\' + $winver + '\localexperiencepack\' $items = $WPFCustomLBLEP.items foreach ($item in $items){ $source = $LPSourceFolder + $item $license = get-item -Path $source\*.xml $file = get-item -Path $source\*.appx $text = 'Applying ' + $item Update-Log -Data $text -Class Information Add-ProvisionedAppxPackage -PackagePath $file -LicensePath $license -Path $mountdir | out-null Update-Log -Data "Injection Successful" -Class Information } Update-Log -Data "Local Experience Pack injections complete" -Class Information } #Function to apply selected FODs to the mounted WIM function apply-FODs{ Update-Log -data "Applying Features On Demand..." -Class Information if ($WPFSourceWIMImgDesTextBox.text -like '*10*'){$WinOS = "Windows 10"} Else {$WinOS = "Windows Server"} If ($WPFSourceWimVerTextBox.text -like "10.0.18362.*") { $WinVer = "1909" } If ($WPFSourceWimVerTextBox.text -like "10.0.17763.*") { $WinVer = "1809" } $mountdir = $WPFMISMountTextBox.text $FODsource = $PSScriptRoot + '\imports\FODs\' + $winOS + '\' + $Winver + '\' $items = $WPFCustomLBFOD.items foreach ($item in $items){ $text = "Applying " + $item update-log -Data $text -Class Information Add-WindowsCapability -Path $mountdir -Name $item -Source $FODsource | out-null Update-Log -Data "Injection Successful" -Class Information } Update-Log -Data "Feature on Demand injections complete" -Class Information } #Function to import the selected LP's in to the Imports folder Function import-LanguagePacks($Winver,$LPSourceFolder,$WinOS){ update-log -Data "Importing Language Packs..." -Class Information if ((test-path -Path $PSScriptRoot\imports\Lang\$WinOS\$winver\LanguagePacks) -eq $False){ Update-Log -Data "Destination folder does not exist. Creating..." -Class Warning $path = $PSScriptRoot + '\imports\Lang\' + $WinOS + '\' + $winver +'\LanguagePacks' $text = 'Creating folder ' + $path update-log -data $text -Class Information New-Item -Path $PSScriptRoot\imports\Lang\$WinOS\$winver -Name LanguagePacks -ItemType Directory update-log -Data "Folder created successfully" -Class Information } $items = $WPFImportOtherLBList.items foreach ($item in $items){ $source = $LPSourceFolder + $item $text = 'Importing ' + $item update-log -Data $text -Class Information Copy-Item $source -destination $PSScriptRoot\imports\Lang\$WinOS\$Winver\LanguagePacks -Force} update-log -Data "Importation Complete" -Class Information } #Function to import the selected LXP's into the imports forlder Function import-LocalExperiencePack($Winver,$LPSourceFolder,$WinOS){ update-log -Data "Importing Local Experience Packs..." -Class Information if ((test-path -Path $PSScriptRoot\imports\Lang\$WinOS\$winver\localexperiencepack) -eq $False){ Update-Log -Data "Destination folder does not exist. Creating..." -Class Warning $path = $PSScriptRoot + '\imports\Lang\' + $WinOS + '\' + $winver +'\localexperiencepack' $text = 'Creating folder ' + $path update-log -data $text -Class Information New-Item -Path $PSScriptRoot\imports\Lang\$WinOS\$winver -Name localexperiencepack -ItemType Directory update-log -Data "Folder created successfully" -Class Information } $items = $WPFImportOtherLBList.items foreach ($item in $items){ $name = $item $source = $LPSourceFolder + $name $text = 'Creating destination folder for ' + $item update-log -Data $text -Class Information if ((test-path -Path $PSScriptRoot\imports\lang\$WinOS\$winver\localexperiencepack\$name) -eq $False){New-Item -Path $PSScriptRoot\imports\lang\$WinOS\$winver\localexperiencepack -Name $name -ItemType Directory} else {$text = 'The folder for ' + $item + ' already exists. Skipping creation...' Update-Log -Data $text -Class Warning} Update-Log -Data "Copying source to destination folders..." -Class Information get-childitem -path $source | Copy-Item -destination $PSScriptRoot\imports\Lang\$WinOS\$Winver\LocalExperiencePack\$name -Force} Update-log -Data "Importation complete" -Class Information } #Function to import the contents of the selected FODs into the imports forlder Function import-FOD($Winver,$LPSourceFolder,$WinOS){ $path = $WPFImportOtherTBPath.text $text = 'Starting importation of Feature On Demand binaries from ' + $path update-log -Data $text -Class Information $langpacks = Get-ChildItem -path $LPSourceFolder if ((test-path -Path $PSScriptRoot\imports\FODs\$WinOS\$Winver) -eq $False){ Update-Log -Data "Destination folder does not exist. Creating..." -Class Warning $path = $PSScriptRoot + '\imports\FODs\' + $WinOS + '\' + $winver $text = 'Creating folder ' + $path update-log -data $text -Class Information New-Item -Path $PSScriptRoot\imports\fods\$WinOS -Name $winver -ItemType Directory update-log -Data "Folder created successfully" -Class Information } foreach ($langpack in $langpacks){ $source = $LPSourceFolder + $langpack.name Copy-Item $source -destination $PSScriptRoot\imports\FODs\$WinOS\$Winver\ -Force $name = $langpack.name $text = 'Copying ' + $name Update-Log -Data $text -Class Information } Update-Log -Data "Importing metadata subfolder..." -Class Information get-childitem -path ($LPSourceFolder + '\metadata\') | Copy-Item -destination $PSScriptRoot\imports\FODs\$WinOS\$Winver\metadata -force update-log -data "Feature On Demand imporation complete." } #Function to update winver cobmo box function update-importverCB{ $WPFImportOtherCBWinVer.Items.Clear() if ($WPFImportOtherCBWinOS.SelectedItem -eq "Windows Server"){Foreach ($WinSrvVer in $WinSrvVer){$WPFImportOtherCBWinVer.Items.Add($WinSrvVer)}} if ($WPFImportOtherCBWinOS.SelectedItem -eq "Windows 10"){Foreach ($Win10Ver in $Win10ver){$WPFImportOtherCBWinVer.Items.Add($Win10Ver)}} } #function to select other object import source path function select-importotherpath{ Add-Type -AssemblyName System.Windows.Forms $browser = New-Object System.Windows.Forms.FolderBrowserDialog $browser.Description = "Source folder" $null = $browser.ShowDialog() $ImportPath = $browser.SelectedPath + '\' $WPFImportOtherTBPath.text = $ImportPath } #function to allow user to pause MAke it so process function pause-makeitso{ $MISPause = ([System.Windows.MessageBox]::Show("Click Yes to continue the image build. Click No to cancel and discard the wim file.",'WIM Witch Paused','YesNo','Warning')) if ($MISPause -eq "Yes"){return "Yes"} if ($MISPause -eq "No"){ return "No"} } #function to run a powershell script with supplied paramenters function run-script($file,$parameter){ $string = "$file $parameter" try{ update-log -Data "Running script" -Class Information Invoke-Expression -command $string -ErrorAction Stop update-log -data "Script complete" -Class Information } catch { update-log -Data "Script failed" -Class Error } } #=========================================================================== # Run commands to set values of files and variables, etc. #=========================================================================== #calls fuction to display the opening text blurb display-openingtext check-install #Set the path and name for logging $Log = "$PSScriptRoot\logging\WIMWitch.log" Set-Logging #Clears out old logs from previous builds and checks for other folders #The OSD Update functions. Disable the following four to increase start time. check-superced takes the longest - FYI #=========================================================================== Check-WIMWitchVer #Checks installed version of WIM Witch and updates if selected Get-OSDBInstallation #Sets OSDUpate version info Get-OSDBCurrentVer #Discovers current version of OSDUpdate compare-OSDBuilderVer #determines if an update of OSDUpdate can be applied get-osdsusinstallation #Sets OSDSUS version info Get-OSDSUSCurrentVer #Discovers current version of OSDSUS compare-OSDSUSVer #determines if an update of OSDSUS can be applied #Function download-patches($build,$OS) if ($DownloadUpdates -eq $true) { If (($UpdatePoShModules -eq $true) -and ($WPFUpdatesOSDBOutOfDateTextBlock.Visibility -eq "Visible")) { update-OSDB Update-OSDSUS } if ($Server2016 -eq $true){ check-superceded -action delete -OS "Windows Server 2016" -Build 1607 download-patches -OS "Windows Server 2016" -build 1607} if ($Server2019 -eq $true){ check-superceded -action delete -OS "Windows Server 2019" -Build 1809 download-patches -OS "Windows Server 2019" -build 1809} if ($Win10Version -ne "none"){ if (($Win10Version -eq "1709") -or ($Win10Version -eq "all")){ check-superceded -action delete -OS "Windows 10" -Build 1709 download-patches -OS "Windows 10" -build 1709} if (($Win10Version -eq "1803") -or ($Win10Version -eq "all")){ check-superceded -action delete -OS "Windows 10" -Build 1803 download-patches -OS "Windows 10" -build 1803} if (($Win10Version -eq "1809") -or ($Win10Version -eq "all")){ check-superceded -action delete -OS "Windows 10" -Build 1809 download-patches -OS "Windows 10" -build 1809} if (($Win10Version -eq "1903") -or ($Win10Version -eq "all")){ check-superceded -action delete -OS "Windows 10" -Build 1903 download-patches -OS "Windows 10" -build 1903} if (($Win10Version -eq "1909") -or ($Win10Version -eq "all")){ check-superceded -action delete -OS "Windows 10" -Build 1909 download-patches -OS "Windows 10" -build 1909} download-onedrive } } #=========================================================================== #=========================================================================== # Set default values for certain variables #=========================================================================== #Set the value of the JSON field in Make It So tab $WPFMISJSONTextBox.Text = "False" #Set the value of the Driver field in the Make It So tab $WPFMISDriverTextBox.Text = "False" #Set the value of the Updates field in the Make It So tab $WPFMISUpdatesTextBox.Text = "False" $WPFMISAppxTextBox.Text = "False" #$WPFAppTab.IsEnabled = $False #=========================================================================== # Section for Combo box functions #=========================================================================== #Set the combo box values of the other import tab $ObjectTypes = @("Language Pack","Local Experience Pack","Feature On Demand") $WinOS = @("Windows Server","Windows 10") $WinSrvVer = @("2019") $Win10Ver = @("1809","1903","1909") Foreach ($ObjectType in $ObjectTypes){$WPFImportOtherCBType.Items.Add($ObjectType) | out-null} Foreach ($WinOS in $WinOS){$WPFImportOtherCBWinOS.Items.Add($WinOS) | out-null} #Run Script Timing combox box $RunScriptActions = @("After image mount","Before image dismount","On build completion") Foreach ($RunScriptAction in $RunScriptActions){$WPFCustomCBScriptTiming.Items.add($RunScriptAction) | out-null} #=========================================================================== # Section for Buttons to call functions #=========================================================================== #Mount Dir Button $WPFMISMountSelectButton.Add_Click( { SelectMountdir }) #Source WIM File Button $WPFSourceWIMSelectButton.Add_Click( { SelectSourceWIM }) #JSON File selection Button $WPFJSONButton.Add_Click( { SelectJSONFile }) #Target Folder selection Button $WPFMISFolderButton.Add_Click( { SelectTargetDir }) #Driver Directory Buttons $WPFDriverDir1Button.Add_Click( { SelectDriverSource -DriverTextBoxNumber $WPFDriverDir1TextBox }) $WPFDriverDir2Button.Add_Click( { SelectDriverSource -DriverTextBoxNumber $WPFDriverDir2TextBox }) $WPFDriverDir3Button.Add_Click( { SelectDriverSource -DriverTextBoxNumber $WPFDriverDir3TextBox }) $WPFDriverDir4Button.Add_Click( { SelectDriverSource -DriverTextBoxNumber $WPFDriverDir4TextBox }) $WPFDriverDir5Button.Add_Click( { SelectDriverSource -DriverTextBoxNumber $WPFDriverDir5TextBox }) #Make it So Button, which builds the WIM file $WPFMISMakeItSoButton.Add_Click( { MakeItSo -appx $global:SelectedAppx }) #Update OSDBuilder Button $WPFUpdateOSDBUpdateButton.Add_Click( { update-OSDB Update-OSDSUS }) #Update patch source $WPFUpdatesDownloadNewButton.Add_Click( { update-patchsource }) #Logging window #$WPFLoggingTextBox.text = Get-Content -Path $Log -Delimiter "\n" #Select Appx packages to remove $WPFAppxButton.Add_Click( { $global:SelectedAppx = Select-Appx }) #Select Autopilot path to save button $WPFJSONButtonSavePath.Add_Click( { SelectNewJSONDir }) #retrieve autopilot profile from intune $WPFJSONButtonRetrieve.Add_click( { get-wwautopilotprofile -login $WPFJSONTextBoxAADID.Text -path $WPFJSONTextBoxSavePath.Text }) #Button to save configuration file $WPFSLSaveButton.Add_click( { save-config -filename $WPFSLSaveFileName.text }) #Button to load configuration file $WPFSLLoadButton.Add_click( { select-config }) #Button to select ISO for importation $WPFImportImportSelectButton.Add_click( { select-iso }) #Button to import content from iso $WPFImportImportButton.Add_click( { if (($WPFImportDotNetCheckBox.IsChecked -eq $true) -and ($WPFImportWIMCheckBox.IsChecked -eq $true)) { import-iso -type all -file $WPFImportISOTextBox.text -newname $WPFImportNewNameTextBox.text } if (($WPFImportDotNetCheckBox.IsChecked -eq $true) -and ($WPFImportWIMCheckBox.IsChecked -eq $false)) { import-iso -type DotNet -file $WPFImportISOTextBox.text } if (($WPFImportDotNetCheckBox.IsChecked -eq $false) -and ($WPFImportWIMCheckBox.IsChecked -eq $true)) { import-iso -type wim -file $WPFImportISOTextBox.text -newname $WPFImportNewNameTextBox.text } }) #Combo Box dynamic change for Winver combo box $WPFImportOtherCBWinOS.add_SelectionChanged({update-importverCB}) #Button to select the import path in the other components $WPFImportOtherBSelectPath.add_click({select-importotherpath if ($WPFImportOtherCBType.SelectedItem -ne "Feature On Demand"){$items = (Get-ChildItem -path $WPFImportOtherTBPath.text | Select-Object -Property Name | Out-GridView -title "Select Objects" -PassThru)} if ($WPFImportOtherCBType.SelectedItem -eq "Feature On Demand"){$items = (get-Childitem -path $WPFImportOtherTBPath.text)} $WPFImportOtherLBList.Items.Clear() $count = 0 $path = $WPFImportOtherTBPath.text foreach ($item in $items){ $WPFImportOtherLBList.Items.Add($item.name) $count = $count + 1 } if ($wpfImportOtherCBType.SelectedItem -eq "Language Pack"){update-log -data "$count Language Packs selected from $path" -Class Information} if ($wpfImportOtherCBType.SelectedItem -eq "Local Experience Pack"){update-log -data "$count Local Experience Packs selected from $path" -Class Information} if ($wpfImportOtherCBType.SelectedItem -eq "Feature On Demand"){update-log -data "Features On Demand source selected from $path" -Class Information} }) #Button to import Other Components content $WPFImportOtherBImport.add_click({ if ($WPFImportOtherCBType.SelectedItem -eq "Language Pack"){import-LanguagePacks -Winver $WPFImportOtherCBWinVer.SelectedItem -WinOS $WPFImportOtherCBWinOS.SelectedItem -LPSourceFolder $WPFImportOtherTBPath.text} if ($WPFImportOtherCBType.SelectedItem -eq "Local Experience Pack"){import-LocalExperiencePack -Winver $WPFImportOtherCBWinVer.SelectedItem -WinOS $WPFImportOtherCBWinOS.SelectedItem -LPSourceFolder $WPFImportOtherTBPath.text} if ($WPFImportOtherCBType.SelectedItem -eq "Feature On Demand"){import-FOD -Winver $WPFImportOtherCBWinVer.SelectedItem -WinOS $WPFImportOtherCBWinOS.SelectedItem -LPSourceFolder $WPFImportOtherTBPath.text}}) #Button Select LP's for importation $WPFCustomBLangPacksSelect.add_click({select-LPFODCriteria -type "LP"}) #Button to select FODs for importation $WPFCustomBFODSelect.add_click({select-LPFODCriteria -type "FOD"}) #Button to select LXPs for importation $WPFCustomBLEPSelect.add_click({select-LPFODCriteria -type "LXP" }) #Button to select PS1 script $WPFCustomBSelectPath.add_click({ $Script = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = [Environment]::GetFolderPath('Desktop') Filter = 'PS1 (*.ps1)|' } $null = $Script.ShowDialog() $WPFCustomTBFile.text = $Script.FileName }) #=========================================================================== # Section for Checkboxes to call functions #=========================================================================== #Enable JSON Selection $WPFJSONEnableCheckBox.Add_Click( { If ($WPFJSONEnableCheckBox.IsChecked -eq $true) { $WPFJSONButton.IsEnabled = $True $WPFMISJSONTextBox.Text = "True" } else { $WPFJSONButton.IsEnabled = $False $WPFMISJSONTextBox.Text = "False" } }) #Enable Driver Selection $WPFDriverCheckBox.Add_Click( { If ($WPFDriverCheckBox.IsChecked -eq $true) { $WPFDriverDir1Button.IsEnabled = $True $WPFDriverDir2Button.IsEnabled = $True $WPFDriverDir3Button.IsEnabled = $True $WPFDriverDir4Button.IsEnabled = $True $WPFDriverDir5Button.IsEnabled = $True $WPFMISDriverTextBox.Text = "True" } else { $WPFDriverDir1Button.IsEnabled = $False $WPFDriverDir2Button.IsEnabled = $False $WPFDriverDir3Button.IsEnabled = $False $WPFDriverDir4Button.IsEnabled = $False $WPFDriverDir5Button.IsEnabled = $False $WPFMISDriverTextBox.Text = "False" } }) #Enable Updates Selection $WPFUpdatesEnableCheckBox.Add_Click( { If ($WPFUpdatesEnableCheckBox.IsChecked -eq $true) { $WPFMISUpdatesTextBox.Text = "True" } else { $WPFMISUpdatesTextBox.Text = "False" } }) #Enable AppX Selection $WPFAppxCheckBox.Add_Click( { If ($WPFAppxCheckBox.IsChecked -eq $true) { $WPFAppxButton.IsEnabled = $True $WPFMISAppxTextBox.Text = "True" } else { $WPFAppxButton.IsEnabled = $False } }) #Enable install.wim selection in import $WPFImportWIMCheckBox.Add_Click( { If ($WPFImportWIMCheckBox.IsChecked -eq $true) { $WPFImportNewNameTextBox.IsEnabled = $True $WPFImportImportButton.IsEnabled = $True } else { $WPFImportNewNameTextBox.IsEnabled = $False if ($WPFImportDotNetCheckBox.IsChecked -eq $False) { $WPFImportImportButton.IsEnabled = $False } } }) #Enable .Net binaries selection in import $WPFImportDotNetCheckBox.Add_Click( { If ($WPFImportDotNetCheckBox.IsChecked -eq $true) { $WPFImportImportButton.IsEnabled = $True } else { if ($WPFImportWIMCheckBox.IsChecked -eq $False) { $WPFImportImportButton.IsEnabled = $False } } }) #Enable Win10 version selection $WPFUpdatesW10Main.Add_Click( { If ($WPFUpdatesW10Main.IsChecked -eq $true) { $WPFUpdatesW10_1909.IsEnabled = $True $WPFUpdatesW10_1903.IsEnabled = $True $WPFUpdatesW10_1809.IsEnabled = $True $WPFUpdatesW10_1803.IsEnabled = $True $WPFUpdatesW10_1709.IsEnabled = $True } else { $WPFUpdatesW10_1909.IsEnabled = $False $WPFUpdatesW10_1903.IsEnabled = $False $WPFUpdatesW10_1809.IsEnabled = $False $WPFUpdatesW10_1803.IsEnabled = $False $WPFUpdatesW10_1709.IsEnabled = $False } }) #Enable LP Selection $WPFCustomCBLangPacks.Add_Click({ If ($WPFCustomCBLangPacks.IsChecked -eq $true){$WPFCustomBLangPacksSelect.IsEnabled = $True} else {$WPFCustomBLangPacksSelect.IsEnabled = $False} }) #ENable Language Experience Pack selection $WPFCustomCBLEP.Add_Click({ If ($WPFCustomCBLEP.IsChecked -eq $true){$WPFCustomBLEPSelect.IsEnabled = $True} else {$WPFCustomBLEPSelect.IsEnabled = $False} }) #Enable Feature On Demand selection $WPFCustomCBFOD.Add_Click({ If ($WPFCustomCBFOD.IsChecked -eq $true){$WPFCustomBFODSelect.IsEnabled = $True} else {$WPFCustomBFODSelect.IsEnabled = $False} }) #Enable Run Script settings $WPFCustomCBRunScript.Add_Click({ If ($WPFCustomCBRunScript.IsChecked -eq $true){ $WPFCustomTBFile.IsEnabled = $True $WPFCustomBSelectPath.IsEnabled = $True $WPFCustomTBParameters.IsEnabled = $True $WPFCustomCBScriptTiming.IsEnabled = $True } else {$WPFCustomTBFile.IsEnabled = $False $WPFCustomBSelectPath.IsEnabled = $False $WPFCustomTBParameters.IsEnabled = $False $WPFCustomCBScriptTiming.IsEnabled = $False} }) #========================================================== #Run WIM Witch below #========================================================== #Runs WIM Witch from a single file, bypassing the GUI if (($auto -eq $true) -and ($autofile -ne "")) { run-configfile -filename $autofile display-closingtext exit 0 } if (($auto -eq $true) -and ($autopath -ne "")) { Update-Log -data "Running batch job from config folder $autopath" -Class Information $files = Get-ChildItem -Path $autopath Update-Log -data "Setting batch job for the folling configs:" -Class Information foreach ($file in $files) { Update-Log -Data $file -Class Information } foreach ($file in $files) { $fullpath = $autopath + '\' + $file run-configfile -filename $fullpath } Update-Log -Data "Work complete" -Class Information display-closingtext exit 0 } #Closing action for the WPF form Register-ObjectEvent -InputObject $form -EventName Closed -Action ( { display-closingtext }) | Out-Null #Start GUI update-log -data "Starting WIM Witch GUI" -class Information $Form.ShowDialog() | out-null #This starts the GUI |