Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Load-Module DISM
- $wsusoffline_directory = "PATH_TO_WSUSOFFLINE_BASE_DIRECTORY"
- $work_base_directory = "PATH_TO_WORK_DIRECTORY"
- $scratch_directory = "$($wsusoffline_directory)\temp"
- $scratch_image = "$($scratch_directory)\work.wim"
- $image_index = 1 # or whatever it is on your WIM file
- $cabs = Get-ChildItem -Path "$($wsusoffline_directory)\client" -Recurse -Include *.cab,*.msu -Exclude wsusscn2.cab | Sort-Object LastWriteTime
- Write-Host "Mounting Image"
- $mounted_image = Mount-WindowsImage -ImagePath $scratch_image -Index $image_index -Path "$($work_base_directory)\mountpoint"
- Write-Host "Adding Packages to Image"
- $failed_updates = [ordered]@{}
- foreach ($cab in $cabs){
- $add_result = Add-WindowsPackage -PackagePath $cab.FullName -Path "$($work_base_directory)\mountpoint" -Verbose -LogPath "$($work_base_directory)\updates.log" -LogLevel WarningsInfo -ScratchDirectory $scratch_directory
- if($? -eq $true){
- ($scratch_image,$cab.FullName) -join " :: " | Out-File -FilePath "$($work_base_directory)\updates-success.log" -Append
- } else {
- if($Error[0].Exception.HResult -eq 0x800f081e){
- ($scratch_image,$cab.FullName) -join " :: " | Out-File -FilePath "$($work_base_directory)\updates-Notapplicable.log" -Append
- } else {
- ($scratch_image,$cab.FullName) -join " :: " | Out-File -FilePath "$($work_base_directory)\updates-failed.log" -Append
- $failed_updates.Add($cab, 1)
- }
- }
- }
- while ($failed_updates.Count -gt 0) {
- foreach ($cab in $failed_updates.Keys){
- $add_result = Add-WindowsPackage -PackagePath $cab.FullName -Path "$($work_base_directory)\mountpoint" -Verbose -LogPath "$($work_base_directory)\updates.log" -LogLevel WarningsInfo -ScratchDirectory $scratch_directory
- if($? -eq $true){
- ($scratch_image,$cab.FullName) -join " :: " | Out-File -FilePath "$($work_base_directory)\updates-success.log" -Append
- $failed_updates.Remove($cab)
- } else {
- $failed_updates[$cab] += 1
- ($scratch_image,$cab.FullName, "Try #$($failed_updates[$cab])]") -join " :: " | Out-File -FilePath "$($work_base_directory)\updates-failed.log" -Append
- if ($failed_updates[$cab] -ge 5){
- $failed_updates.Remove($cab)
- }
- }
- }
- }
- Write-Host "Enabling Features"
- $features = Get-WindowsOptionalFeature -Path "$($work_base_directory)\mountpoint" -LogPath "$($work_base_directory)\features.log" -ScratchDirectory $scratch_directory -LogLevel WarningsInfo -Verbose
- $enable_features = $features | Where-Object {
- $_.FeatureName -in (
- "MicrosoftWindowsPowerShellV2Root", "MicrosoftWindowsPowerShellV2", "NetFx3",
- "NetFx4-AdvSrvs", "TelnetClient", "TFTP"
- ) -and $_.State -notin ([Microsoft.Dism.Commands.FeatureState]::Enabled,
- [Microsoft.Dism.Commands.FeatureState]::EnablePending,
- [Microsoft.Dism.Commands.FeatureState]::Superseded)
- } | Enable-WindowsOptionalFeature -Path "$($work_base_directory)\mountpoint" -LogPath "$($work_base_directory)\features.log" -ScratchDirectory $scratch_directory -LogLevel WarningsInfo -Verbose
- Write-Host "Disabling Features"
- $disable_features = $features | Where-Object {
- $_.FeatureName -in (
- "WCF-Services45", "WCF-TCP-PortSharing45", "NetFx4Extended-ASPNET45",
- "Microsoft-Hyper-V-All", "SimpleTCP", "SNMP",
- "IIS-WebServerRole", "IIS-WebServer", "IIS-FTPServer",
- "IIS-FTPSvc", "IIS-FTPExtensibility", "Microsoft-Windows-MobilePC-Client-Premium-Package-net",
- "Microsoft-Windows-MobilePC-LocationProvider-INF", "TelnetServer", "SMB1Protocol"
- ) -and $_.State -notin ([Microsoft.Dism.Commands.FeatureState]::Disabled,
- [Microsoft.Dism.Commands.FeatureState]::DisablePending,
- [Microsoft.Dism.Commands.FeatureState]::DisabledWithPayloadRemoved,
- [Microsoft.Dism.Commands.FeatureState]::Superseded)
- } | Disable-WindowsOptionalFeature -Path "$($work_base_directory)\mountpoint" -LogPath "$($work_base_directory)\features.log" -ScratchDirectory $scratch_directory -LogLevel WarningsInfo -Verbose
- Write-Host "Disabling Bloatware"
- $disable_bloatware = Get-AppxProvisionedPackage -Path "$($work_base_directory)\mountpoint" -LogPath $($work_base_directory)\appx.log" -ScratchDirectory $scratch_directory -LogLevel WarningsInfo -Verbose | Where-Object {
- $_.DisplayName -in (
- "Microsoft.BingFinance", "Microsoft.BingFoodAndDrink", "Microsoft.BingHealthAndFitness",
- "Microsoft.BingMaps", "Microsoft.BingNews", "Microsoft.BingSports",
- "Microsoft.BingTravel", "Microsoft.BingWeather", "Microsoft.SkypeApp",
- "Microsoft.XboxLIVEGames", "Microsoft.ZuneMusic", "Microsoft.ZuneVideo"
- )
- } | Remove-AppxProvisionedPackage -path "$($work_base_directory)\mountpoint" -LogPath "$($work_base_directory)\appx.log" -ScratchDirectory $scratch_directory -LogLevel WarningsInfo -Verbose
- Write-Host "Injecting Post-Setup executables"
- # Copy desired executables (frameworks, runtimes, etc) to (IMAGE)\postsetup and append entries to (image)\Windows\Setup\Scripts\SetupComplete.cmd to run unattended installation
- $postsetup_script_file = "$($work_base_directory)\mountpoint\Windows\Setup\Scripts\SetupComplete.cmd"
- [System.Collections.ArrayList]$postsetup_script = Get-Content $postsetup_script_file
- ##Ensure cleanup is done on post-install
- Write-Host "Adding Component Store Cleanup"
- $component_store_cleanup = (
- "start /wait c:\windows\system32\dism.exe /Online /LogPath:c:\setup.log\cleanup-spsuperseded.log /LogLevel:3 /Cleanup-Image /SPSuperseded",
- "start /wait c:\windows\system32\dism.exe /Online /LogPath:c:\setup.log\cleanup-resetbase.log /LogLevel:3 /Cleanup-Image /StartComponentCleanup /ResetBase",
- "start /wait c:\windows\system32\dism.exe /Online /LogPath:c:\setup.log\cleanup-components.log /LogLevel:3 /Cleanup-Image /StartComponentCleanup"
- )
- [System.Collections.ArrayList]$postsetup_script = $postsetup_script | Where-Object { $_ -notin $component_store_cleanup }
- $component_store_cleanup | ForEach-Object { $postsetup_script.Insert($postsetup_script.IndexOf("md c:\setup.log")+1, $_ ) }
- Write-Host "Writing New PostSetup Script"
- $postsetup_script | Out-File $postsetup_script_file -Encoding ascii -Verbose
- Write-Host "Committing Changes to Image"
- $retry_counter = 10
- do{
- $retry_counter -= 1
- Dismount-WindowsImage -Path "$($work_base_directory)\mountpoint" -Save
- }while($? -eq $false -and $retry_counter -gt 0)
Add Comment
Please, Sign In to add comment