Public/New-UnattendXml.ps1
function New-UnattendXml { <# .Synopsis Create a new Unattend.xml .DESCRIPTION This Command Creates a new Unattend.xml that skips any prompts, and sets the administrator password Has options for: Joining domain Adding user accounts Auto logon a set number of times Set the Computer Name First Boot or First Logon powersrhell script Product Key TimeZone Input, System and User Locals UI Language Registered Owner and Orginization First Boot, First Logon and Every Logon Commands Enable Administrator account without autologon (client OS) If no Path is provided a the file will be created in a temp folder and the path returned. .EXAMPLE New-UnattendXml -AdminPassword 'P@ssword' -logonCount 1 Create an an randomly named xml in $env:temp that will set the Administrator Password and autologin 1 time. outputing the path to the file .EXAMPLE New-UnattendXml -Path c:\temp\Unattent.xml -AdminPassword 'P@ssword' -logonCount 100 -FirstLogonScriptPath c:\pstemp\firstrun.ps1 Create an Unattend in at c:\temp\Unattend.xml that :, Sets the Administrator Password Sets the auto logon count to 100 (basicly every reboot untill you manualy logoff) Call c:\pstemp\firstrun.ps1 for each new user's first logon #> [CmdletBinding(DefaultParameterSetName = 'Basic_FirstLogonScript', SupportsShouldProcess = $true)] [OutputType([System.IO.FileInfo])] Param ( # The password to have unattnd.xml set the local Administrator to (minimum lenght 8) [Parameter(Mandatory = $true, HelpMessage = 'Local Administrator Credentials', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [Alias('AdminPassword')] [System.Management.Automation.Credential()][PSCredential] $AdminCredential, # User account/password to create and add to Administators group [System.Management.Automation.Credential()][PSCredential[]] $UserAccount, # User account/password to join do the domain MUST use Domain\User or user@domain format [System.Management.Automation.Credential()][PSCredential] $JoinAccount, # Domain to join [string] $domain, # OU to place computer account into [string] $OU, # Output Path [Alias('FilePath', 'FullName', 'pspath', 'outfile')] [string] $Path = "$(New-TemporaryDirectory)\unattend.xml", # Number of times that the local Administrator account should automaticaly login (default 0) [ValidateRange(0, 1000)] [int] $LogonCount, # ComputerName (default = *) [ValidateLength(1, 15)] [string] $ComputerName = '*', # PowerShell Script to run on FirstLogon (ie. %SystemDrive%\PSTemp\FirstRun.ps1 ) [Parameter(ParameterSetName = 'Basic_FirstLogonScript')] [string] $FirstLogonScriptPath, # PowerShell Script to run on FirstBoot (ie.: %SystemDrive%\PSTemp\FirstRun.ps1 ) Executed in system context during specialize phase [Parameter(ParameterSetName = 'Basic_FirstBootScript')] [string] $FirstBootScriptPath, # The product key to use for the unattended installation. [ValidatePattern('^[A-Z0-9]{5,5}-[A-Z0-9]{5,5}-[A-Z0-9]{5,5}-[A-Z0-9]{5,5}-[A-Z0-9]{5,5}$')] [string] $ProductKey, # Timezone (default: Timezone of the local Computer) [ArgumentCompleter( { param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters ) $possibleValues = [System.TimeZoneInfo]::GetSystemTimeZones().ID | Where-Object { $_ -like "$wordToComplete*" } | Foreach-Object{ if ($_ -like '* *') { "'{0}'" -f $_ } else {$_}} $possibleValues | ForEach-Object {$_} } )] [ValidateScript({ trap [System.TimeZoneNotFoundException] {$false} $null -ne [System.TimeZoneInfo]::FindSystemTimeZoneById($_) })] [string] $TimeZone = [System.TimeZoneInfo]::Local.Id, # Specifies the system input locale and the keyboard layout (default: current system language) [Parameter(ValueFromPipelineByPropertyName)] [ArgumentCompleter( { param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters ) $possibleValues = [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::AllCultures).Name | Where-Object { $_ -like '*-*' } | Where-Object { $_ -like "$wordToComplete*" } $possibleValues | ForEach-Object {$_} } )] [ValidateScript({ trap [System.Globalization.CultureNotFoundException] {$false} $null -ne [System.Globalization.CultureInfo]::GetCultureInfo($_) })] [Alias('keyboardlayout')] [String] $InputLocale = [System.Globalization.Cultureinfo]::CurrentCulture.Name, # Specifies the language for non-Unicode programs (default: Current system language) [Parameter(ValueFromPipelineByPropertyName)] [ArgumentCompleter( { param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters ) $possibleValues = [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::AllCultures).Name | Where-Object { $_ -like '*-*' } | Where-Object { $_ -like "$wordToComplete*" } $possibleValues | ForEach-Object {$_} } )] [ValidateScript({ trap [System.Globalization.CultureNotFoundException] {$false} $null -ne [System.Globalization.CultureInfo]::GetCultureInfo($_) })] [String] $SystemLocale = [System.Globalization.Cultureinfo]::CurrentCulture.Name, # Specifies the per-user settings used for formatting dates, times, currency and numbers (default: current system language) [Parameter(ValueFromPipelineByPropertyName)] [ArgumentCompleter( { param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters ) $possibleValues = [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::AllCultures).Name | Where-Object { $_ -like '*-*' } | Where-Object { $_ -like "$wordToComplete*" } $possibleValues | ForEach-Object {$_} } )] [ValidateScript({ trap [System.Globalization.CultureNotFoundException] {$false} $null -ne [System.Globalization.CultureInfo]::GetCultureInfo($_) })] [String] $UserLocale = [System.Globalization.Cultureinfo]::CurrentCulture.Name, # Specifies the system default user interface (UI) language (default: current system language) [Parameter(ValueFromPipelineByPropertyName)] [ArgumentCompleter( { param ( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters ) $possibleValues = [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::AllCultures).Name | Where-Object { $_ -like '*-*' } | Where-Object { $_ -like "$wordToComplete*" } $possibleValues | ForEach-Object {$_} } )] [ValidateScript({ trap [System.Globalization.CultureNotFoundException] {$false} $null -ne [System.Globalization.CultureInfo]::GetCultureInfo($_) })] [String] $UILanguage = [System.Globalization.Cultureinfo]::CurrentCulture.Name, # Registered Owner (default: 'Valued Customer') [Parameter(ValueFromPipelineByPropertyName)] [ValidateNotNull()] [String] $RegisteredOwner, # Registered Organization (default: 'Valued Customer') [Parameter(ValueFromPipelineByPropertyName)] [ValidateNotNull()] [String] $RegisteredOrganization, # Array of hashtables with Description, Order, and Path keys, and optional Domain, Password(plain text), username keys. Executed by in the system context [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Advanced')] [Hashtable[]] $FirstBootExecuteCommand, # Array of hashtables with Description, Order and CommandLine keys. Execuded at first logon of an Administrator, will auto elivate [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Advanced')] [Hashtable[]] $FirstLogonExecuteCommand, # Array of hashtables with Description, Order and CommandLine keys. Executed at every logon, does not elivate. [Parameter(ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Advanced')] [Hashtable[]] $EveryLogonExecuteCommand, # Enable Local Administrator account (default $true) this is needed for client OS if your not useing autologon or adding aditional admin users. [switch] $enableAdministrator ) Begin { $templateUnattendXml = [xml] @' <?xml version="1.0" encoding="utf-8"?> <unattend xmlns="urn:schemas-microsoft-com:unattend"> <settings pass="specialize"> <component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></component> <component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></component> <component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></component> <component name="Microsoft-Windows-Deployment" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></component> <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></component> <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></component> </settings> <settings pass="oobeSystem"> <component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <InputLocale>en-US</InputLocale> <SystemLocale>en-US</SystemLocale> <UILanguage>en-US</UILanguage> <UserLocale>en-US</UserLocale> </component> <component name="Microsoft-Windows-International-Core" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <InputLocale>en-US</InputLocale> <SystemLocale>en-US</SystemLocale> <UILanguage>en-US</UILanguage> <UserLocale>en-US</UserLocale> </component> <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <OOBE> <HideEULAPage>true</HideEULAPage> <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> <NetworkLocation>Work</NetworkLocation> <ProtectYourPC>1</ProtectYourPC> <SkipUserOOBE>true</SkipUserOOBE> <SkipMachineOOBE>true</SkipMachineOOBE> </OOBE> <TimeZone>GMT Standard Time</TimeZone> <UserAccounts> <AdministratorPassword> <Value></Value> <PlainText>false</PlainText> </AdministratorPassword> </UserAccounts> <RegisteredOrganization>Generic Organization</RegisteredOrganization> <RegisteredOwner>Generic Owner</RegisteredOwner> </component> <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <OOBE> <HideEULAPage>true</HideEULAPage> <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE> <NetworkLocation>Work</NetworkLocation> <ProtectYourPC>1</ProtectYourPC> <SkipUserOOBE>true</SkipUserOOBE> <SkipMachineOOBE>true</SkipMachineOOBE> </OOBE> <TimeZone>GMT Standard Time</TimeZone> <UserAccounts> <AdministratorPassword> <Value></Value> <PlainText>false</PlainText> </AdministratorPassword> </UserAccounts> <RegisteredOrganization>Generic Organization</RegisteredOrganization> <RegisteredOwner>Generic Owner</RegisteredOwner> </component> </settings> </unattend> '@ if ($LogonCount -gt 0) { Write-Warning -Message '-Autologon places the Administrator password in plain txt' } } Process { if ($pscmdlet.ShouldProcess("$path", 'Create new Unattended.xml')) { if ($FirstBootScriptPath) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding PowerShell script to First boot command" $FirstBootExecuteCommand = @(@{ Description = 'PowerShell First boot script' order = 1 path = "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"$FirstBootScriptPath`"" }) } if ($FirstLogonScriptPath) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding PowerShell script to First Logon command" $FirstLogonExecuteCommand = @(@{ Description = 'PowerShell First logon script' order = 1 CommandLine = "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"$FirstBootScriptPath`"" }) } if ($enableAdministrator) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Enabeling Administrator via First boot command" if ($FirstBootExecuteCommand) { $FirstBootExecuteCommand = $FirstBootExecuteCommand + @{ Description = 'Enable Administrator' order = 0 path = 'net user administrator /active:yes' } } else { $FirstBootExecuteCommand = @{ Description = 'Enable Administrator' order = 0 path = 'net user administrator /active:yes' } } } else { if ((-not ($UserAccount)) -or (-not($EnableAdministrator)) -or ( (-not ($domain)) -and (-not ($JoinAccount)) -and (-not ($OU)) ) ) { Write-Warning -Message "$Path only usable on a server SKU, for a client OS, use either -EnableAdministrator or -UserAccount, or (-Domain and -JoinAccount and -OU)" } } [xml] $unattendXml = $templateUnattendXml foreach ($setting in $unattendXml.Unattend.Settings) { foreach ($component in $setting.Component) { if ($setting.'Pass' -eq 'specialize' -and $component.'Name' -eq 'Microsoft-Windows-UnattendedJoin' ) { if (($JoinAccount) -or ($domain) -or ($OU)) { if (($JoinAccount) -and ($domain) -and ($OU)) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Unattend Domain Join for $($component.'processorArchitecture') Architecture" $identificationElement = $component.AppendChild($unattendXml.CreateElement('Identification', 'urn:schemas-microsoft-com:unattend')) $IdCredentialElement = $identificationElement.AppendChild($unattendXml.CreateElement('Credentials', 'urn:schemas-microsoft-com:unattend')) $IdCredDomainEliment = $IdCredentialElement.AppendChild($unattendXml.CreateElement('Domain', 'urn:schemas-microsoft-com:unattend')) $Null = $IdCredDomainEliment.AppendChild($unattendXml.CreateTextNode($JoinAccount.GetNetworkCredential().Domain)) $IdCredPasswordElement = $IdCredentialElement.AppendChild($unattendXml.CreateElement('Password', 'urn:schemas-microsoft-com:unattend')) $Null = $IdCredPasswordElement.AppendChild($unattendXml.CreateTextNode($JoinAccount.GetNetworkCredential().Password)) $IdCredUserNameElement = $IdCredentialElement.AppendChild($unattendXml.CreateElement('Username', 'urn:schemas-microsoft-com:unattend')) $Null = $IdCredUserNameElement.AppendChild($unattendXml.CreateTextNode($JoinAccount.GetNetworkCredential().UserName)) $IdJoinDomainElement = $identificationElement.AppendChild($unattendXml.CreateElement('JoinDomain', 'urn:schemas-microsoft-com:unattend')) $Null = $IdJoinDomainElement.AppendChild($unattendXml.CreateTextNode($domain)) $IdMachineOUElement = $identificationElement.AppendChild($unattendXml.CreateElement('MachineObjectOU', 'urn:schemas-microsoft-com:unattend')) $Null = $IdMachineOUElement.AppendChild($unattendXml.CreateTextNode($OU)) $IdUnsecureJoinElement = $identificationElement.AppendChild($unattendXml.CreateElement('UnsecureJoin', 'urn:schemas-microsoft-com:unattend')) $Null = $IdUnsecureJoinElement.AppendChild($unattendXml.CreateTextNode('False')) } else { Write-Warning 'Domain join requires -JoinAccount, -Domain, and -OU : one or more is missing, skipping section' } } } if ($setting.'Pass' -eq 'specialize' -and $component.'Name' -eq 'Microsoft-Windows-Deployment' ) { if (($null -ne $FirstBootExecuteCommand -or $FirstBootExecuteCommand.Length -gt 0) -and $component.'processorArchitecture' -eq 'x86') { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding first boot command(s)" $commandOrder = 1 $runSynchronousElement = $component.AppendChild($unattendXml.CreateElement('RunSynchronous', 'urn:schemas-microsoft-com:unattend')) foreach ($synchronousCommand in ($FirstBootExecuteCommand | Sort-Object -Property { $_.order })) { $syncCommandElement = $runSynchronousElement.AppendChild($unattendXml.CreateElement('RunSynchronousCommand', 'urn:schemas-microsoft-com:unattend')) $null = $syncCommandElement.SetAttribute('action', 'http://schemas.microsoft.com/WMIConfig/2002/State', 'add') $syncCommandDescriptionElement = $syncCommandElement.AppendChild($unattendXml.CreateElement('Description', 'urn:schemas-microsoft-com:unattend')) $Null = $syncCommandDescriptionElement.AppendChild($unattendXml.CreateTextNode($synchronousCommand['Description'])) $syncCommandOrderElement = $syncCommandElement.AppendChild($unattendXml.CreateElement('Order', 'urn:schemas-microsoft-com:unattend')) $Null = $syncCommandOrderElement.AppendChild($unattendXml.CreateTextNode($commandOrder)) $syncCommandPathElement = $syncCommandElement.AppendChild($unattendXml.CreateElement('Path', 'urn:schemas-microsoft-com:unattend')) $Null = $syncCommandPathElement.AppendChild($unattendXml.CreateTextNode($synchronousCommand['Path'])) $commandOrder++ } } } if (($setting.'Pass' -eq 'specialize') -and ($component.'Name' -eq 'Microsoft-Windows-Shell-Setup')) { if ($ComputerName) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding custom computername for $($component.'processorArchitecture') Architecture" $computerNameElement = $component.AppendChild($unattendXml.CreateElement('ComputerName', 'urn:schemas-microsoft-com:unattend')) $Null = $computerNameElement.AppendChild($unattendXml.CreateTextNode($ComputerName)) } if ($ProductKey) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Product key for $($component.'processorArchitecture') Architecture" $productKeyElement = $component.AppendChild($unattendXml.CreateElement('ProductKey', 'urn:schemas-microsoft-com:unattend')) $Null = $productKeyElement.AppendChild($unattendXml.CreateTextNode($ProductKey.ToUpper())) } } if (($setting.'Pass' -eq 'oobeSystem') -and ($component.'Name' -eq 'Microsoft-Windows-International-Core')) { if ($InputLocale) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Input Locale for $($component.'processorArchitecture') Architecture" $component.InputLocale = $InputLocale } if ($SystemLocale) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding System Locale for $($component.'processorArchitecture') Architecture" $component.SystemLocale = $SystemLocale } if ($UILanguage) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding UI Language for $($component.'processorArchitecture') Architecture" $component.UILanguage = $UILanguage } if ($UserLocale) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding User Locale for $($component.'processorArchitecture') Architecture" $component.UserLocale = $UserLocale } } if (($setting.'Pass' -eq 'oobeSystem') -and ($component.'Name' -eq 'Microsoft-Windows-Shell-Setup')) { if ($TimeZone) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Time Zone for $($component.'processorArchitecture') Architecture" $component.TimeZone = $TimeZone } Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Administrator Passwords for $($component.'processorArchitecture') Architecture" $concatenatedPassword = '{0}AdministratorPassword' -f $AdminCredential.GetNetworkCredential().password $component.UserAccounts.AdministratorPassword.Value = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($concatenatedPassword)) if ($RegisteredOrganization) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Registred Organization for $($component.'processorArchitecture') Architecture" $component.RegisteredOrganization = $RegisteredOrganization } if ($RegisteredOwner) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Registered Owner for $($component.'processorArchitecture') Architecture" $component.RegisteredOwner = $RegisteredOwner } if ($UserAccount) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding User Account(s) for $($component.'processorArchitecture') Architecture" $UserAccountsElement = $component.UserAccounts $LocalAccountsElement = $UserAccountsElement.AppendChild($unattendXml.CreateElement('LocalAccounts', 'urn:schemas-microsoft-com:unattend')) foreach ($Account in $UserAccount) { $LocalAccountElement = $LocalAccountsElement.AppendChild($unattendXml.CreateElement('LocalAccount', 'urn:schemas-microsoft-com:unattend')) $LocalAccountPasswordElement = $LocalAccountElement.AppendChild($unattendXml.CreateElement('Password', 'urn:schemas-microsoft-com:unattend')) $LocalAccountPasswordValueElement = $LocalAccountPasswordElement.AppendChild($unattendXml.CreateElement('Value', 'urn:schemas-microsoft-com:unattend')) $LocalAccountPasswordPlainTextElement = $LocalAccountPasswordElement.AppendChild($unattendXml.CreateElement('PlainText', 'urn:schemas-microsoft-com:unattend')) $LocalAccountDisplayNameElement = $LocalAccountElement.AppendChild($unattendXml.CreateElement('DisplayName', 'urn:schemas-microsoft-com:unattend')) $LocalAccountGroupElement = $LocalAccountElement.AppendChild($unattendXml.CreateElement('Group', 'urn:schemas-microsoft-com:unattend')) $LocalAccountNameElement = $LocalAccountElement.AppendChild($unattendXml.CreateElement('Name', 'urn:schemas-microsoft-com:unattend')) $null = $LocalAccountElement.SetAttribute('action', 'http://schemas.microsoft.com/WMIConfig/2002/State', 'add') $concatenatedPassword = '{0}Password' -f $Account.GetNetworkCredential().password $null = $LocalAccountPasswordValueElement.AppendChild($unattendXml.CreateTextNode([System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($concatenatedPassword)))) $null = $LocalAccountPasswordPlainTextElement.AppendChild($unattendXml.CreateTextNode('false')) $null = $LocalAccountDisplayNameElement.AppendChild($unattendXml.CreateTextNode($Account.UserName)) $null = $LocalAccountGroupElement.AppendChild($unattendXml.CreateTextNode('Administrators')) $null = $LocalAccountNameElement.AppendChild($unattendXml.CreateTextNode($Account.UserName)) } } if ($LogonCount) { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Autologon for $($component.'processorArchitecture') Architecture" $autoLogonElement = $component.AppendChild($unattendXml.CreateElement('AutoLogon', 'urn:schemas-microsoft-com:unattend')) $autoLogonPasswordElement = $autoLogonElement.AppendChild($unattendXml.CreateElement('Password', 'urn:schemas-microsoft-com:unattend')) $autoLogonPasswordValueElement = $autoLogonPasswordElement.AppendChild($unattendXml.CreateElement('Value', 'urn:schemas-microsoft-com:unattend')) $autoLogonCountElement = $autoLogonElement.AppendChild($unattendXml.CreateElement('LogonCount', 'urn:schemas-microsoft-com:unattend')) $autoLogonUsernameElement = $autoLogonElement.AppendChild($unattendXml.CreateElement('Username', 'urn:schemas-microsoft-com:unattend')) $autoLogonEnabledElement = $autoLogonElement.AppendChild($unattendXml.CreateElement('Enabled', 'urn:schemas-microsoft-com:unattend')) $null = $autoLogonPasswordValueElement.AppendChild($unattendXml.CreateTextNode($AdminCredential.GetNetworkCredential().password)) $null = $autoLogonCountElement.AppendChild($unattendXml.CreateTextNode($LogonCount)) $null = $autoLogonUsernameElement.AppendChild($unattendXml.CreateTextNode('administrator')) $null = $autoLogonEnabledElement.AppendChild($unattendXml.CreateTextNode('true')) } if (($Null -ne $FirstLogonExecuteCommand -or $FirstBootExecuteCommand.Length -gt 0) -and $component.'processorArchitecture' -eq 'x86') { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding First Logon Commands" $commandOrder = 1 $FirstLogonCommandsElement = $component.AppendChild($unattendXml.CreateElement('FirstLogonCommands', 'urn:schemas-microsoft-com:unattend')) foreach ($command in ($FirstLogonExecuteCommand | Sort-Object -Property { $_.order })) { $CommandElement = $FirstLogonCommandsElement.AppendChild($unattendXml.CreateElement('SynchronousCommand', 'urn:schemas-microsoft-com:unattend')) $CommandDescriptionElement = $CommandElement.AppendChild($unattendXml.CreateElement('Description', 'urn:schemas-microsoft-com:unattend')) $CommandOrderElement = $CommandElement.AppendChild($unattendXml.CreateElement('Order', 'urn:schemas-microsoft-com:unattend')) $CommandCommandLineElement = $CommandElement.AppendChild($unattendXml.CreateElement('CommandLine', 'urn:schemas-microsoft-com:unattend')) $CommandRequireInputlement = $CommandElement.AppendChild($unattendXml.CreateElement('RequiresUserInput', 'urn:schemas-microsoft-com:unattend')) $null = $CommandElement.SetAttribute('action', 'http://schemas.microsoft.com/WMIConfig/2002/State', 'add') $null = $CommandDescriptionElement.AppendChild($unattendXml.CreateTextNode($command['Description'])) $null = $CommandOrderElement.AppendChild($unattendXml.CreateTextNode($commandOrder)) $null = $CommandCommandLineElement.AppendChild($unattendXml.CreateTextNode($command['CommandLine'])) $null = $CommandRequireInputlement.AppendChild($unattendXml.CreateTextNode('false')) $commandOrder++ } } if (($null -ne $EveryLogonExecuteCommand -or $FirstBootExecuteCommand.Length -gt 0) -and $component.'processorArchitecture' -eq 'x86') { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Adding Every-Logon Commands" $commandOrder = 1 $FirstLogonCommandsElement = $component.AppendChild($unattendXml.CreateElement('LogonCommands', 'urn:schemas-microsoft-com:unattend')) foreach ($command in ($EveryLogonExecuteCommand | Sort-Object -Property { $_.order })) { $CommandElement = $FirstLogonCommandsElement.AppendChild($unattendXml.CreateElement('AsynchronousCommand', 'urn:schemas-microsoft-com:unattend')) $CommandDescriptionElement = $CommandElement.AppendChild($unattendXml.CreateElement('Description', 'urn:schemas-microsoft-com:unattend')) $CommandOrderElement = $CommandElement.AppendChild($unattendXml.CreateElement('Order', 'urn:schemas-microsoft-com:unattend')) $CommandCommandLineElement = $CommandElement.AppendChild($unattendXml.CreateElement('CommandLine', 'urn:schemas-microsoft-com:unattend')) $CommandRequireInputlement = $CommandElement.AppendChild($unattendXml.CreateElement('RequiresUserInput', 'urn:schemas-microsoft-com:unattend')) $null = $CommandElement.SetAttribute('action', 'http://schemas.microsoft.com/WMIConfig/2002/State', 'add') $null = $CommandDescriptionElement.AppendChild($unattendXml.CreateTextNode($command['Description'])) $null = $CommandOrderElement.AppendChild($unattendXml.CreateTextNode($commandOrder)) $null = $CommandCommandLineElement.AppendChild($unattendXml.CreateTextNode($command['CommandLine'])) $null = $CommandRequireInputlement.AppendChild($unattendXml.CreateTextNode('false')) $commandOrder++ } } } } #end foreach setting.Component } #end foreach unattendXml.Unattend.Settings Write-Verbose -Message "[$($MyInvocation.MyCommand)] Saving file" $unattendXml.Save($Path) Get-ChildItem $Path # } # catch # { # throw $_.Exception.Message # } } } } function Get-UnattendChunk { param ( [string] $pass, [string] $component, [string] $arch, [xml] $unattend ) # Helper function that returns one component chunk from the Unattend XML data structure return $unattend.unattend.settings | Where-Object -Property pass -EQ -Value $pass | Select-Object -ExpandProperty component | Where-Object -Property name -EQ -Value $component | Where-Object -Property processorArchitecture -EQ -Value $arch } |