├── New-IsoWindowsUnattendedPlusVMwareTools.ps1 └── UnattendXML ├── 2016 └── autounattend.xml └── 2012R2 └── autounattend.xml /New-IsoWindowsUnattendedPlusVMwareTools.ps1: -------------------------------------------------------------------------------- 1 |  2 | #Description 3 | #Windows server 2016 unattended installation with VMware tools. 4 | #Build process automatized with PowerShell. 5 | #PVSCI drivers are included in the ISO for an installation on top of "VMware paravirtual SCSI" controller. 6 | #After the installation use "invoke-vmscript" to configure all settings needed in the OS. 7 | 8 | #Notes 9 | #Author: Christophe Calvet 10 | #Based on the work of many others bloggers, complete list in the blog. 11 | #Blog: http:/thecrazyconsultant/windows-server-2016-unattended-installation-plus-vmware-tools 12 | 13 | 14 | # Prerequisites: 15 | ### 1) Windows 10 16 | # SSD strongly recommended for a fast execution 17 | ### 2) Windows ADK installed in the default installation path. (Deployment Tools only) 18 | # https://developer.microsoft.com/en-us/windows/hardware/windows-assessment-deployment-kit 19 | # Use the one associated to your build 20 | # To find your build: (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ReleaseId).ReleaseId 21 | ### 3) Download Windows ISO. 22 | # Example with windows server 2016 evaluation: 23 | # https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2016/ 24 | # 14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO 25 | ### 4) Create "autounattend.xml" for this Operating System. 26 | # The autounattend.xml must be configured to launch the installation of VMware tools. 27 | # Please see details in the blog. 28 | ### 5) Identify the URL of the VMware tools ISO matching the version to be installed in Windows. 29 | # https://packages.vmware.com/tools/esx/index.html 30 | 31 | 32 | ###################RUN THE POWERSHELL SCRIPT AS ADMINISTRATOR##################### 33 | #Disconnect all ISO already mounted if any. 34 | 35 | New-Item -ItemType Directory -Path C:\CustomizedWindowsIso 36 | New-Item -ItemType Directory -Path C:\CustomizedWindowsIso\FinalIso 37 | New-Item -ItemType Directory -Path C:\CustomizedWindowsIso\UnattendXML 38 | 39 | #To create a new ISO: 40 | #1)Disconnect all ISO already mounted 41 | #2)Modify user parameters 42 | #3)Execute all commands below. 43 | 44 | #Modify user parameters as needed. 45 | $SourceWindowsIsoPath = 'C:\ALL ISO\Microsoft\14393.0.161119-1705.RS1_REFRESH_SERVER_EVAL_X64FRE_EN-US.ISO' 46 | $VMwareToolsIsoUrl = "https://packages.vmware.com/tools/esx/6.5/windows/VMware-tools-windows-10.1.0-4449150.iso" 47 | $AutoUnattendXmlPath = 'C:\CustomizedWindowsIso\UnattendXML\2016\autounattend.xml' 48 | #By default the script will install 64 bits drivers for pvscsi but you can edit the relevant lines in the script for 32 bits. 49 | 50 | #Clean DISM mount point if any. Linked to the PVSCSI drivers injection. 51 | Clear-WindowsCorruptMountPoint 52 | Dismount-WindowsImage -path 'C:\CustomizedWindowsIso\Temp\MountDISM' -discard 53 | 54 | #The Temp folder is only needed during the creation of one ISO. 55 | Remove-Item -Recurse -Force 'C:\CustomizedWindowsIso\Temp' 56 | 57 | New-Item -ItemType Directory -Path C:\CustomizedWindowsIso\Temp 58 | New-Item -ItemType Directory -Path C:\CustomizedWindowsIso\Temp\WorkingFolder 59 | New-Item -ItemType Directory -Path C:\CustomizedWindowsIso\Temp\VMwareTools 60 | New-Item -ItemType Directory -Path C:\CustomizedWindowsIso\Temp\MountDISM 61 | 62 | #Prepare path for the Windows ISO destination file 63 | $SourceWindowsIsoFullName = $SourceWindowsIsoPath.split("\")[-1] 64 | $DestinationWindowsIsoPath = 'C:\CustomizedWindowsIso\FinalIso\' + ($SourceWindowsIsoFullName -replace ".iso","") + '-CUSTOM.ISO' 65 | 66 | #Download VMware Tools ISO 67 | $VMwareToolsIsoFullName = $VMwareToolsIsoUrl.split("/")[-1] 68 | $VMwareToolsIsoPath = "C:\CustomizedWindowsIso\Temp\VMwareTools\" + $VMwareToolsIsoFullName 69 | (New-Object System.Net.WebClient).DownloadFile($VMwareToolsIsoUrl, $VMwareToolsIsoPath) 70 | 71 | #Reminder Disconnect all ISO already mounted 72 | 73 | # mount the source Windows iso. 74 | $MountSourceWindowsIso = mount-diskimage -imagepath $SourceWindowsIsoPath -passthru 75 | # get the drive letter assigned to the iso. 76 | $DriveSourceWindowsIso = ($MountSourceWindowsIso | get-volume).driveletter + ':' 77 | 78 | #Mount VMware tools ISO 79 | $MountVMwareToolsIso = mount-diskimage -imagepath $VMwareToolsIsoPath -passthru 80 | # get the drive letter assigned to the iso. 81 | $DriveVMwareToolsIso = ($MountVMwareToolsIso | get-volume).driveletter + ':' 82 | 83 | # Copy the content of the Source Windows Iso to a Working Folder 84 | copy-item $DriveSourceWindowsIso\* -Destination 'C:\CustomizedWindowsIso\Temp\WorkingFolder' -force -recurse 85 | 86 | # remove the read-only attribtue from the extracted files. 87 | get-childitem 'C:\CustomizedWindowsIso\Temp\WorkingFolder' -recurse | %{ if (! $_.psiscontainer) { $_.isreadonly = $false } } 88 | 89 | #Copy VMware tools exe in a custom folder in the future ISO 90 | New-Item -ItemType Directory -Path 'C:\CustomizedWindowsIso\Temp\WorkingFolder\CustomFolder' 91 | #For 64 bits by default. 92 | copy-item "$DriveVMwareToolsIso\setup64.exe" -Destination 'C:\CustomizedWindowsIso\Temp\WorkingFolder\CustomFolder' 93 | #For 32 bits comment above line and uncomment line below. 94 | #copy-item "$DriveVMwareToolsIso\setup.exe" -Destination 'C:\CustomizedWindowsIso\TempWorkingFolder\CustomFolder' 95 | 96 | 97 | #Inject PVSCSI Drivers in boot.wim and install.vim 98 | 99 | #For 64 bits 100 | $pvcsciPath = $DriveVMwareToolsIso + '\Program Files\VMware\VMware Tools\Drivers\pvscsi\Win8\amd64\pvscsi.inf' 101 | #For 32 bits 102 | #$pvcsciPath = $DriveVMwareToolsIso + '\Program Files\VMware\VMware Tools\Drivers\pvscsi\Win8\i386\pvscsi.inf' 103 | 104 | 105 | #Optional check all Image Index for boot.wim 106 | Get-WindowsImage -ImagePath 'C:\CustomizedWindowsIso\Temp\WorkingFolder\sources\boot.wim' 107 | 108 | #Modify all images in "boot.wim" 109 | #Example for windows 2016 iso: 110 | # Microsoft Windows PE (x64) 111 | # Microsoft Windows Setup (x64) 112 | 113 | Get-WindowsImage -ImagePath 'C:\CustomizedWindowsIso\Temp\WorkingFolder\sources\boot.wim' | foreach-object { 114 | Mount-WindowsImage -ImagePath 'C:\CustomizedWindowsIso\Temp\WorkingFolder\sources\boot.wim' -Index ($_.ImageIndex) -Path 'C:\CustomizedWindowsIso\Temp\MountDISM' 115 | Add-WindowsDriver -path 'C:\CustomizedWindowsIso\Temp\MountDISM' -driver $pvcsciPath -ForceUnsigned 116 | Dismount-WindowsImage -path 'C:\CustomizedWindowsIso\Temp\MountDISM' -save 117 | } 118 | 119 | #Optional check all Image Index for install.wim 120 | Get-WindowsImage -ImagePath 'C:\CustomizedWindowsIso\Temp\WorkingFolder\sources\install.wim' 121 | 122 | #Modify all images in "install.wim" 123 | #Example for windows 2016 iso: 124 | # Windows Server 2016 SERVERSTANDARDCORE 125 | # Windows Server 2016 SERVERSTANDARD 126 | # Windows Server 2016 SERVERDATACENTERCORE 127 | # Windows Server 2016 SERVERDATACENTER 128 | 129 | Get-WindowsImage -ImagePath 'C:\CustomizedWindowsIso\Temp\WorkingFolder\sources\install.wim' | foreach-object { 130 | Mount-WindowsImage -ImagePath 'C:\CustomizedWindowsIso\Temp\WorkingFolder\sources\install.wim' -Index ($_.ImageIndex) -Path 'C:\CustomizedWindowsIso\Temp\MountDISM' 131 | Add-WindowsDriver -path 'C:\CustomizedWindowsIso\Temp\MountDISM' -driver $pvcsciPath -ForceUnsigned 132 | Dismount-WindowsImage -path 'C:\CustomizedWindowsIso\Temp\MountDISM' -save 133 | } 134 | 135 | #Add the autaunattend xml for a basic configuration AND the installation of VMware tools. 136 | copy-item $AutoUnattendXmlPath -Destination 'C:\CustomizedWindowsIso\Temp\WorkingFolder\autounattend.xml' 137 | 138 | 139 | #Maybe in a future update of the script 140 | #Add all patches in the ISO with ADD-WINDOWS PACKAGE 141 | 142 | 143 | #Now copy the content of the working folder in the new custom windows ISO. 144 | 145 | $OcsdimgPath = 'C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg' 146 | $oscdimg = "$OcsdimgPath\oscdimg.exe" 147 | $etfsboot = "$OcsdimgPath\etfsboot.com" 148 | $efisys = "$OcsdimgPath\efisys.bin" 149 | 150 | $data = '2#p0,e,b"{0}"#pEF,e,b"{1}"' -f $etfsboot, $efisys 151 | start-process $oscdimg -args @("-bootdata:$data",'-u2','-udfver102', 'C:\CustomizedWindowsIso\Temp\WorkingFolder', $DestinationWindowsIsoPath) -wait -nonewwindow 152 | 153 | #Mount this ISO in a new VM and enjoy. 154 | -------------------------------------------------------------------------------- /UnattendXML/2012R2/autounattend.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | en-US 7 | 8 | en-US 9 | en-US 10 | en-US 11 | en-US 12 | 13 | 14 | 15 | 16 | 17 | 18 | /IMAGE/NAME 19 | Windows Server 2012 R2 SERVERSTANDARD 20 | 21 | 22 | 23 | 0 24 | 2 25 | 26 | 27 | 28 | 29 | true 30 | 31 | 32 | OnError 33 | 34 | 0 35 | true 36 | 37 | 38 | 1 39 | 350 40 | Primary 41 | 42 | 43 | 2 44 | true 45 | Primary 46 | 47 | 48 | 49 | 50 | NTFS 51 | 52 | 1 53 | 1 54 | true 55 | 56 | 57 | NTFS 58 | 59 | 2 60 | 2 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | TheCr@zyConsu1tant 72 | true</PlainText> 73 | </AdministratorPassword> 74 | </UserAccounts> 75 | </component> 76 | </settings> 77 | <settings pass="specialize"> 78 | <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"> 79 | <RunSynchronous> 80 | <RunSynchronousCommand wcm:action="add"> 81 | <Path>D:\CustomFolder\setup64.exe /s /v&quot;/qn REBOOT=R&quot;</Path> 82 | <Order>1</Order> 83 | </RunSynchronousCommand> 84 | </RunSynchronous> 85 | </component> 86 | </settings> 87 | <cpi:offlineImage cpi:source="wim:c:/temp/2012r2/sources/install.wim#Windows Server 2012 R2 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> 88 | </unattend> 89 | -------------------------------------------------------------------------------- /UnattendXML/2016/autounattend.xml: -------------------------------------------------------------------------------- 1 | <?xml version="1.0" encoding="utf-8"?> 2 | <unattend xmlns="urn:schemas-microsoft-com:unattend"> 3 | <settings pass="windowsPE"> 4 | <component name="Microsoft-Windows-International-Core-WinPE" 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"> 5 | <SetupUILanguage> 6 | <UILanguage>en-US</UILanguage> 7 | </SetupUILanguage> 8 | <InputLocale>en-US</InputLocale> 9 | <SystemLocale>en-US</SystemLocale> 10 | <UILanguage>en-US</UILanguage> 11 | <UserLocale>en-US</UserLocale> 12 | </component> 13 | <component name="Microsoft-Windows-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"> 14 | <ImageInstall> 15 | <OSImage> 16 | <InstallFrom> 17 | <MetaData wcm:action="add"> 18 | <Key>/IMAGE/NAME</Key> 19 | <Value>Windows Server 2016 SERVERSTANDARD</Value> 20 | </MetaData> 21 | </InstallFrom> 22 | <InstallTo> 23 | <DiskID>0</DiskID> 24 | <PartitionID>2</PartitionID> 25 | </InstallTo> 26 | </OSImage> 27 | </ImageInstall> 28 | <UserData> 29 | <AcceptEula>true</AcceptEula> 30 | </UserData> 31 | <DiskConfiguration> 32 | <WillShowUI>OnError</WillShowUI> 33 | <Disk wcm:action="add"> 34 | <DiskID>0</DiskID> 35 | <WillWipeDisk>true</WillWipeDisk> 36 | <CreatePartitions> 37 | <CreatePartition wcm:action="add"> 38 | <Order>1</Order> 39 | <Size>500</Size> 40 | <Type>Primary</Type> 41 | </CreatePartition> 42 | <CreatePartition wcm:action="add"> 43 | <Order>2</Order> 44 | <Extend>true</Extend> 45 | <Type>Primary</Type> 46 | </CreatePartition> 47 | </CreatePartitions> 48 | <ModifyPartitions> 49 | <ModifyPartition wcm:action="add"> 50 | <Format>NTFS</Format> 51 | <Label>System Reserved</Label> 52 | <Order>1</Order> 53 | <PartitionID>1</PartitionID> 54 | <Active>true</Active> 55 | </ModifyPartition> 56 | <ModifyPartition wcm:action="add"> 57 | <Format>NTFS</Format> 58 | <Label></Label> 59 | <Order>2</Order> 60 | <PartitionID>2</PartitionID> 61 | </ModifyPartition> 62 | </ModifyPartitions> 63 | </Disk> 64 | </DiskConfiguration> 65 | </component> 66 | </settings> 67 | <settings pass="oobeSystem"> 68 | <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"> 69 | <UserAccounts> 70 | <AdministratorPassword> 71 | <Value>TheCr@zyConsu1tant</Value> 72 | <PlainText>true</PlainText> 73 | </AdministratorPassword> 74 | </UserAccounts> 75 | </component> 76 | </settings> 77 | <settings pass="specialize"> 78 | <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"> 79 | <RunSynchronous> 80 | <RunSynchronousCommand wcm:action="add"> 81 | <Path>D:\CustomFolder\setup64.exe /s /v&quot;/qn REBOOT=R&quot;</Path> 82 | <Order>1</Order> 83 | </RunSynchronousCommand> 84 | </RunSynchronous> 85 | </component> 86 | </settings> 87 | <cpi:offlineImage cpi:source="wim:c:/temp/2016/sources/install.wim#Windows Server 2016 SERVERSTANDARD" xmlns:cpi="urn:schemas-microsoft-com:cpi" /> 88 | </unattend> 89 | --------------------------------------------------------------------------------