PowerShell: Windows 2016 Pristine Image

Desired Output

Windows Server deployment should be made as seamless and efficient as possible. Here’s a sample output of a recent script:

Now Performing System Scan as triggered by script C:\Users\kimconnect\Desktop\windows-prep.ps1:

----------------------------------------------------------


Checking Internet Access...

WARNING: No Internet Access Detected!
Type 'Yes' or 'y' to set the proxy as http://proxy:8080 - 'no' or 'n' to proceed without Internet: yes

Current WinHTTP proxy settings:

Proxy Server(s) : http://proxy:8080
Bypass List : localhost;*.kimconnect.com

Proxy is now good to go...

Checking SNMP...


1 : snmp.kimconnect.com
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SNMP\Parameters\PermittedManagers
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SNMP\Parameters
PSChildName : PermittedManagers
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry

kimconnect : 4
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SNMP\Parameters\ValidCommunities
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\SNMP\Parameters
PSChildName : ValidCommunities
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry


Checking for Local Administrator Password Solution (LAPS)...
LAPS is installed.

Microsoft Licensing Status(es)...
Description : Windows(R) Operating System, VOLUME_KMSCLIENT channel
LicenseStatus : 1


Checking IISCrypto...
SSL 3.0 is Disabled
TLS 1.0 is Disabled
TLS 1.1 is Disabled
TLS 1.2 is Enabled
IISCryptoCli is available.

Checking RDP...
RDP Network Authentication Requirement: passed!
RDP Encryption Level: FIPS Compliant

Scanning for vulnerabilities...

----------------------------------------------------------
Internet Explorer
CVE-2017-829 (32-Bit): pass
CVE-2017-8529 (64-bit): pass
ASLR Hardening Setting for IE (32-Bit): pass
ASLR Hardening Setting for IE (64-Bit): pass

----------------------------------------------------------

Memory Management Registry Keys
CVE-2017-5715: pass
CVE-2017-5715: pass
CVE-2017-5753-54: pass

----------------------------------------------------------
SNMP: pass

----------------------------------------------------------

Remote Code Execution
MS11-025 (MFC Remote Code Execution): Pass

----------------------------------------------------------
Windows Defender is NOT enabled on this system.

Checking Windows Updates...
----------------------------------------------------------
Here is a detailed list of Updates on this system...
----------------------------------------------------------

Result Date Title
------ ---- -----
Succeeded 5/9/2019 2:05:28 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1172.0)
Succeeded 5/9/2019 1:19:35 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1167.0)
Succeeded 5/9/2019 12:31:43 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1165.0)
Succeeded 5/8/2019 6:25:50 PM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1144.0)
Succeeded 5/8/2019 1:39:14 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1093.0)
Succeeded 5/8/2019 12:31:42 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1090.0)
Succeeded 5/7/2019 9:42:18 PM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1071.0)
Succeeded 5/7/2019 12:31:43 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.1014.0)
Succeeded 5/6/2019 12:31:41 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.931.0)
Succeeded 5/5/2019 12:31:41 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.869.0)
Succeeded 5/4/2019 12:31:35 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.799.0)
Succeeded 5/3/2019 11:19:05 PM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.795.0)
Succeeded 5/3/2019 9:54:09 PM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.790.0)
Succeeded 5/3/2019 12:31:39 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.681.0)
Succeeded 5/2/2019 12:31:45 AM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.630.0)
Succeeded 5/1/2019 7:27:52 PM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.619.0)
Aborted 5/1/2019 7:16:36 PM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.619.0)
Succeeded 5/1/2019 7:16:36 PM Update for Windows Defender Antivirus antimalware platform - KB4052623 (Version 4.18.1904.1)
Succeeded 5/1/2019 6:55:41 PM Definition Update for Windows Defender Antivirus - KB2267602 (Definition 1.293.612.0)
Succeeded 5/1/2019 6:55:26 PM 2019-04 Cumulative Update for Windows Server 2016 for x64-based Systems (KB4493473)
Succeeded 5/1/2019 6:48:10 PM Realtek Semiconductor Corp. - USB - 4/1/2019 12:00:00 AM - 10.0.17763.31247
Succeeded 5/1/2019 6:48:08 PM Intel - System - 1/21/2019 12:00:00 AM - 1904.12.0.1208
Succeeded 5/1/2019 6:48:07 PM Windows Malicious Software Removal Tool x64 - April 2019 (KB890830)
Succeeded 5/1/2019 6:46:36 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 IOxAPIC Configuration Registers - 2036
Succeeded 5/1/2019 6:46:32 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 LMDP Channel 1 - 2047
Succeeded 5/1/2019 6:46:28 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 M3KTI Registers - 204C
Succeeded 5/1/2019 6:46:24 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 LMS Channel 2 - 204A
Succeeded 5/1/2019 6:46:21 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 CHA Registers - 208D
Succeeded 5/1/2019 6:45:49 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 CHA Registers - 2056
Succeeded 5/1/2019 6:45:46 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 Integrated Memory Controller - 2041
Succeeded 5/1/2019 6:45:43 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 CBDMA Registers - 2021
Succeeded 5/1/2019 6:45:30 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 M2PCI Registers - 2018
Succeeded 5/1/2019 6:45:25 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 DECS Channel 2 - 2048
Succeeded 5/1/2019 6:45:22 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 LM Channel 1 - 2045
Succeeded 5/1/2019 6:45:18 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 KTI 0 - 2058
Succeeded 5/1/2019 6:45:13 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 PCU Registers - 2085
Succeeded 5/1/2019 6:45:11 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 Ubox Registers - 2016
Succeeded 5/1/2019 6:45:09 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 CHA Registers - 208E
Succeeded 5/1/2019 6:44:31 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 PCI Express Root Port 1A - 2030
Succeeded 5/1/2019 6:43:44 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 LMS Channel 1 - 2046
Succeeded 5/1/2019 6:43:40 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 CHA Registers - 2057
Succeeded 5/1/2019 6:43:39 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 Integrated Memory Controller - 2043
Succeeded 5/1/2019 6:43:35 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 PCU Registers - 2083
Succeeded 5/1/2019 6:43:33 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 MM/Vt - d Configuration Registers - 2024
Succeeded 5/1/2019 6:43:31 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 Integrated Memory Controller - 2044
Succeeded 5/1/2019 6:43:28 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 PCU Registers - 2081
Succeeded 5/1/2019 6:43:26 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 Integrated Memory Controller - 2066
Succeeded 5/1/2019 6:43:22 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 LMDP Channel 2 - 204B
Succeeded 5/1/2019 6:43:18 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 PCU Registers - 2080
Succeeded 5/1/2019 6:43:16 PM Intel - Other hardware - Intel(R) Xeon(R) processor P family/Core i7 M3KTI Registers - 204D


----------------------------------------------------------
Checking for New Updates from Microsoft...
----------------------------------------------------------
No New Updates Detected.

----------------------------------------------------------

This system has passed all checks. No further action is necessary.

----------------------------------------------------------
PowerShell Script:
#Declare global variables
$proxy="http://proxy:8080";
$exclusionList="localhost;*.kimconnect.com"
$snmpCommunities=@(@{Name='COMMUNITY1'; Rights='Read Only'})
$snmpHosts = 'snmp01.kimconnect.com';
$windowsLicense="xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
$script=$MyInvocation.MyCommand.Path
$regexTargetOS="[w+0-9]*Windows Server 2016"
$GLOBAL:fixList=New-Object System.Collections.ArrayList;
$targetKernelVersion="10.0.14393.2969"
$kernelDownload="http://download.windowsupdate.com/d/msdownload/update/software/updt/2019/05/windows10.0-kb4505052-x64_5a55867f01ad604494c2ed4291f7372e1eab4fea.msu"
# Initialize
function showFunctions{
$functions=(Get-ChildItem function:).Name
foreach ($function in $functions){
if ($function.length -gt 4){
$function
}
}
}

# This function will allow a scriptblock to be attempted X number of times
# To call this, follow the syntax of "TryLoop -ScriptBlock{execute something here;} -Retries X" where X is the number of retries
function TryLoop {
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$True)]
[scriptblock]$ScriptBlock,

[Parameter(Position=1, Mandatory=$False)]
[int]$Retries = 2
)

Begin {
$count = 0
}

Process {
do {
$count++
try {
$ScriptBlock.Invoke()
return
} catch {
Write-Error $_.Exception.InnerException.Message -ErrorAction Continue
}
} while ($count -lt $Retries)

throw 'ScriptBlock failed.'
}
}

function checkWinDefender{
if(!($haveInternet)){"Cannot Proceed without Internet Access";break;}
try{
$regexGetVersion='(<[^>]+>|[:\s]+|Version)' #Test regex at RegexStorm.net
$regexGetReleaseDate='(<[^>]+>|^\s|\s+$|Released:)'
$winDefenderDefURL="https://www.microsoft.com/en-us/wdsi/definitions"

#$html = Invoke-WebRequest –Uri $winDefenderDefURL -Method Get
#$html = Start-BitsTransfer -Source $winDefenderDefURL
#$html = (New-Object System.Net.Webclient).Downloadstring($winDefenderDefURL);
$mpStatus=Get-MpComputerStatus
$actualVersion=$mpStatus.AntivirusSignatureVersion -replace $regexGetVersion
$lastUpdated=$mpStatus.AntispywareSignatureLastUpdated

#$today = Get-Date -Format g
try{
$html = Invoke-WebRequest –Uri $winDefenderDefURL -Method Get;
}
catch{
"URL retrieval process has an error. Retrying...";
$html=$False
}

if ($html){
$latestVersion=($html.tostring() -split "[`r`n]" | select-string "Version:") -replace $regexGetVersion;
$releaseDate=($html.tostring() -split "[`r`n]" | select-string "Released:") -replace $regexGetReleaseDate -replace " ";
$releaseDateLocalTime=[System.TimeZoneInfo]::ConvertTimeFromUtc($releaseDate,[System.TimeZoneInfo]::FindSystemTimeZoneById((Get-WmiObject win32_timezone).StandardName))
$timeDifference = New-TimeSpan -Start $lastUpdated -End $releaseDate
$daysDifference=$timeDifference.Days

if($latestVersion -ne 0){
"It has been $daysDifference day(s) between Last Update: $lastUpdated and New Release: $releaseDate";
if ($actualVersion -ne $latestVersion){
"Malware Antivirus Signature version $actualVersion on this system does not match the Latest version $latestVersion... `nIssue the command -- updateWinDefender -- to fix this.";
#Update-MPSignature;
}
else{
"Excellent! Malware Antivirus Definition $actualVersion on this computer matches the Microsoft release."
}
}
else{checkWinDefender;}
}
else{
checkWinDefender;
}
"Please note that Microsoft Windows Defender should be removed if there's an Enterprise Antivirus scanner installed on this system.";
$fixList.Add('removeWinDefender');
}
catch{
"Windows Defender is NOT enabled on this system.";
}
}

function removeWinDefender{
Remove-WindowsFeature Windows-Defender, Windows-Defender-GUI;
}

function updateWinDefender{
if(!($haveInternet)){if(!($haveInternet)){"Cannot Proceed without Internet Access";break;}}
try{
Update-MpSignature;
"Done."
}
catch{
"There was an error."
}
}

function checkUpdates{
# Check for applied updates
<# Too much information
"`nHere is a list of Updates already applied..."
gwmi win32_quickfixengineering | sort installedon -desc
#>
"----------------------------------------------------------"
"Here is a detailed list of Updates on this system..."
"----------------------------------------------------------"
function Convert-WuaResultCodeToName{
param( [Parameter(Mandatory=$true)]
[int] $ResultCode
)
$Result = $ResultCode
switch($ResultCode){
2 { $Result = "Succeeded" }
3 { $Result = "Succeeded With Errors" }
4 { $Result = "Failed" }
5 { $Result = "Aborted" }
}
return $Result
}

function Get-WuaHistory{
# Get a WUA Session
$session = (New-Object -ComObject 'Microsoft.Update.Session')

# Query the latest 1000 History starting with the first recordp
$history = $session.QueryHistory("",0,50) | ForEach-Object {
$Result = Convert-WuaResultCodeToName -ResultCode $_.ResultCode
# Make the properties hidden in com properties visible.
$_ | Add-Member -MemberType NoteProperty -Value $Result -Name Result
$Product = $_.Categories | Where-Object {$_.Type -eq 'Product'} | Select-Object -First 1 -ExpandProperty Name
Write-Output $_
}

#Remove null records and only return the fields we want
$history | Where-Object {![String]::IsNullOrWhiteSpace($_.title)} |
Select-Object Result, Date, Title
}
Get-WuaHistory | Format-Table

# Checking for Available Updates
"----------------------------------------------------------"
"Checking for New Updates from Microsoft...`n----------------------------------------------------------"
$availableUpdates

# This registry settings means Windows Update Server is OFF
$wuPath="Registry::HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU"
$wuKey="UseWUServer"
$wuValue=0

$wuIsOn=checkRegKey -path $wuPath -name $wuKey -value 1

# If Windows Update Server is ON, then temporarily set it to off > check for Microsoft Updates > then set it back to ON
# Preemptively resolve error: Exception from HRESULT: 0x8024401C
if($wuIsOn){
setRegKey -path $wuPath -name $wuKey -value $wuValue
$availableUpdates=Get-WUList
setRegKey -path $wuPath -name $wuKey -value 1
}
else{
$availableUpdates=Get-WUList
}

if($availableUpdates){$availableUpdates;$fixList.Add('updateWindows');}
else{"No New Updates Detected.";}
}

function checkRDP{
$rdpAuth=(Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").UserAuthenticationRequired
$encryptionLevel=(Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").MinEncryptionLevel
switch ($encryptionLevel){
1 {$compliant="Low";}
2 {$compliant="Client Compatible";}
3 {$compliant="High";}
4 {$compliant="FIPS Compliant";}
}
if($rdpAuth){"RDP Network Authentication Requirement: passed!`nRDP Encryption Level: $compliant";}else{"RDP Network Authentication Requirement: failed!`nNeed to run the secureRDP command to fix this issue.";$fixList.Add('secureRDP');}
}

function checkSpectreVulnerability{
<#
# Checking hotfix
Get-HotFix -Id "KB4346087"
dism /online /get-packages | findstr KB4346087
#>

$regexRemoveDots="\."
$patchedVersion="10.0.14393.2842"
$actualVersion=(Get-Item C:\Windows\system32\mcupdate_genuineintel.dll | select VersionInfo).VersionInfo.ProductVersion
if($actualVersion.length -lt 15){$actualVersion+"0";}
else{$fixedActualVersion=$actualVersion;}
"$actualVersion vs $patchedVersion"
if([double]($fixedActualVersion -replace $regexRemoveDots) -lt [double]($patchedVersion -replace $regexRemoveDots)){
"Spectre meltdown vulnerability detected.";
fixList.Add('fixSpectreVulnerability');
}
else{"No Spectre meltdown vulnerability detected.";}
}

function fixSpectreVulnerability{
# KB4346087: http://www.catalog.update.microsoft.com/Search.aspx?q=KB4346087%20
$spectreDownload="http://download.windowsupdate.com/c/msdownload/update/software/updt/2019/02/windows10.0-kb4346087-v3-x64_d108fe2af745ebf98bfb0548c905c07715492941.msu"
$spectreDestination="C:\Temp\kb4346087-v3-x64.msu"
download $spectreDownload $spectreDestination
wusa.exe -kb $spectreDestination /norestart /quiet

<#
# DISM method
mkdir c:\temp\KB4346087
Expand –F:* $spectreDestination c:\temp\KB4346087
DISM.exe /Online /Add-Package /PackagePath:c:\temp\KB4346087\Windows10.0-KB4346087-v3-x64.cab /NoRestart
#>
}

function checkVulnerabilities{
$remediateVulnerabilities=$False

$ieKeys=@(
@("CVE-2017-829 (32-Bit)","HKLM:SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ENABLE_PRINT_INFO_DISCLOSURE_FIX"),
@("CVE-2017-8529 (64-bit)","HKLM:SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ENABLE_PRINT_INFO_DISCLOSURE_FIX"),
@("ASLR Hardening Setting for IE (32-Bit)","HKLM:SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ALLOW_USER32_EXCEPTION_HANDLER_HARDENING"),
@("ASLR Hardening Setting for IE (64-Bit)","HKLM:SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ALLOW_USER32_EXCEPTION_HANDLER_HARDENING")
)

$memKeys=@(
@("CVE-2017-5715","HKLM:SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management","FeatureSettingsOverride","0"),
@("CVE-2017-5715","HKLM:SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management","FeatureSettingsOverrideMask","3"),
@("CVE-2017-5753-54","HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization","MinVmVersionForCpuBasedMitigations","1.0")
)

$snmpKeys=@(@("HKLM:System\CurrentControlSet\Services\snmp\parameters","TrapConfiguration","1"))

"`n----------------------------------------------------------"
"Internet Explorer"
foreach ($ieKey in $ieKeys){
try{
$value=(Get-ItemProperty -Path $ieKey[1] -Name "iexplore.exe").'iexplore.exe';
}
catch{
$value=0;
continue;
}
$result=if($value -eq 1){"pass"}else{"fail";$remediateVulnerabilities=$True;}
$ieKey[0] + ": " + $result
}
"`n----------------------------------------------------------"

"`nMemory Management Registry Keys"
foreach ($memKey in $memKeys){
$value=(Get-ItemProperty -Path $memKey[1] -Name $memKey[2]).[string]($memKey[2])
$result=if($value -eq $memKey[3]){"pass"}else{"fail";$remediateVulnerabilities=$True;}
$memKey[0]+ ": " + $result
}
"`n----------------------------------------------------------"

$value=(Get-ItemProperty -Path $snmpKeys[0] -Name $snmpKeys[1]).[string]($snmpKeys[1])
$result=if($value -eq $snmpKeys[2]){"pass"}else{"fail";$remediateVulnerabilities=$True;}
"SNMP: " + $result
"`n----------------------------------------------------------"

"`nRemote Code Execution"
$minVersion=14
$vcVersions=(Get-ItemProperty Registry::HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | where {$_.displayname -like "Microsoft Visual C++*"} | Select-Object DisplayVersion)
foreach ($version in $vcVersions){
if($version.DisplayVersion -ge $minVersion){
$safeFlag=$True;
}
}
if ($safeFlag){
"MS11-025 (MFC Remote Code Execution): Pass"
}
else{$remediateVulnerabilities=$True;}


"`n----------------------------------------------------------"
checkWinDefender;
<# This doesn't work
$hive=(Get-ChildItem -Path "HKLM:SOFTWARE\Microsoft\VisualStudio").Name
$vcInstalled=(Get-ItemProperty -Path "Registry::$hive\VC\Runtimes\x64" -Name "Installed").Installed
if($vcInstalled){
"`nMS11-025 MFC Remote Code Execution: Pass`n"
}
#>

"`n----------------------------------------------------------"
checkSpectreVulnerability;

if ($remediateVulnerabilities){fixList.Add('remediateVulnerabilities');}
}

function scanSystem{
"`nChecking Internet Access..."
if(checkProxy){
"`nInternet access is good!";
$GLOBAL:haveInternet=$True;
}
else{
"`nWARNING: No Internet Access Detected!";

$yesArray='yes','y'
$noArray='no','n'

do {
$userInput=(Read-Host -Prompt "Type 'Yes' or 'y' to set the proxy as $proxy - 'no' or 'n' to proceed without Internet").toLower()
switch($userInput){
'yes'{fixproxy;}
'y'{fixproxy;}
'no'{break;}
'n'{break;}
}
} while (!($yesArray -match $userInput -or $noArray -match $userInput))


<# Popup method
do {
$a = new-object -comobject wscript.shell
$userInput = $a.popup("Do you want to fix this issue?", 0, "Fix Proxy", 3)
$userInput
if ($userInput -eq 6){
fixProxy;
$a.popup("Proxy fixed.")
}
if ($userInput -eq 2){
$a.popup("Proxy not fixed. Continuing at user's discretion...")
$GLOBAL:haveInternet=$False;
break;
}
} while ($userInput -ne 6 -or $userInput -ne 2)
#>
}


"`nChecking SNMP...";
try{
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\services\SNMP\Parameters\PermittedManagers";
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\services\SNMP\Parameters\ValidCommunities";
}
catch{
"SNMP is not set correctly.";
$fixList.Add('setSNMP');
}

"`nChecking for Local Administrator Password Solution (LAPS)..."
if(Get-ChildItem 'C:\Program Files\LAPS\CSE\Admpwd.dll'){"LAPS is installed."}else{"LAPS is not installed.";$fixList.Add('installLaps');}

"`nMicrosoft Licensing Status(es)..."
Get-CimInstance -ClassName SoftwareLicensingProduct | where {$_.PartialProductKey} | select Description, LicenseStatus

"`nChecking IISCrypto..."
checkIISCrypto;

"`nChecking RDP..."
checkRDP;

"`nScanning for vulnerabilities..."
checkVulnerabilities;

"`nChecking Windows Updates..."
checkUpdates;
checkNTKernel;
}

function checkProxy{
try{
$connectionTest=iwr download.microsoft.com
#$connectionSucceeds=Test-NetConnection -Computername download.microsoft.com -Port 443 -InformationLevel Quiet
if ($connectionTest){
$haveInternet=$True;
return $True;
}
}
catch{
return $False
}
}

function fixProxy{

# Check if proxy is enabled on the system and fix it
$proxyKey=(Get-ItemProperty -Path "Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings")
if ($proxyKey.ProxyEnable){
# Set http proxy for browsers
Set-Itemproperty -path "Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name 'ProxyServer' -value $proxy

# Set winhttp proxy for PowerShell
netsh winhttp set proxy $proxy $exclusionList

# Commands to verify proxy settings
# netsh winhttp show proxy

# Reset winhttp proxy
# netsh winhttp reset

#$proxy = [System.Net.WebProxy]::GetDefaultProxy().Address #skips this because the default sometimes is wrong
[system.net.webrequest]::defaultwebproxy = New-Object system.net.webproxy($proxy)
[system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# Set current Shell session to use proxy (not recommended)
#$PSDefaultParameterValues = @{"*:Proxy"="$proxy";}

<#
# Set PowerShell User Agent to be recognized by the proxy and authenticate via Default AD credential
$webClient = new-object System.Net.WebClient
$webClient.Headers.Add(“user-agent”, “PowerShell Script”)
$webClient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
<#

<# Registry manipulation
# Set proxy registry
$asciiValue = "(   $proxy $exclusionList" #The hidden binary characters wouldn't show up as ASCII chars so this conversion doesn't work currently
$binaryValue = [system.Text.Encoding]::Default.GetBytes($asciiValue) | %{[System.Convert]::ToString($_) }
$winHTTPHive = "Registry::HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"
$winHTTPKey = "WinHttpSettings"
Set-ItemProperty -Path $winHTTPHive -Name $winHTTPKey -Value $binaryValue

# Check values
$WinHttpValue=(Get-ItemProperty -Path $winHTTPHive -Name $winHTTPKey).WinHttpSettings
[Text.Encoding]::ASCII.getString($WinHttpValue) # Display Binary as ASCCI - PowerShell default

#>
}

if (checkProxy){
"Proxy is now good to go..."
$GLOBAL:haveInternet=$True;
}
else{
"Proxy problems..."
$GLOBAL:haveInternet=$False;
break;
}
}

# This function takes 1 or 2 arguments
# If the destination is not specified, a downloaded file shall be placed inside the C:\Temp directory as the same file name as the source
function download{
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$True)]
[string]$source,

[Parameter(Position=1, Mandatory=$False)]
[string]$destination = "C:\Temp\$(Split-Path $source -leaf)"
)

New-Item -ItemType Directory -Force -Path $(split-path $destination) # Create Temp folder if it doesn't already exist
if ($haveInternet){
# BitsTransfer doesn't work with strict proxies
# Start-BitsTransfer -Source $source -Destination $destination;
(New-Object System.Net.WebClient).DownloadFile($source, $destination)
}
else{
#fixProxy;
"`n$source was not accessible at this time. Download is aborted."
}
}

function updateWindows{
if(!($haveInternet)){fixProxy;}

# Set PowerShell Gallery as Trusted to bypass prompts
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted

# Include the PowerShell Windows Update module
$checkModule=Get-Module -ListAvailable -Name PSWindowsUpdate
if(!($checkModule)){Install-Module PSWindowsUpdate -Confirm:$false;}

# Register the user of Windows Update Service if it has not been registered
$MicrosoftUpdateID="7971f918-a847-4430-9279-4a52d1efe18d"
$registered=(Get-WUServiceManager).ServiceID | Where-Object {$MicrosoftUpdateID -contains $_}
if (!($registered)){
Add-WUServiceManager -ServiceID $MicrosoftUpdateID -Confirm:$false
}

# Handling Windows Updates Server settings
# This registry settings means Windows Update Server is OFF
$wuPath="Registry::HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate\AU"
$wuKey="UseWUServer"
$wuIsOff=checkRegKey -path $wuPath -name $wuKey -value 0
$wuIsOn=checkRegKey -path $wuPath -name $wuKey -value 1

# This preemptively resolves error: Exception from HRESULT: 0x8024401C
if($wuIsOn){
# Turn WU Server OFF temporarily
setRegKey -path $wuPath -name $wuKey -value 0
restart-service wuauserv

# Perform Updates
Get-WindowsUpdate -AcceptAll -MicrosoftUpdate -Install -IgnoreReboot;

# Turn Windows Update Server back to ON
setRegKey -path $wuPath -name $wuKey -value 1
restart-service wuauserv

"Windows Update sequence is completed.";
}
else{
# Perform Updates
Get-WindowsUpdate -AcceptAll -MicrosoftUpdate -Install -IgnoreReboot;
"Windows Update sequence is completed.";
}
}

function optimizeWindows{
"`nDisable Gisvc..."
try{
sc config "GISvc" start= disabled
sc stop "GISvc"
}
catch{
"VMWare Tools is not installed in this system. Skipping..."
}

"`nDisable MapsBroker..."
try{
sc config "MapsBroker" start= disabled
sc stop "MapsBroker"
}
catch{
"MapsBroker is not found. Skipping..."
}

#Disable OneSync
#Set DWORD of "Start"=4 in HKLM:\System\CurrentControlSet\Services\OneSyncSvc*

#Adjust memory settings for Best Performance

"`nSet Power Options..."
powercfg /setactive SCHEME_MIN
powercfg /hibernate off
powercfg -L
powercfg /hibernate off

"`nInstall Telnet Client..."
Install-WindowsFeature -name Telnet-Client
#dism /online /Enable-Feature /FeatureName:TelnetClient
}

function remediateVulnerabilities{
if(!($haveInternet)){fixProxy;}

"`nVCE-2017-829..."
reg add "HKLM\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ENABLE_PRINT_INFO_DISCLOSURE_FIX" /v iexplore.exe /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ENABLE_PRINT_INFO_DISCLOSURE_FIX" /v iexplore.exe /t REG_DWORD /d 1 /f

"`nCVE-2017-5715..."
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" /v FeatureSettingsOverride /t REG_DWORD /d 0 /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" /v FeatureSettingsOverrideMask /t REG_DWORD /d 3 /f

"`nVCE-2017-5753-54..."
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization" /v MinVmVersionForCpuBasedMitigations /t REG_SZ /d "1.0" /f

"`nASLR Hardening Setting for IE..."
reg add "HKLM\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ALLOW_USER32_EXCEPTION_HANDLER_HARDENING" /v iexplore.exe /t REG_DWORD /d 1 /f
reg add "HKLM\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_ALLOW_USER32_EXCEPTION_HANDLER_HARDENING" /v iexplore.exe /t REG_DWORD /d 1 /f

"`nRemediate MS11-025 MFC Remote Code Execution..."
TryLoop -ScriptBlock {
$minVersion=14
$vcVersions=(Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | where {$_.displayname -like "Microsoft Visual C++*"} | Select-Object DisplayVersion)
foreach ($version in $vcVersions){
if($version.DisplayVersion -ge $minVersion){
$safeFlag=$True;
}
}
if (!($safeFlag)){
try{
New-Item -ItemType Directory -Force -Path C:\Temp # Create Temp folder if it doesn't already exist
(new-object System.Net.WebClient).DownloadFile('https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe','C:\Temp\vcredist_x64.exe')
C:\Temp\vcredist_x64.exe /quiet /norestart
}
catch{
fixProxy
}
}
} -Retries 2

"`nSecuring Remote Desktop..."
secureRDP;

try{"`nUpdating Windows Defender Antimalware Virus Definitions...";Update-MPSignature;}
catch{}

fixUnquotedServicePathEnum;
}

function checkNTKernel{
# This function needs to be upgraded to account for the different Build of Windows versions
# Assuming ([System.Environment]::OSVersion.Version).Build to be 14393

$kernelActualVersion=[System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Windows\system32\ntoskrnl.exe").ProductVersion
if($kernelActualVersion.length -lt 15){$kernelActualVersion+"0";}
$regexRemoveDots="\."
if ([double]($kernelActualVersion -replace $regexRemoveDots) -lt [double]($targetKernelVersion -replace $regexRemoveDots)){
"`nC:\Windows\system32\ntoskrnl.exe version $kernelActualVersion is older than the May 2019 Kernel $targetKernelVersion.";
$fixList.Add('updateNTKernel');
}
else{"NT Kernel is already $targetKernelVersion or greater.";}
}

function updateNTKernel{
if (!($haveInternet)){fixProxy;}

$kernelPatch="c:\temp\patch_$(get-date -f yyyy-MM-dd).msu";

if (!([System.IO.File]::Exists($kernelPatch))){
download -source $kernelDownload -destination $kernelPatch;
}

$updateKernel = Start-Job -Name "MyJobName" -ScriptBlock {
wusa.exe $patch /quiet /norestart;
}
Wait-Job -Job $updateKernel

"Kernel Update has been started in the background.";
}

function fixUnquotedServicePathEnum{
if (!($haveInternet)){fixProxy;}

<#
$fixScriptDownload="https://kimconnect.com/wp-content/uploads/2019/05/Windows_Path_Enumerate.zip"
$fixScriptDestination="C:\Temp\Windows_Path_Enumerate.zip"
$destination="C:\Temp"
(New-Object System.Net.WebClient).DownloadFile($fixScriptDownload, $fixScriptDestination)
expand-archive -path $fixScriptDestination -destinationpath $destination
C:\Temp\Windows_Path_Enumerate.ps1 -FixUninstall -FixEnv -WhatIf
#>

$fixScriptDestination="C:\Temp\Windows_Path_Enumerate.ps1"
$fixScriptDownload="https://gallery.technet.microsoft.com/scriptcenter/Windows-Unquoted-Service-190f0341/file/136821/7/Windows_Path_Enumerate.ps1"
(New-Object System.Net.WebClient).DownloadFile($fixScriptDownload, $fixScriptDestination)
C:\Temp\Windows_Path_Enumerate.ps1 -FixUninstall -FixEnv
}

function installLAPS{
if (!($haveInternet)){fixProxy;}

TryLoop -ScriptBlock{
$lapsInstalled=Get-ChildItem 'C:\Program Files\LAPS\CSE\Admpwd.dll'
if (!($lapsInstalled)){

Import-Module BitsTransfer
#Download Installation Files and trigger the install
New-Item -ItemType Directory -Force -Path C:\Temp # Create Temp folder if it doesn't already exist
$url = "https://download.microsoft.com/download/C/7/A/C7AAD914-A8A6-4904-88A1-29E657445D03/LAPS.x64.msi"
$output = "C:\Temp\LAPS.x64.msi"
download $url $output
C:\Temp\LAPS.x64.msi /quiet /norestart

}
else{
"Local Administrator Password Solution (LAPS) is already installed on this Windoze Komputer."
}
} -Retries 2
}

function setSNMP{
try{
"`nInstall SNMP Service, if necessary..."
Install-WindowsFeature 'SNMP-Service','RSAT-SNMP' -IncludeManagementTools
}catch{}

"`nCreate missing SNMP Key, if necessary..."
reg add "HKLM\System\CurrentControlSet\Services\snmp\parameters" /v TrapConfiguration /t REG_DWORD /d 1 /f

#Set managers
$count=$snmpHosts
foreach ($snmpHost in $snmpHosts) {
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\services\SNMP\Parameters\PermittedManagers" -Name $count -Value $snmpHost
$count--
}

#set community strings
foreach ($snmpCommunity in $snmpCommunities) {
#Translating Community Rights into decimal values
switch ($snmpCommunity.Rights) {
'Read Only' {
$value = 4
}
'Read Write' {
$value = 8
}
default {
throw "Unrecognized input: [$]"
}
}
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\services\SNMP\Parameters\ValidCommunities" -Name $snmpCommunity.Name -Value $value
}
}

function activateWindows{
# using cscript to call slmgr.vbs to suppress prompts
cscript //B "%windir%\system32\slmgr.vbs" /ipk $windowsLicense
cscript //B "%windir%\system32\slmgr.vbs" /ato
}

function checkIISCrypto{
$regHiveSSL30="Registry::HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server"
$regHiveTLS10="Registry::HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server"
$regHiveTLS11="Registry::HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server"
$regHiveTLS12="Registry::HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server"

$isSSL30Disabled = checkRegKey -Path $regHiveSSL30 -Name "Enabled" 0
$isTLS10Disabled = checkRegKey -Path $regHiveTLS10 -Name "Enabled" 0
$isTLS11Disabled = checkRegKey -Path $regHiveTLS11 -Name "Enabled" 0
$isTLS12Disabled = checkRegKey -Path $regHiveTLS12 -Name "Enabled" 0
$applyIISCrypto=$False;

If ($isSSL30Disabled) {"SSL 3.0 is Disabled";} Else {"SSL 3.0 is Enabled.`nRun applyIISCrypto to fix this.";$applyIISCrypto=$True;}
If ($isTLS10Disabled) {"TLS 1.0 is Disabled";} Else {"TLS 1.0 is Enabled.`nRun applyIISCrypto to fix this.";$applyIISCrypto=$True;}
If ($isTLS11Disabled) {"TLS 1.1 is Disabled";} Else {"TLS 1.1 is Enabled.`nRun applyIISCrypto to fix this.";$applyIISCrypto=$True;}
If ($isTLS12Disabled) {"TLS 1.2 is Disabled.`nRun applyIISCrypto to fix this.";} Else {"TLS 1.2 is Enabled";}
If([System.IO.File]::Exists("C:\Windows\IISCryptoCli.exe")){"IISCryptoCli is available."}else{"IISCryptoCli is not available at C:\Windows.`nRun installIISCrypto & applyIISCrypto to fix this.";$applyIISCrypto=$True;}

If ($applyIISCrypto){$fixList.Add('applyIISCrypto');}
}

function installIISCrypto{
TryLoop -ScriptBlock{
if($haveInternet){
# Download
$url = "https://kimconnect.com/wp-content/uploads/2019/05/IISCryptoCli.zip"
$temp = "C:\Temp\IISCryptoCli.zip"
download $url $temp

$destination="C:\Windows"
expand-archive -path $temp -destinationpath $destination

# New-Item -ItemType Directory -Force -Path C:\Temp # Create Temp folder if it doesn't already exist
# (new-object System.Net.WebClient).DownloadFile($url,$temp)

# Copy from a Intranet zone
# copy \\FILESERVER\Software\IISCryptoCli.exe C:\Windows
}
else{fixProxy;return $False}
} -Retries 2
}

function applyIISCrypto{
$templateValues="pci32","best","strict","fips140","default"
$count=$templateValues.length
for ($i=0; $i -lt $count; $i++) { $template=$templateValues[$i];"$i`: $template"}
$index=Read-Host -Prompt "Type in the Template Index NUMBER from 0 to $($count-1) to apply"
if ($index -lt $count){

$iisCryptoExist=([System.IO.File]::Exists("C:\Windows\IISCryptoCli.exe"))
if ($iisCryptoExist){
$choice=$templateValues[$index]
"`nBacking up registry into C:\backup.reg, and applying $choice template..."
IISCryptoCli /backup C:\backup.reg /template $choice;
"`nIISCrypto $choice template has been applied...`nPlease reboot machine for changes to take effect."
}
else{
"`nIISCryto wasn't installed. Retrying..."
installIISCripto;
applyIISCrypto;
}

}
else{
"Index number was not recognized. Thus, IISCrypto Template was NOT applied."
}
}

function cleanWindows{
"Clear Windows Update Cache..."
Dism.exe /online /Cleanup-Image /StartComponentCleanup

"Delete files in Temp directory..."
del C:\Temp\*.* -Recurse -Force

"Prune Event Logs..."
wevtutil el | Foreach-Object {wevtutil cl "$_"}

"Performing Disk Cleanup..."
$HKLM = [UInt32] "0x80000002"
$strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
$strValueName = "StateFlags0065"

$subkeys = gci -Path HKLM:\$strKeyPath -Name
ForEach ($subkey in $subkeys) {
New-ItemProperty -Path HKLM:\$strKeyPath\$subkey -Name $strValueName -PropertyType DWord -Value 2 -ErrorAction SilentlyContinue| Out-Null
Start-Process cleanmgr -ArgumentList "/sagerun:65" -Wait -NoNewWindow -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
}
ForEach ($subkey in $subkeys) {
Remove-ItemProperty -Path HKLM:\$strKeyPath\$subkey -Name $strValueName | Out-Null
}
}

# Syntax: checkRegKey $hive $key $value
function checkRegKey{
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$True)]
[string]$path,

[Parameter(Position=1, Mandatory=$True)]
[string]$name,

[Parameter(Position=2, Mandatory=$False)]
[string]$value=1
)

$val = Get-ItemProperty -Path $path -Name $key
if($val.$name -eq $value){return $True}
else{return $False}
}

function setRegKey{
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$True)]
[string]$path,

[Parameter(Position=1, Mandatory=$True)]
[string]$name,

[Parameter(Position=2, Mandatory=$True)]
[string]$value
)

Set-Itemproperty -path $path -Name $name -value $value
}

function secureRDP{
# These should have been done via Group Policy at this location
# Computer Configuration\Policies\Administrative Templates\Windows Components\Remote Desktop Services\Remote Desktop Session Host\Security
#
# References:
#
# .SetUserAuthenticationRequired(1) - https://msdn.microsoft.com/en-us/library/aa383441%28v=vs.85%29.aspx
# .SetEncryptionLevel(3) - https://msdn.microsoft.com/en-us/library/aa383800(v=vs.85).aspx
# .SetSecurityLayer(2) - https://msdn.microsoft.com/en-us/library/aa383801(v=vs.85).aspx
###############################################################################

# Remote Desktop Services: Enable NLA Requirement
#(Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").UserAuthenticationRequired
(Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(1)


# Remote Desktop Services: Require 'High' level of encryption - FIPS compliant
(Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").SetEncryptionLevel(4)

# Remote Desktop Services: Set Security Layer to SSL - If NLA has been set, Security Layer is out of scope and cannot be changed.
# (Get-WmiObject -class "Win32_TSGeneralSetting" -Namespace root\cimv2\terminalservices -Filter "TerminalName='RDP-tcp'").SetSecurityLayer(2)

}

function recommendations{
If ($fixList){
"These are the commended commands to fix this system:";
"--------------------------------------------------------";
$fixList;
}
Else{"This system has passed all checks. No further action is necessary.";}
}

$targetOS=Get-CimInstance Win32_Operatingsystem | select -expand Caption | select-string $regexTargetOS -AllMatches
if(!($targetOS)){
$thisOS=Get-CimInstance Win32_Operatingsystem | select -expand Caption
"This script is meant for Windows Server 2016, only.`nThis OS, '$thisOS' does not match that.`nExiting..."
$continue=Read-Host -Prompt "If you want to proceed anyway, enter [Y] or [yes]"
if ($continue.toLower() -eq "y" -or $continue.toLower() -eq "yes"){
cls
"Now Performing System Scan as triggered by script $script`:"
"`n----------------------------------------------------------`n"
scanSystem;
"`n----------------------------------------------------------`n"
recommendations;
"cleanupWindows when done.";
"`n----------------------------------------------------------`n"
}
else{break;}
}
else{
cls
"Now Performing System Scan as triggered by script $script`:"
"`n----------------------------------------------------------`n"
scanSystem;
"`n----------------------------------------------------------`n"
recommendations;
"cleanupWindows when done.";
"`n----------------------------------------------------------`n"
}

As of May 2019, there are errors with Windows Update where a certain roll-ups needed to be manually applied such as KB4494440. Here’s a manual workaround:

$KB4494440="http://windows10.0-kb4494440-x64_390f926659a23a56cc9cbb331e5940e132ad257d.msu"
$tempfile="C:\Temp\KB4494440.msu"
New-Item -ItemType Directory -Force -Path C:\Temp
(new-object System.Net.WebClient).DownloadFile($KB4494440,$tempfile)
wusa.exe -kb $tempfile /norestart /quiet

Another method to install specific KBs

$KBs = "KB4494440" 
Get-WUInstall -Type "Software" -KBArticleID $KBs -AcceptAll

Also, here is a script to install some useful system utilities

# Install Chocolatey if it's not already available
#$chocoInstalled=Test-Path -Path "$env:ProgramData\Chocolatey"

if (!(Get-Command choco.exe -ErrorAction SilentlyContinue)) {
# Install Chocolatey if Choco.exe yields negative
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

}

# Install commonly used packages
$packages='googlechrome','notepadplusplus.install','adobereader','7zip.install','javaruntime','putty.install','sysinternals'
ForEach ($package in $packages)
{
choco install $package -y
}

Consider this command clear Windows licensing dependencies prior to convert a VM into a Template

%WINDIR%\system32\sysprep\sysprep.exe /generalize /shutdown /oobe

Leave a Reply

Your email address will not be published. Required fields are marked *