├── FILES └── .gitignore ├── ISO └── .gitignore ├── VM └── .gitignore ├── .gitignore ├── Example-privatedata.json ├── scripts ├── sysprep-shutdown.ps1 ├── SetupComplete-qemu.ps1 ├── tools-winrm.ps1 ├── SetupComplete-vmw.ps1 ├── cloudbase-init.ps1 ├── bootstrap-win.ps1 ├── cleanup-compact.ps1 ├── configure-win.ps1 ├── configure-windows-local-policy.ps1 └── windows-update-winrm.ps1 ├── cloud_init ├── cloudbase-init.conf ├── cloudbase-init-unattend.conf └── cloudbase-init-firstboot.ps1 ├── LICENSE ├── README.md ├── answer_files ├── vmw │ └── 10 │ │ └── Autounattend.xml └── qemu │ └── 10 │ └── Autounattend.xml └── Win10.json /FILES/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | 4 | -------------------------------------------------------------------------------- /ISO/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | 4 | -------------------------------------------------------------------------------- /VM/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | privatedata.json 3 | -------------------------------------------------------------------------------- /Example-privatedata.json: -------------------------------------------------------------------------------- 1 | { 2 | "localuser_win_pass": "localuser-10" 3 | } -------------------------------------------------------------------------------- /scripts/sysprep-shutdown.ps1: -------------------------------------------------------------------------------- 1 | # Kick off sysprep 2 | start-process -FilePath 'C:/windows/System32/Sysprep/sysprep.exe' -ArgumentList '/oobe /generalize /shutdown "/unattend:C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\Unattend.xml"' 3 | exit 0 -------------------------------------------------------------------------------- /scripts/SetupComplete-qemu.ps1: -------------------------------------------------------------------------------- 1 | 2 | # start cloudbase-init service and set to auto-start 3 | start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "config cloudbase-init start= auto" -wait 4 | start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "start cloudbase-init" -wait 5 | 6 | exit 0 7 | -------------------------------------------------------------------------------- /scripts/tools-winrm.ps1: -------------------------------------------------------------------------------- 1 | # install vmware tools 2 | write-output "Starting VMare Tools install" 3 | 4 | ## Download vmware tools 5 | $client = new-object System.Net.WebClient 6 | $client.DownloadFile("https://packages.vmware.com/tools/releases/latest/windows/x64/VMware-tools-10.0.9-3917699-x86_64.exe", "C:\windows\temp\setup64.exe" ) 7 | 8 | #Write-host "Installing VMware Tools..." 9 | start-process -FilePath 'C:/Windows/Temp/setup64.exe' -ArgumentList '/S /v "/qn /l*v ""C:\windows\temp\vmwtoolsinstall.log"" ADDLOCAL=ALL REMOVE=Hgfs REBOOT=R"' -------------------------------------------------------------------------------- /scripts/SetupComplete-vmw.ps1: -------------------------------------------------------------------------------- 1 | # if you create custom ovfEnv properties in your template you can easily turn them into Environment variables for fun automation possibiliites. 2 | 3 | # read properties from vmware tools and store as xml 4 | & "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe" --cmd "info-get guestinfo.ovfEnv" 2>&1 | tee-object -variable vmtoolsxml | out-null 5 | [xml]$vmtoolsxml = $vmtoolsxml 6 | 7 | # turn all properties into ps Environment variables 8 | foreach( $property in $vmtoolsxml.Environment.PropertySection.SelectNodes("*")){ 9 | $ps_varname = ($property.key | %{$_ -replace "vm.",""} | %{$_ -replace "\.","_"} ) 10 | new-variable -name $ps_varname -value $property.value 11 | } 12 | 13 | 14 | 15 | exit 0 -------------------------------------------------------------------------------- /cloud_init/cloudbase-init.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe 3 | mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\ 4 | verbose=true 5 | debug=false 6 | logdir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\ 7 | logfile=cloudbase-init.log 8 | default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN 9 | logging_serial_port_settings=COM1,115200,N,8 10 | local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\ 11 | metadata_services=cloudbaseinit.metadata.services.httpservice.HttpService 12 | plugins=cloudbaseinit.plugins.common.localscripts.LocalScriptsPlugin,cloudbaseinit.plugins.common.userdata.UserDataPlugin 13 | allow_reboot=true 14 | stop_service_on_exit=false 15 | check_latest_version=false -------------------------------------------------------------------------------- /cloud_init/cloudbase-init-unattend.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | username=Administrator 3 | inject_user_password=true 4 | first_logon_behaviour=no 5 | bsdtar_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\bsdtar.exe 6 | mtools_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\bin\ 7 | verbose=true 8 | debug=false 9 | logdir=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\log\ 10 | logfile=cloudbase-init-unattend.log 11 | default_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN 12 | logging_serial_port_settings=COM1,115200,N,8 13 | local_scripts_path=C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\ 14 | metadata_services=cloudbaseinit.metadata.services.httpservice.HttpService 15 | plugins=cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin 16 | allow_reboot=true 17 | stop_service_on_exit=false 18 | check_latest_version=false -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Blake Garner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/cloudbase-init.ps1: -------------------------------------------------------------------------------- 1 | #download installer 2 | $client = new-object System.Net.WebClient 3 | $client.DownloadFile("https://cloudbase.it/downloads/CloudbaseInitSetup_Stable_x64.msi", "C:\windows\temp\CloudbaseInitSetup_Stable_x64.msi" ) 4 | 5 | # install the payload 6 | start-process -FilePath 'c:\Windows\temp\CloudbaseInitSetup_Stable_x64.msi' -ArgumentList '/qn /l*v C:\windows\temp\cloud-init.log LOGGINGSERIALPORTNAME=COM1 USERNAME=admin' -passthru | wait-process 7 | 8 | # verify that cloudbase-init tools exists 9 | if (-not(test-path -path "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts")){ 10 | Write-output "cloudbase-init not installed exiting..." 11 | exit 1 12 | } 13 | 14 | move-item C:\Windows\Temp\cloudbase-init-unattend.conf "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init-unattend.conf" -force 15 | move-item C:\Windows\Temp\cloudbase-init.conf "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\conf\cloudbase-init.conf" -force 16 | move-item C:\Windows\Temp\cloudbase-init-firstboot.ps1 "C:\Program Files\Cloudbase Solutions\Cloudbase-Init\LocalScripts\cloudbase-init-firstboot.ps1" -force 17 | start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "config cloudbase-init start= demand" -wait 18 | -------------------------------------------------------------------------------- /scripts/bootstrap-win.ps1: -------------------------------------------------------------------------------- 1 | # windows powershell bootstrap script 2 | $host.ui.RawUI.WindowTitle = "Bootstrapping Windows" 3 | 4 | ## Identify the version of windows 5 | 6 | # test to see if this is a desktop version of windows 7 | $windesktop = (gwmi win32_operatingsystem).OperatingSystemSKU -notmatch "(\b[7-9]|10|1[2-5]|1[7-9]|2[0-5])" 8 | if ($windesktop) 9 | { 10 | write-output "This is a desktop version of windows" 11 | } 12 | 13 | # get the windows kernel version 14 | $KERNELVERSION = [Environment]::OSVersion.Version 15 | 16 | # example test for reference. 17 | # 6.1 = Windows 7 & 2008 R2 18 | # 6.2 = Windows 8 & Server 2012 19 | # 6.3 = Windows 8.1 & Server 2012 R2 20 | # 10.0 = Windows 10 & Server 2016 21 | #if ($KERNELVERSION -ge (new-object 'Version' 10,0)) { 22 | # write-output "Windows 10 kernel version" 23 | #} 24 | 25 | # supress network location Prompt 26 | New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff" -Force 27 | 28 | # set network to private 29 | $ifaceinfo = Get-NetConnectionProfile 30 | Set-NetConnectionProfile -InterfaceIndex $ifaceinfo.InterfaceIndex -NetworkCategory Private 31 | #need to test below 32 | #Get-NetAdapter | Set-NetConnectionProfile -NetworkCategory Private 33 | 34 | # Make administrator user active for desktop OS 35 | net user administrator /active:yes 36 | 37 | # disable windows defender If you install your own AV later 38 | #if ($KERNELVERSION -ge (new-object 'Version' 10,0)) { 39 | # Set-MpPreference -DisableRealtimeMonitoring $true -DisableArchiveScanning $true -DisableIOAVProtection $true 40 | #} 41 | 42 | # enable winrm on http 43 | set-wsmanquickconfig -force 44 | 45 | # config winrm settings to work with packer 46 | winrm set winrm/config '@{MaxTimeoutms="1800000"}' 47 | winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="2048"}' 48 | winrm set winrm/config/service '@{AllowUnencrypted="true"}' 49 | winrm set winrm/config/service/auth '@{Basic="true"}' 50 | winrm set winrm/config/client/auth '@{Basic="true"}' 51 | winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port="5985"}' 52 | winrm set winrm/config/winrs '@{MaxConcurrentUsers="200"}' 53 | winrm set winrm/config/winrs '@{MaxShellsPerUser="200"}' 54 | 55 | # configure powersaving and screen saver 56 | powercfg -setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c 57 | powercfg -change -monitor-timeout-ac 0 58 | powercfg -hibernate OFF 59 | 60 | New-Itemproperty -Path "registry::HKCU\Control Panel\Desktop" -Name ScreenSaveActive -Value 0 -PropertyType "DWord" -Force 61 | New-Itemproperty -Path "registry::HKCU\Control Panel\Desktop" -Name ScreenSaveTimeOut -Value 0 -PropertyType "DWord" -Force 62 | New-Itemproperty -Path "registry::HKU\.DEFAULT\Control Panel\Desktop" -Name ScreenSaveActive -Value 0 -PropertyType "DWord" -Force 63 | New-Itemproperty -Path "registry::HKU\.DEFAULT\Control Panel\Desktop" -Name ScreenSaveTimeOut -Value 0 -PropertyType "DWord" -Force 64 | 65 | #Stop windows updtes from starting immediatly 66 | $WUSettings = (New-Object -com "Microsoft.Update.AutoUpdate").Settings 67 | $WUSettings.NotificationLevel=1 68 | $WUSettings.save() 69 | -------------------------------------------------------------------------------- /scripts/cleanup-compact.ps1: -------------------------------------------------------------------------------- 1 | #Powershell version of install cleanup_compact 2 | 3 | # get the windows kernel version 4 | $KERNELVERSION = [Environment]::OSVersion.Version 5 | 6 | get-packageprovider -name chocolatey -ForceBootstrap 7 | install-package sdelete -force 8 | #install-package ultradefrag -force 9 | 10 | # unzip function 11 | function punzip( $zipfile, $outdir ) { 12 | If(-not(Test-Path -path $zipfile)){return "zipfile " + $zipfile + " not found!"} 13 | If(-not(Test-Path -path $outdir)){return "output dir " + $outdir + " not found!"} 14 | $shell = new-object -com shell.application 15 | $zip = $shell.NameSpace($zipfile) 16 | foreach($item in $zip.items()) 17 | { 18 | $shell.Namespace($outdir).copyhere($item) 19 | } 20 | } 21 | 22 | ## Download the FILES 23 | $client = new-object System.Net.WebClient 24 | $client.DownloadFile("http://downloads.sourceforge.net/project/ultradefrag/stable-release/7.0.1/ultradefrag-portable-7.0.1.bin.amd64.zip", "C:\windows\temp\ultradefrag-portable-7.0.1.bin.amd64.zip" ) 25 | 26 | # Stops the windows update service. 27 | Stop-Service -Name wuauserv -Force -EA 0 28 | Get-Service -Name wuauserv 29 | 30 | # Delete the contents of windows software distribution. 31 | write-output "Delete the contents of windows software distribution" 32 | Get-ChildItem "C:\Windows\SoftwareDistribution\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | remove-item -force -recurse -ErrorAction SilentlyContinue 33 | 34 | # Delete the contents of localuser apps. 35 | write-output "Delete the contents of localuser apps" 36 | Get-ChildItem "C:\users\localuser\AppData\Local\Packages\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | remove-item -force -recurse -ErrorAction SilentlyContinue 37 | 38 | # Delete the contents of user template desktop. 39 | write-output "Delete the contents of user template desktop" 40 | Get-ChildItem "C:\Users\Public\Desktop\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | remove-item -force -recurse -ErrorAction SilentlyContinue 41 | 42 | # Starts the Windows Update Service 43 | Start-Service -Name wuauserv -EA 0 44 | 45 | # use dism to cleanup windows sxs. This only works on 2012r2 and 8.1 and above. 46 | # bumped up to windows 10 only as was failing on 2012r2 47 | if ([Environment]::OSVersion.Version -ge [Version]"10.0") { 48 | write-output "Cleaning up winSXS with dism" 49 | dism /online /cleanup-image /startcomponentcleanup /resetbase /quiet 50 | } 51 | 52 | # extract ultradefrag archive 53 | write-output "extracting ultradefrag archive" 54 | punzip ("C:\windows\temp\ultradefrag-portable-7.0.1.bin.amd64.zip") ("C:\Windows\temp") 55 | 56 | # Defragment the virtual disk blocks 57 | write-output "Starting to Defragment Disk" 58 | start-process -FilePath 'C:\Windows\Temp\ultradefrag-portable-7.0.1.amd64\udefrag.exe' -ArgumentList '--optimize --repeat C:' -wait -verb RunAs 59 | 60 | # Zero dirty blocks 61 | write-output "Starting to Zero blocks" 62 | #New-Item -Path "HKCU:\Software\Sysinternals\SDelete" -force -ErrorAction SilentlyContinue 63 | #Set-ItemProperty -Path "HKCU:\Software\Sysinternals\SDelete" -Name EulaAccepted -Value "1" -Type DWORD -force 64 | start-process -FilePath 'C:\Chocolatey\bin\sdelete64.bat' -ArgumentList '-q -z C:' -wait -EA 0 65 | uninstall-package sdelete -force 66 | 67 | exit 0 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # packer-win-pc 2 | ***packer.io templates & scripts for building private cloud optimized Windows OS images.*** 3 | If your unclear what packer templates are about check http://packer.io 4 | 5 | This template is used to create both VMware ESXi and OpenStack/KVM templates of Windows 10. It utilzes Windows RM and PowerShell scripts to build the latest OS with the modern tools. These images use virtio/pvscsi intefaces for the boot disk for optimized IO. 6 | 7 | ***Google Groups thread*** 8 | If you want to discuss this project please use this thread. 9 | https://groups.google.com/forum/#!topic/packer-tool/6evwAHomcaA 10 | 11 | **Prerequsits** 12 | 13 | You will need to have http://packer.io installed and the appropriate hypervisor. QEMU/KVM and VMware Workstation/Fusion/Player are ones you should have avialable. Linux systems that can have Workstation and QEMU/KVM are ideal as you can build both images at the same time given enough system resrouces. 14 | 15 | Extract the pvscsi and vmxnet3 drivers from VMware tools installer and popluate the FILES directory. 16 | https://kb.vmware.com/kb/2032184 17 | 18 | Aquire a set of virtio windows drivers. Ideally install the virtio-win package on redhat and extract those as they are signed drivers. 19 | 20 | Populate the FILES with the drivers as shown below. These get written to a flopy image before the sysetem is booted. Downloading them after boot is not realistic. 21 |
22 | FILES 23 | ├── pvscsi 24 | │ ├── pvscsi.cat 25 | │ ├── pvscsi.inf 26 | │ ├── pvscsi.sys 27 | │ ├── pvscsiver.dll 28 | │ └── txtsetup.oem 29 | ├── virtio-win 30 | │ └── Win8.1 31 | │ ├── netkvm.cat 32 | │ ├── netkvm.inf 33 | │ ├── netkvm.sys 34 | │ ├── vioscsi.cat 35 | │ ├── vioscsi.inf 36 | │ ├── vioscsi.sys 37 | │ ├── viostor.cat 38 | │ ├── viostor.inf 39 | │ └── viostor.sys 40 | └── vmxnet3 41 | ├── vmxnet3n61x64.sys 42 | ├── vmxnet3n61x86.sys 43 | ├── vmxnet3ndis6.cat 44 | ├── vmxnet3ndis6.inf 45 | └── vmxnet3ndis6ver.dll 46 |47 | 48 | Grab your installer .iso files and put them in the ISO directory. 49 |
50 | ISO 51 | ├── RELEASE_CLIENTENTERPRISE_OEM_X64FRE_EN-US.ISO 52 | └── RELEASE_SERVER_OEM_X64FRE_EN-US.ISO 53 |54 | 55 | ***Required changes to the template file*** 56 | ISO filename 57 | You must edit the Win10.json file to inclued the correct path to your Windows 10 .iso file in both builders. Additionally update the sha256 checksum that matches your .iso. 58 | 59 | ***Private data*** 60 | In this example the only private data is the password used for local administrator and "localuser" user account. Copy the Example-privatedate.json to privatedata.json in the root of the directory. Add your own password here and the file will be ignored by git. Follow this practice for any other data you do not want in your repo. 61 | 62 | ***Building the images*** 63 | After configuring your build system with the required bits and prerequsits use the following commands to build the images. From the root of the git repo run the follwing commands. 64 | 65 | Quick validation of file paths... 66 |
packer validate -var-file privatedata.json Win10.json
67 |
68 | Build both OpenStack and VMware images at the same time
69 | packer build -force -var-file privatedata.json Win10.json
70 |
71 | Build the VMware image only
72 | packer build -force -var-file privatedata.json -only vmware-iso Win10.json
73 |
74 | Build the OpenStack image only
75 | packer build -force -var-file privatedata.json -only qemu Win10.json
76 |
77 |
78 | ***References***
79 | https://github.com/joefitzgerald/packer-windows
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/scripts/configure-win.ps1:
--------------------------------------------------------------------------------
1 | # windows server cleanup
2 |
3 | # test to see if this is a desktop version of windows
4 | $windesktop = (gwmi win32_operatingsystem).OperatingSystemSKU -notmatch "(\b[7-9]|10|1[2-5]|1[7-9]|2[0-5])"
5 | if ($windesktop)
6 | {
7 | write-output "This is a desktop version of windows"
8 | }
9 |
10 | write-output "Disable Hybernation"
11 | powercfg -hibernate OFF
12 |
13 | write-output "configure screen saver"
14 | Set-ItemProperty -Path "registry::HKEY_USERS\.DEFAULT\Control Panel\Desktop" -Name ScreenSaveActive -Value 0
15 |
16 | write-output "change administrator user pass next login"
17 | # this gets reset by sysprep/guest customization. need to set it again in the guest customization script.
18 | net user localuser /logonpasswordchg:no
19 |
20 | write-output "Enable administrator account"
21 | net user administrator /active:yes
22 |
23 | write-output "Disable firewall"
24 | netsh advfirewall set allprofiles state off
25 |
26 | write-output "supress network location Prompt"
27 | New-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff" -Force
28 |
29 | # remove troublesome 3rd party app store apps that cause sysprep to fail
30 | if ($windesktop)
31 | {
32 | if ([Environment]::OSVersion.Version -ge (new-object 'Version' 10,0))
33 | {
34 | Get-AppxPackage -user localuser PackageFullName | Remove-AppxPackage -ErrorAction SilentlyContinue
35 | }
36 | }
37 |
38 | ## Optimize IPv6 settings
39 | write-output "disable privacy IPv6 addresses"
40 | netsh interface ipv6 set privacy state=disabled store=active
41 | netsh interface ipv6 set privacy state=disabled store=persistent
42 |
43 | write-output "enable EUI-64 addressing"
44 | netsh interface ipv6 set global randomizeidentifiers=disabled store=active
45 | netsh interface ipv6 set global randomizeidentifiers=disabled store=persistent
46 |
47 | write-output "Enable Remote Desktop"
48 | (Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices).SetAllowTsConnections(1,1) | Out-Null
49 | (Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0) | Out-Null
50 |
51 | write-output "Clear windows autologon"
52 | Remove-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultDomainName -EA 0
53 | Remove-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -EA 0
54 | Remove-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -EA 0
55 | Remove-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserPassword -EA 0
56 |
57 | # not the most secure option here..
58 | write-output "Enable remote command policy"
59 | Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name LocalAccountTokenFilterPolicy -Value 1 -Type DWord
60 |
61 | # sysprep with wmf 5 fix
62 | Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\StreamProvider -Name LastFullPayloadTime -Value 0 -Type DWord
63 |
64 | # set ntp to sync time before domain join
65 | Write-Output "Setting System Time Zone to UTC `r"
66 | tzutil.exe /s "UTC"
67 |
68 | write-output "setup guest customization shim"
69 | if(!(Test-Path -Path "C:\Windows\Setup\Scripts" )){
70 | New-Item -ItemType directory -Path "C:\Windows\Setup\Scripts"
71 | }
72 | Set-Content -path C:\windows\setup\scripts\SetupComplete.cmd -value 'powershell -executionpolicy bypass -file C:\windows\setup\scripts\SetupComplete.ps1'
73 | move-item c:\windows\temp\SetupComplete.ps1 c:\windows\setup\scripts\
74 |
75 |
--------------------------------------------------------------------------------
/cloud_init/cloudbase-init-firstboot.ps1:
--------------------------------------------------------------------------------
1 | #ps1_sysnative
2 | # powershell guest customizatin payload script for vcloud and vsphere
3 |
4 | write-output "itc customization started"
5 |
6 | # setup logging
7 | Start-Transcript -path c:\windows\temp\cloudbase-init-firstboot.log -Append -force
8 |
9 |
10 | ## Identify the version of windows
11 |
12 | # test to see if this is a desktop version of windows
13 | $windesktop = (gwmi win32_operatingsystem).OperatingSystemSKU -notmatch "(\b[7-9]|10|1[2-5]|1[7-9]|2[0-5])"
14 | if ($windesktop)
15 | {
16 | write-output "This is a desktop version of windows"
17 | }
18 |
19 | # get the windows kernel version
20 | $KERNELVERSION = [Environment]::OSVersion.Version
21 |
22 | # example test for reference.
23 | # 6.1 = Windows 7 & 2008 R2
24 | # 6.2 = Windows 8 & Server 2012
25 | # 6.3 = Windows 8.1 & Server 2012 R2
26 | # 10.0 = Windows 10 & Server 2016
27 | if ($KERNELVERSION -ge (new-object 'Version' 10,0)) {
28 | write-output "Windows 10 kernel version"
29 | }
30 |
31 | ## Set windows computer/hostname from the primary IP reverse DNS record
32 | # get default gateway IP
33 | $gateway=(gwmi Win32_networkAdapterConfiguration | ?{$_.IPEnabled}).DefaultIPGateway
34 |
35 | # trim to the first two octets of default route
36 | $gatewaynet = $gateway.split('.')
37 | $gatewaynet = $gatewaynet[0,1]
38 | $gatewaynet = $gatewaynet -join '.'
39 |
40 | # get list of IPv4 addresses
41 | $localipaddr=(gwmi Win32_NetworkAdapterConfiguration | ? { $_.IPAddress -ne $null }).ipaddress
42 |
43 | # match IPv4 address to default gateway and make sure it's only one IP
44 | $primaryip = $localipaddr -like "$gatewaynet*" | Select-Object -first 1
45 |
46 | # lookup reverse dns record for that IP
47 | $reversefqdn=(nslookup "$primaryip") -match "Name" | select-object -last 1
48 | $reversefqdn = ($reversefqdn).split(" ") | select-object -last 1
49 |
50 | # get the shortname
51 | $new_hostname = $reversefqdn.split('.')
52 | $new_hostname = $new_hostname[0]
53 |
54 | # use primary IP reverse DNS name to rename the host
55 | write-output "Changing Windows hostname to $new_hostname"
56 | $ComputerInfo = Get-WmiObject -Class Win32_ComputerSystem
57 | $ComputerInfo.Rename($new_hostname)
58 |
59 | # set dns search suffix
60 | Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "NV Domain" -value "example.com" -type string -Force
61 | Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "SyncDomainWithMembership" -value "0" -type dword -Force
62 |
63 | # Set time zone and sync clock with ntp
64 | Write-Output "Setting System Time Zone to UTC `r"
65 | tzutil.exe /s "UTC"
66 |
67 | # configure NTP for local site
68 | Write-Output "Setting System Time via NTP `r"
69 | $DNS_SERVER = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'").DNSServerSearchOrder | Select-Object -first 1
70 | Set-Service -Name "w32time" -StartupType Automatic -Status stopped
71 | w32tm /config /manualpeerlist:$DNS_SERVER /syncfromflags:MANUAL
72 | start-Service "w32time"
73 | w32tm /resync
74 |
75 | # Disable firewall
76 | Write-Output "Configuring firewall... `r"
77 | netsh advfirewall set allprofiles state off
78 |
79 | # Set activation server
80 | Write-Output "Setting KMS for CORP `r"
81 | cscript C:\Windows\System32\slmgr.vbs /skms kms.example.com
82 |
83 | # Clear windows autologon
84 | Remove-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultDomainName -ea Silentlycontinue
85 | Remove-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -ea Silentlycontinue
86 | Remove-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -ea Silentlycontinue
87 |
88 | # Make administrator user active for desktop OS
89 | net user administrator /active:yes
90 |
91 | # disable password never expires on administrator account
92 | Get-WmiObject -Class Win32_UserAccount -Filter "name = 'administrator'" | Set-WmiInstance -Argument @{PasswordExpires = 1}
93 |
94 | # set localuser user to not have expiring password. Sysprep resets this after customization
95 | Write-Output "Setting localuser user to no-expire password `r"
96 | net user localuser /expires:never /active:yes /logonpasswordchg:no
97 |
98 | # extend disk
99 | $extendvolume=@(
100 | 'select volume 1',
101 | 'extend',
102 | 'exit'
103 | )
104 | $extendvolume | diskpart
105 |
106 | # stop logging
107 | stop-transcript
108 |
109 | # exit with return code 1001
110 | exit 1001
111 |
--------------------------------------------------------------------------------
/scripts/configure-windows-local-policy.ps1:
--------------------------------------------------------------------------------
1 | $ProgressPreference="SilentlyContinue"
2 |
3 | # test to see if this is a desktop version of windows
4 | $windesktop = (gwmi win32_operatingsystem).OperatingSystemSKU -notmatch "(\b[7-9]|10|1[2-5]|1[7-9]|2[0-5])"
5 | if ($windesktop)
6 | {
7 | write-output "This is a desktop version of windows"
8 | }
9 |
10 | # get the windows kernel version
11 | $KERNELVERSION = [Environment]::OSVersion.Version
12 |
13 | # example test for reference.
14 | # 6.1 = Windows 7 & 2008 R2
15 | # 6.2 = Windows 8 & Server 2012
16 | # 6.3 = Windows 8.1 & Server 2012 R2
17 | # 10.0 = Windows 10 & Server 2016
18 | #if ($KERNELVERSION -ge (new-object 'Version' 10,0)) {
19 | # write-output "Windows 10 kernel version"
20 | #}
21 |
22 | # install PolicyFileEditor
23 | Install-Module -Name PolicyFileEditor -Confirm:$false
24 |
25 | # disable windows defender
26 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows Defender" -ValueName DisableAntiSpyware -Data 1 -Type DWord
27 |
28 | # reg unload
29 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows\System" -ValueName DisableForceUnload -Data 1 -Type DWord
30 |
31 | # ProcessCreationIncludeCmdLine_Enabled
32 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit" -ValueName ProcessCreationIncludeCmdLine_Enabled -Data 1 -Type DWord
33 |
34 | # set RDP Min encryption level
35 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows NT\Terminal Services" -ValueName MinEncryptionLevel -Data 3 -Type DWord
36 |
37 | # set RPC encryption
38 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows NT\Terminal Services" -ValueName fEncryptRPCTraffic -Data 1 -Type DWord
39 |
40 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows NT\Terminal Services" -ValueName fPromptForPassword -Data 1 -Type DWord
41 |
42 | # limit log size
43 | limit-eventlog -logname Security -MaximumSize 1048576kb
44 |
45 | # Windows 81 & 2012r2 or newer
46 | if ($KERNELVERSION -ge (new-object 'Version' 6,3)) {
47 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging" -ValueName EnableModuleLogging -Data 1 -Type DWord
48 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" -ValueName **delvals. -Data 1 -Type String
49 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames" -ValueName Microsoft.Powershell.* -Data Microsoft.Powershell.* -Type String
50 | }
51 |
52 | # Windows 10 specific policy
53 | if ($KERNELVERSION -ge (new-object 'Version' 10,0)) {
54 | write-output "Setting Windows Kernel Version 10 Policy"
55 | # disable web results search bar
56 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "Software\Policies\Microsoft\Windows\Windows Search" -ValueName ConnectedSearchUseWeb -Data 0 -Type DWord
57 | # disable Cortana
58 | Set-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -Key "SOFTWARE\Policies\Microsoft\Windows\Windows Search" -ValueName AllowCortana -Data 0 -Type DWord
59 | }
60 |
61 | # show results
62 | write-output "Listing configured local windows policies"
63 | Get-PolicyFileEntry -Path $env:systemroot\system32\GroupPolicy\Machine\registry.pol -All
64 |
65 |
66 | write-output "Configure local security policy"
67 | secedit /export /cfg c:\windows\temp\secpol.cfg
68 | (get-content c:\windows\temp\secpol.cfg).replace('PasswordComplexity = 0', 'PasswordComplexity = 1') | Out-File c:\windows\temp\secpol.cfg
69 | (get-content c:\windows\temp\secpol.cfg).replace('MaximumPasswordAge = 42', 'MaximumPasswordAge = 90') | Out-File c:\windows\temp\secpol.cfg
70 | (get-content c:\windows\temp\secpol.cfg).replace('MaximumPasswordAge = 0', 'MaximumPasswordAge = 90') | Out-File c:\windows\temp\secpol.cfg
71 | (get-content c:\windows\temp\secpol.cfg).replace('PasswordHistorySize = 0', 'PasswordHistorySize = 10') | Out-File c:\windows\temp\secpol.cfg
72 | (get-content c:\windows\temp\secpol.cfg).replace('DontDisplayLastUserName=4,0', 'DontDisplayLastUserName=4,1') | Out-File c:\windows\temp\secpol.cfg
73 | (get-content c:\windows\temp\secpol.cfg).replace('CachedLogonsCount=1,"10"', 'CachedLogonsCount=1,"4"') | Out-File c:\windows\temp\secpol.cfg
74 | (get-content c:\windows\temp\secpol.cfg).replace('RestrictAnonymous=4,0', 'RestrictAnonymous=4,1') | Out-File c:\windows\temp\secpol.cfg
75 | (get-content c:\windows\temp\secpol.cfg).replace('FilterAdministratorToken=4,0', 'FilterAdministratorToken=4,1') | Out-File c:\windows\temp\secpol.cfg
76 | (get-content c:\windows\temp\secpol.cfg).replace('LockoutBadCount = 0', "LockoutBadCount = 5`nResetLockoutCount = 15`nLockoutDuration = 15`n") | Out-File c:\windows\temp\secpol.cfg
77 | (get-content c:\windows\temp\secpol.cfg).replace('MinimumPasswordLength = 8', 'MinimumPasswordLength = 12') | Out-File c:\windows\temp\secpol.cfg
78 | (get-content c:\windows\temp\secpol.cfg).replace('MinimumPasswordLength = 0', 'MinimumPasswordLength = 12') | Out-File c:\windows\temp\secpol.cfg
79 | (get-content c:\windows\temp\secpol.cfg).replace('FilterAdministratorToken=4,0', 'FilterAdministratorToken=4,1') | Out-File c:\windows\temp\secpol.cfg
80 | get-content c:\windows\temp\secpol.cfg
81 | secedit /configure /db c:\windows\security\local.sdb /cfg c:\windows\temp\secpol.cfg /areas SECURITYPOLICY
82 |
83 | #audit policy
84 | write-output "Configure local audit policy"
85 | auditpol /set /subcategory:"Credential Validation" /failure:enable /success:enable
86 | auditpol /set /subcategory:"Application Group Management" /failure:enable /success:enable
87 | auditpol /set /subcategory:"Computer Account Management" /failure:enable /success:enable
88 | auditpol /set /subcategory:"Distribution Group Management" /failure:enable /success:enable
89 | auditpol /set /subcategory:"Other Account Management Events" /failure:enable /success:enable
90 | auditpol /set /subcategory:"Security Group Management" /failure:enable /success:enable
91 | auditpol /set /subcategory:"User Account Management" /failure:enable /success:enable
92 | auditpol /set /subcategory:"Process Creation" /success:enable
93 | auditpol /set /subcategory:"Account Lockout" /failure:enable /success:enable
94 | auditpol /set /subcategory:"File Share" /failure:enable
95 | auditpol /set /subcategory:"Registry" /failure:enable
96 | auditpol /set /subcategory:"Removable Storage" /failure:enable /success:enable
97 | auditpol /set /subcategory:"SAM" /failure:enable /success:enable
98 | auditpol /set /subcategory:"Audit Policy Change" /failure:enable /success:enable
99 | auditpol /set /subcategory:"Authentication Policy Change" /failure:enable /success:enable
100 | auditpol /set /subcategory:"Sensitive Privilege Use" /success:enable
101 | auditpol /set /subcategory:"Security State Change" /failure:enable /success:enable
102 | auditpol /set /subcategory:"Security System Extension" /failure:enable /success:enable
103 | auditpol /set /subcategory:"Process Termination" /failure:enable /success:enable
104 |
105 | # report audit policy
106 | auditpol.exe /get /category:*
107 |
--------------------------------------------------------------------------------
/scripts/windows-update-winrm.ps1:
--------------------------------------------------------------------------------
1 | # Powershell version of install windows update via task scheduler
2 | # This script creates a logon task to run windows updates.
3 | # Depends on packer windows-restart to start the taks and stop winrm.
4 | # After all updaets are instaled winrm is started and the login task is removed.
5 |
6 | # setup window name and script name variable
7 | $scriptname="windows-update-winrm.ps1"
8 | $host.ui.RawUI.WindowTitle = "$scriptname"
9 |
10 | # start logging
11 | start-transcript -path c:\windows\temp\windows-update-winrm.log -append
12 |
13 | # Report the IE version Installed
14 | Write-output ("Installed IE Version currently is " + (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Internet Explorer').Version)
15 |
16 | # Report the powershell version installed
17 | $powershellversion=$PSVersionTable.PSVersion
18 | write-output "Powershell version $powershellversion installed"
19 | if ($PSVersionTable.PSVersion.Major -lt 5) {
20 | write-output "Powershell upgrade in previous step failed!!"
21 | get-content "C:\Windows\wsusofflineupdate.log"
22 | exit 1
23 | }
24 |
25 | # Report the version of windows update agent
26 | $wu_agent=(get-command C:\windows\system32\wups2.dll).version
27 | if ($wu_agent -ge [Version]"7.6.7601.19161") {
28 | write-output "Windows Update agent is current! $wu_agent"
29 | } else {
30 | write-output "Windows Update agent out of date! $wu_agent"
31 | }
32 |
33 | # Check to see if scheduled task called $scriptname exists
34 | if (schtasks /query /tn $scriptname 2>$null ) {
35 | write-output "Checking for updates...."
36 | Get-WUInstallerStatus
37 | # hack to get buggy windows 7 to show updates
38 | #if ([Environment]::OSVersion.Version -le [Version]"6.1.7601.65536") {
39 | #if ((gwmi win32_operatingsystem).OperatingSystemSKU -notmatch "(\b[7-9]|10|1[2-5]|1[7-9]|2[0-5])") {
40 | if ([Version](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Internet Explorer').Version -le [Version]"9.11.9600.18231") {
41 | write-output "Forcing Windows to search for updates until it finds some...."
42 | while (-not(Get-WindowsUpdate -notCategory "Windows 7 Language Packs")) {
43 | write-output "Still looking for updates...."
44 | }
45 | Write-output "Win Found some updates"
46 | }
47 | #}
48 | #}
49 | # Actually install the updates starts here..
50 | if (Get-WindowsUpdate -notCategory "Windows 7 Language Packs" -NotTitle "Printer")
51 | {
52 | write-output "Starting Windows update installation..."
53 | # run windows updates
54 | Install-WindowsUpdate -IgnoreUserInput -AcceptALL -IgnoreReboot -verbose -notCategory "Windows 7 Language Packs"
55 | # restart after every insstall of updates
56 | stop-transcript
57 | restart-computer
58 | } else {
59 | write-output "No updates found..."
60 | # maybe check for systems that still show zero installed updates and reboot
61 | #if (Get-WUList -IsInstalled) {write-output "updates have been installed"}
62 | #remove scheduled task
63 | schtasks /delete /tn $scriptname /f
64 | # stop logging & dump to console so it gets recorded in packer log
65 | #get-content c:\windows\temp\windows-update-winrm.log
66 | # start winrm service and set to autostart
67 | start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "config WinRM start= delayed-auto" -wait
68 | #start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "start WinRM" -wait
69 | stop-transcript
70 | restart-computer
71 | }
72 | } else {
73 | # first run of script
74 | # setup windows updater components
75 | $ErrorActionPreference = 'Stop'
76 | # install nuget
77 | write-output "Installing NuGet"
78 |
79 | [int]$attempts = 0
80 | do {
81 | try {
82 | $attempts +=1
83 | Get-PackageProvider -Name NuGet -ForceBootstrap
84 | if (-not([string](Get-PackageProvider).name -match "NuGet")) { throw "Error installing NuGet" }
85 | break
86 | } catch {
87 | write-host "Problem installing NuGet `tAttempt $attempts `
88 | `n`tException: " $_.Exception.Message
89 | start-sleep -s 20
90 | }
91 | }
92 | while ($attempts -lt 10)
93 | if ($attempts -ge 10) {
94 | write-host "NuGet failed to install!!"
95 | exit 1
96 | }
97 |
98 | # allow repo install
99 | write-output "adding PSGallery repo"
100 | Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
101 |
102 | # install PSWindowsUpdate
103 | write-output "Installing PSWindowsUpdate"
104 | Install-Module -Name PSWindowsUpdate -Confirm:$false | out-null
105 | write-output "Installed PSWindowsUpdate"
106 |
107 | # attempt install early for debugging
108 | #Get-WUInstallerStatus
109 |
110 | #Get-WindowsUpdate -notCategory "Windows 7 Language Packs"
111 | write-output "Modern windows update tools installed..."
112 |
113 | ##### Debugging BS for windows 7 below..
114 | #start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "config bits start= auto" -wait
115 | #start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "config wuauserv start= auto" -wait
116 | #start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "config appidsvc start= auto" -wait
117 | #start-process -nonewwindow -FilePath "C:/Windows/system32/sc.exe" -ArgumentList "config cryptsvc start= auto" -wait
118 |
119 | #if ([Environment]::OSVersion.Version -le [Version]"6.2") {
120 | # Write-output "Installing KB KB2966583"
121 | # Install-WindowsUpdate -KBArticleID KB2966583 -acceptall
122 | #}
123 |
124 | # Stops the windows update service.
125 | # Get-Service -Name wuauserv | Stop-Service -Force -Verbose -ErrorAction SilentlyContinue
126 |
127 | # Delete the contents of windows software distribution.
128 | #write-output "Delete the contents of windows software distribution"
129 | #Get-ChildItem "C:\Windows\SoftwareDistribution\*" -Recurse -Force -Verbose -ErrorAction SilentlyContinue | remove-item -force -recurse -ErrorAction SilentlyContinue
130 |
131 | # setup windows update server from envrionment variables
132 | #write-output "Windows Update Group $env:wsus_group"
133 | #write-output "Windows Update Server $env:wsus_server"
134 | # check if you can reach the wsus server
135 | #If (test-connection -quiet $env:wsus_server) {
136 | #$wsusserver="http://" + $env:wsus_server + ":8530"
137 | #} elseif (test-connection -quiet 10.122.168.21) {
138 | #$wsusserver="http://10.122.168.21:8530"
139 | #} else {
140 | #write-output "Unable to contact the wsus server. Using microsoft.com"
141 | #}
142 | # set windows updates to pull from local wsus server
143 | #if ($wsusserver) {
144 | #write-output "WSUS server contacted " $wsusserver
145 | #New-Item -Path "HKLM:Software\Policies\Microsoft\Windows\WindowsUpdate\AU" -force -ErrorAction SilentlyContinue
146 | #Set-ItemProperty -Path "HKLM:\software\policies\Microsoft\Windows\WindowsUpdate" -Name WUServer -Value $wsusserver -Type String -force
147 | #Set-ItemProperty -Path "HKLM:\software\policies\Microsoft\Windows\WindowsUpdate" -Name WUStatusServer -Value $wsusserver -Type String -force
148 | #Set-ItemProperty -Path "HKLM:\software\policies\Microsoft\Windows\WindowsUpdate\AU" -Name UseWUServer -Value "1" -Type DWORD -force
149 | #Set-ItemProperty -Path "HKLM:\software\policies\Microsoft\Windows\WindowsUpdate" -Name TargetGroupEnabled -Value "1" -Type DWORD -force
150 | #Set-ItemProperty -Path "HKLM:\software\policies\Microsoft\Windows\WindowsUpdate" -Name TargetGroup -Value $env:wsus_group -Type String -force
151 | #}
152 | # set winrm to manual start to prevent packer from connecting on reboot
153 | Set-Service -Name winrm -StartupType Manual
154 | # if schedled task does not exist create it
155 | Write-output "Creating scheduled task to start $scriptname with proper elevation"
156 | # setup task scheduler login item to process this script next boot
157 | schtasks /create /ru "BUILTIN\administrators" /sc ONLOGON /tn $scriptname /tr "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -File C:\windows\temp\$scriptname" /rl highest /f /np
158 | }
159 | stop-transcript
160 | exit 0
--------------------------------------------------------------------------------
/answer_files/vmw/10/Autounattend.xml:
--------------------------------------------------------------------------------
1 |
2 |