Skip to content

Instantly share code, notes, and snippets.

@jason-bivins
Last active May 21, 2024 19:53
Show Gist options
  • Save jason-bivins/587f13c9e10901a975c33e4e88989503 to your computer and use it in GitHub Desktop.
Save jason-bivins/587f13c9e10901a975c33e4e88989503 to your computer and use it in GitHub Desktop.
AzureNotes
https://learn.microsoft.com/en-us/azure/virtual-machines/linux/tutorial-custom-images
#sysprep the VM after you configure it
Perform sysprep. To do so:
Delete C:\Windows\System32\Panther and empty the recycle bin
Remove-Item -Recurse -Force -Path "C:\Windows\System32\Panther"
Clear-RecycleBin -Force
DISM.exe /Online /Set-ReservedStorageState /State:Disabled
Set-Location "C:\Windows\System32\SysPrep"
.\sysprep.exe /oobe /generalize /shutdown /mode:vm
## if you get an error about pre-install packages see steps below
Remove-AppxPackage -Package MicrosoftCorporationII.WindowsSubsystemForLinux_2.0.14.0_x64__8wekyb3d8bbwe
Import-Module Appx
Import-Module Dism
Get-AppxPackage -AllUsers | Where PublisherId -eq 8wekyb3d8bbwe | Format-List -Property PackageFullName,PackageUserInformation
Get-AppxPackage -AllUsers | Format-List -Property PackageFullName,PackageUserInformation
Remove-AppxPackage -Package MicrosoftCorporationII.WindowsSubsystemForLinux_2.0.14.0_x64__8wekyb3d8bbwe
Remove-AppxPackage -Package CanonicalGroupLimited.Ubuntu_2204.3.49.0_x64__79rhkp1fndgsc
Remove-AppxProvisionedPackage -Online -PackageName
net localgroup users "nt authority\authenticated users" /add

Azure vm create quickstart

-- Treat Azure resources like containers. Create them, run your tasks and then delete them. pets vs cattle

-- The steps below are written using AZ cli so that commands work in most terminals and in the cloud portal terminal. You can install and use Azure powershell but syntax will be different

-- you can create Windows or Linux VMs but not Macs. You'll just need to change the authentication and the URN in your create command. I'm including Windows below, and will add Linux eventually


Install the az cli on your machine

  • Windows winget install -e --id Microsoft.AzureCLI

  • Mac brew update && brew install azure-cli

  • Linux curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash


Login to azure

  • note for Windows users: You'll need to go into WSL/Linux first. AZ cli likes a bash prompt. I use ubuntu, Open up cmd or powershell and type either wsl or <your-distro-name> ex: ubuntu

  • This command will open up your default browser and take you through azure authentication. az login


Part 1: Configure your resource group, network and security rules.

You only need to do this part once.

  1. Set variables for desired location and resource group name. Use az account list-locations to find the full list of available locations.

Main US ones are westus, centralus, eastus

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
  1. Create a resource group

az group create --name $resourcegroup --location $location

  1. Create a virtual network az network vnet create --name $vnet --resource-group $resourcegroup --address-prefix 10.0.0.0/16 --subnet-name default --subnet-prefixes 10.0.0.0/24

  2. Create a network security group

az network nsg create --resource-group $resourcegroup --name $nsg

  1. Create security group rules to control ports ports for network traffic. These are very basic for http,rdp and ssh. Feel free to add more.

az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleWeb --protocol tcp --priority 1001 --destination-port-range 80 --access allow

az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleRDP --protocol tcp --priority 1002 --destination-port-range 3389 --access allow

az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleSSH --protocol tcp --priority 1003 --destination-port-range 22 --access allow


Configure virtual machine options

Windows 11

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
vmname="<vmname>"
username="azureuser"
pwd=""
size="Standard_D4s_v3"
osdisksize=250
urn="MicrosoftWindowsDesktop:windows-11:win11-21h2-pro:22000.2416.230902"
#win10
#urn="Canonical:0001-com-ubuntu-pro-jammy:pro-22_04-lts-gen2:22.04.202305160"
#ubuntu
#urn="Canonical:0001-com-ubuntu-pro-jammy:pro-22_04-lts-gen2:22.04.202305160"

Windows 10

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
vmname="<vmname>"
username="azureuser"
pwd="Password1234567"
size="Standard_D4s_v3"
osdisksize=250
winurn="MicrosoftWindowsDesktop:Windows-10:win10-22h2-pro:19045.3448.230831"

Ubuntu 22.04 lts

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
vmname="<vmname>"
username="azureuser"
pwd="Password1234567"
size="Standard_D4s_v3"
osdisksize=250
winurn="Canonical:0001-com-ubuntu-pro-jammy:pro-22_04-lts-gen2:22.04.202305160"

winurn="MicrosoftWindowsDesktop:Windows-10:19h1-pron-gensecond:18362.1256.2012032308"

winurn="Canonical:0001-com-ubuntu-pro-jammy:pro-22_04-lts-gen2:22.04.202305160"

winurn="MicrosoftWindowsDesktop:Windows-10:win10-21h2-entn-ltsc:19044.2965.230505"

vmname="win10rc3" winurn="MicrosoftWindowsDesktop:Windows-10:win10-22h2-pro:19045.3448.230831"

az vm create --name $vmname -g $resourcegroup --image $winurn --public-ip-sku Standard --admin-username $username --admin-password $pwd --os-disk-size-gb $osdisksize --public-ip-address-dns-name $vmname --size $size --nsg $nsg --nic-delete-option delete --os-disk-delete-option delete --no-wait

az vm disk attach -g $resourcegroup --vm-name $vmname --name dataroot --new

az vm run-command invoke --command-id RunPowerShellScript --name $vmname -g $resourcegroup --scripts @windowsconfig.ps1

az vm delete --force-deletion y -g $resourcegroup -n $vmname --yes --no-wait

#win10

winurn="MicrosoftWindowsDesktop:Windows-10:win10-21h2-entn-ltsc:19044.2965.230505"

winurn="MicrosoftWindowsDesktop:Windows-10:win10-22h2-pro:19045.3448.230831"

winurn="MicrosoftWindowsDesktop:Windows-10:19h1-pron-gensecond:18362.1256.2012032308"

winurn="MicrosoftWindowsServer:WindowsServer:2022-datacenter-core:20348.1006.220908"

#Ubuntu

resourcegroup="jbivski" location="eastus2" nsg="jbivnsg" vmname="oldwsl" username="azureuser" pwd="Password1234567" size="Standard_D4s_v3" osdisksize=250 winurn="MicrosoftWindowsDesktop:windows-11:win11-21h2-pro:22000.2416.230902"

winurn="MicrosoftWindowsDesktop:Windows-10:19h1-pron-gensecond:18362.1256.2012032308"

winurn="Canonical:0001-com-ubuntu-pro-jammy:pro-22_04-lts-gen2:22.04.202305160"

az group create --name $resourcegroup --location $location

az network nsg create --resource-group $resourcegroup --name $nsg

az vm create --name $vmname -g $resourcegroup --image $winurn --public-ip-sku Standard --admin-username $username --admin-password $pwd --os-disk-size-gb $osdisksize --public-ip-address-dns-name $vmname --size $size --nsg $nsg --no-wait

az vm run-command invoke --command-id RunPowerShellScript --name $vmname -g $resourcegroup --scripts @windowsconfig.ps1

Cleanup

  • easiest way is to wipe the resource group completely - you can delete individual resources through the portal az group delete -n $resourcegroup --yes

az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleWeb --protocol tcp --priority 1001 --destination-port-range 80 --access allow

  • open up RDP az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleRDP --protocol tcp --priority 1002 --destination-port-range 3389 --access allow

az vm image list az vm image list --publisher RedHat --all | jq -r '.[].urn' az vm image list --publisher SUSE --all | jq -r '.[].urn' az vm image list --publisher Canonical --all | jq -r '.[].urn' >ubuntu.txt az vm image list --publisher CoreOS --all | jq -r '.[].urn' az vm image list --publisher MicrosoftWindowsServer --all | jq -r '.[].urn' > server.txt

az vm image list --publisher MicrosoftWindowsDesktop --all | jq -r '.[].urn' > desktop.txt

#tip to butt config. includes pre-reqs and stuff. will reboot twice
$ProgressPreference = 'SilentlyContinue'
# create working directory
New-Item -ItemType Directory -Force -Path C:\dockerconfig
Set-Location -Path c:\dockerconfig
Start-Transcript -Path config1.txt -Append -IncludeInvocationHeader
# Download latest DD from main channel
#https://desktop-stage.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe
Invoke-WebRequest -UseBasicParsing -Uri "https://desktop-stage.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe" -OutFile "Docker Desktop Installer.exe"
# download config files to run after reboot. I need to rethink this part
Invoke-WebRequest -UseBasicParsing -Uri "https://gist.github.com/jason-bivins/587f13c9e10901a975c33e4e88989503#file-windowssetup-ps1" -Outfile "windowssetup.ps1"
# Check for and enable system requirements
# hyper-v
$hyperVFeature = Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All -ErrorAction SilentlyContinue
if ($hyperVFeature.State -ne 'Enabled') {
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All -NoRestart
}
# containers:
$containersFeature = Get-WindowsOptionalFeature -Online -FeatureName containers -ErrorAction SilentlyContinue
if ($containersFeature.State -ne 'Enabled') {
Enable-WindowsOptionalFeature -Online -FeatureName containers -NoRestart
}
#virtual machine platform
$vmpFeature = Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -ErrorAction SilentlyContinue
if ($vmpFeature.State -ne 'Enabled') {
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart
}
#windows subsystem for linux
$mwslFeature = Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -ErrorAction SilentlyContinue
if ($mwslFeature.State -ne 'Enabled') {
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -NoRestart
}
$TaskName = "config"
$TaskDescription = "This task runs once and then deletes itself."
$TaskAction = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument "-ExecutionPolicy Bypass -File C:\dockerconfig\windowssetup.ps1"
$TaskTrigger = New-ScheduledTaskTrigger -AtStartup
$TaskPrincipal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType System -RunLevel Highest
Register-ScheduledTask -TaskName $TaskName -Description $TaskDescription -Action $TaskAction -Principal $TaskPrincipal -Trigger $TaskTrigger -Force
# stop loggin
Stop-Transcript
#Reboot
#Restart-Computer -Force

az vm image list-publishers --location eastus2 --output table

az vm image list-offers --location eastus2 --publisher MicrosoftWindowsDesktop --output table

az vm image list-skus --location eastus2 --publisher MicrosoftWindowsDesktop --offer Windows-10 --output table

az vm image list --location westus --publisher MicrosoftWindowsDesktop --offer Windows-10 --sku 19h2-pro --all --output table

az vm image show -l eastus2 --offer Windows-10 --publisher MicrosoftWindowsDesktop --sku 20h1-pro

after testing, clean up

If you have custom rules or storage or whatever, you can manually delete resources inside the resource group or the entire RG itself. You can also delete/manage any of this using the clicky clicky in the portal.

az vm delete --force-deletion y -g $resourcegroup -n $vmname --yes --no-wait

az vm image list --location eastus2 --publisher MicrosoftWindowsDesktop --offer Windows-10 --sku 20h1-pro --all --output table >images3.txt

az vm redeploy --resource-group $resourcegroup --name $vmname

rdp: brookeapitest.westus.cloudapp.azure.com u: brooketest p: Brooke!234567

resourcegroup="TempSupportVM" location="westus" vmname="BrookeAPITest" username="azureuser" pwd="Password1234567" size="Standard_D4s_v3" winurn="MicrosoftWindowsDesktop:windows-11:win11-22h2-pro:22621.1413.230310" nsg="BrookeAPITest"

az vm create --name $vmname -g $resourcegroup --image $winurn --public-ip-sku Standard --nic-delete-option delete --os-disk-delete-option delete --admin-username $username --admin-password $pwd --os-disk-size-gb 250 --public-ip-address-dns-name $vmname --size $size --nsg myNetworkSecurityGroup --no-wait --custom-data winstartup.ps1

20h2-pro az vm delete --resource-group $resourcegroup --name $vmname --force-deletion none -y

resourcegroup="jbiv" location="eastus2" vmname="newmon10" username="azureuser" pwd="Password1234567" size="Standard_D4s_v4" winurn="MicrosoftWindowsDesktop:Windows-10:win10-22h2-pro:19045.2728.230311"

az vm create --name $vmname -g $resourcegroup --image $winurn --public-ip-sku Standard --admin-username $username --admin-password $pwd --os-disk-size-gb 250 --public-ip-address-dns-name $vmname --size $size --nsg myNetworkSecurityGroup --no-wait

inurn="MicrosoftWindowsDesktop:Windows-10:win10-22h2-pro:19045.2728.230311"

az vm run-command invoke --command-id RunPowerShellScript --name $vmname -g $resourcegroup --scripts @winstartup.ps1

Azure vm create quickstart

-- Treat Azure resources like containers. Create them, run your tasks and then delete them. pets vs cattle

-- The steps below are written using AZ cli so that commands work in most terminals and in the cloud portal terminal. You can install and use Azure powershell but syntax will be different

-- you can create Windows or Linux VMs but not Macs. You'll just need to change the authentication and the URN in your create command. I'm including Windows below, and will add Linux eventually


Install the az cli on your machine

  • Windows winget install -e --id Microsoft.AzureCLI

  • Mac brew update && brew install azure-cli

  • Linux curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash


Login to azure

  • note for Windows users: You'll need to go into WSL/Linux first. AZ cli likes a bash prompt. I use ubuntu, Open up cmd or powershell and type either wsl or <your-distro-name> ex: ubuntu

  • This command will open up your default browser and take you through azure authentication. az login


Part 1: Configure your resource group, network and security rules.

You only need to do this part once.

  1. Set variables for desired location and resource group name. Use az account list-locations to find the full list of available locations.

Main US ones are westus, centralus, eastus

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
  1. Create a resource group

az group create --name $resourcegroup --location $location

  1. Create a virtual network az network vnet create --name $vnet --resource-group $resourcegroup --address-prefix 10.0.0.0/16 --subnet-name default --subnet-prefixes 10.0.0.0/24

  2. Create a network security group

az network nsg create --resource-group $resourcegroup --name $nsg

  1. Create security group rules to control ports ports for network traffic. These are very basic for http,rdp and ssh. Feel free to add more.

az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleWeb --protocol tcp --priority 1001 --destination-port-range 80 --access allow

az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleRDP --protocol tcp --priority 1002 --destination-port-range 3389 --access allow

az network nsg rule create --resource-group $resourcegroup --nsg-name $nsg --name RuleSSH --protocol tcp --priority 1003 --destination-port-range 22 --access allow


Configure virtual machine options

Windows 11

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
vmname="<vmname>"
username="azureuser"
pwd="Password1234567"
size="Standard_D4s_v3"
osdisksize=250
winurn="MicrosoftWindowsDesktop:windows-11:win11-21h2-pro:22000.2416.230902"

Windows 10

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
vmname="<vmname>"
username="azureuser"
pwd="Password1234567"
size="Standard_D4s_v3"
osdisksize=250
winurn="MicrosoftWindowsDesktop:Windows-10:win10-22h2-pro:19045.3448.230831"

Ubuntu 22.04 lts

resourcegroup="<rg name>"
location="<location>"
vnet="<virtual network name>"
nsg="<nsg name>"
vmname="<vmname>"
username="azureuser"
pwd="Password1234567"
size="Standard_D4s_v3"
osdisksize=250
winurn="Canonical:0001-com-ubuntu-pro-jammy:pro-22_04-lts-gen2:22.04.202305160"

Ubuntu test machine setup guide

Walks you through:

  • Creating an ubuntu VM in azure
  • Installing a GUI and reconnecting via RDP
  • Installing sys reqs for Docker Desktop
  • Installing Docker Desktop

Create an ubuntu VM using az cli

  • Set VM parameters
  • I'm using password instead of SSH keys because we ultimately want RDP connection. If you use SSH, you have to create the uname/pwd anyway for RDP
resourcegroup="jbivski"
location="eastus2"
nsg="jbivnsg"
vmname="bun451test"
username="azureuser"
pwd="Password1234567"
size="Standard_D4s_v3"
osdisksize=250
urn="Canonical:0001-com-ubuntu-confidential-vm-jammy:22_04-lts-cvm:22.04.202304260"
  • Create the VM
az vm create --name $vmname -g $resourcegroup  --image $urn --public-ip-sku Standard --admin-username $username --admin-password $pwd --os-disk-size-gb $osdisksize --public-ip-address-dns-name $vmname --size $size --nsg $nsg --no-wait
  • will add the cloudinit script later (havent written one I like yet)

Install a GUI in ubuntu

https://learn.microsoft.com/en-us/azure/virtual-machines/linux/use-remote-desktop?tabs=azure-cli

  • Connect to the vm using ssh ssh azureuser@VMNAME.eastus2.cloudapp.azure.com

  • (Optional but probably required) Update the machine's kernel and OS.

sudo apt-get update && sudo apt-get dist-upgrade && sudo apt-get autoremove && sudo apt-get autoclean sudo reboot

  • Install xfce and xrdp
sudo apt-get update;
sudo DEBIAN_FRONTEND=noninteractive apt-get -y install xfce4;
sudo apt install xfce4-session;
sudo apt-get -y install xrdp;
sudo systemctl enable xrdp;
sudo adduser xrdp ssl-cert;
echo xfce4-session >~/.xsession
sudo reboot
  • Reconnect to the VM using RDP (port 3389 must be open in your NSG)

Install Desktop system requirements

https://docs.docker.com/desktop/install/linux-install/#system-requirements

  • minimum required extensions and tools
sudo apt-get update -y;
sudo apt-get install -y gnome-shell-extension-appindicator;
sudo apt-get install -y chromium-browser;
sudo apt install gnome-terminal
  • make sure KVM support is enabled. you need to see a 1 besides one of the KVM's listed

lsmod | grep kvm

  • add your user to the kvm group to access virtualization

sudo usermod -aG kvm $USER

Install docker repository and desktop.

sudo apt-get update -y
sudo apt-get install ca-certificates curl gnupg
  • Add Docker’s official GPG key and set up the repository:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  • Download the desired deb package https://desktop.docker.com/linux/main/amd64/docker-desktop-4.18.0-amd64.deb?utm_source=docker&utm_medium=webreferral&utm_campaign=docs-driven-download-linux-amd64

  • Install with apt

sudo apt-get update -y
#cd to the file download location
sudo apt-get install ./docker-desktop-<version>-<arch>.deb

Ignore N: Download is performed unsandboxed as root as file '/home/azureuser/Downloads/docker-desktop-4.19.0-amd64.deb' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)

  • Launch Desktop (seems to want a reboot first, or for the engine to be manually started)

systemctl --user start docker-desktop

  • you can also use the Applications > Development menu to launch using the GUI
$ProgressPreference='SilentlyContinue'
New-Item -ItemType Directory -Force -Path C:\dockerconfig
Set-Location -Path c:\dockerconfig
Start-Transcript -Path config1.txt -Append
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart
Enable-WindowsOptionalFeature -Online -FeatureName containers -NoRestart
Invoke-WebRequest -Uri https://aka.ms/wslubuntu2004 -OutFile Ubuntu2004.appx -UseBasicParsing
Invoke-WebRequest -Uri https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe -OutFile DockerDesktopInstaller.exe -UseBasicParsing
Invoke-Webrequest -Uri https://gist.githubusercontent.com/jason-bivins/587f13c9e10901a975c33e4e88989503/raw/2b22f2077c3602f95f638123dd57954493f5da6c/config2.ps1 -OutFile config2.ps1 -UseBasicParsing
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
choco feature enable -n allowGlobalConfirmation
choco install firefox
#choco install googlechrome
#choco install docker-desktop
choco install sysinternals
schtasks /create /tn "basics" /sc onstart /delay 0000:30 /rl highest /ru system /tr C:\dockerconfig\config2.ps1
Stop-Transcript
Restart-Computer -Force
$ProgressPreference = 'SilentlyContinue'
Set-Location -Path c:\dockerconfig
Start-Transcript -Path config2.txt -Append -IncludeInvocationHeader
Write-Host "this might take a minute, the machine will reboot when the process completes" -ForegroundColor Magenta
# remove the startup install task
$TaskName = "RunDockerSetup"
$task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
if ($task) {
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false
} else {
Write-Host "Task '$TaskName' not found."
}
# Stop the Docker service if exists, and any running processes
$serviceName = "com.docker.service"
if (Get-Service -Name $serviceName -ErrorAction SilentlyContinue) {
Stop-Service -Name $serviceName -Force
Write-Host "Docker service stopped."
} else {
Write-Host "Docker service not found."
}
Get-Process | Where-Object { $_.ProcessName -like "*docker*" } | Stop-Process -Force
Write-Host "All Docker processes ended."
#Install DD
Start-Process '.\Docker Desktop Installer.exe' -ArgumentList 'install --quiet --accept-license --always-run-service' -Wait
#Install Choco
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
#install good stuff using choco
choco feature enable -n allowGlobalConfirmation
choco install vscode
choco install git
choco install gh
choco install sysinternals
choco install firefox
choco install googlechrome
choco install github-desktop
# pull latest windows updates
# Check for, download, and install Windows Updates repeatedly until no more are found
do {
$UpdateSession = New-Object -ComObject Microsoft.Update.Session
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
$SearchResult = $UpdateSearcher.Search("IsInstalled=0")
$UpdatesCount = $SearchResult.Updates.Count
Write-Output "Updates found: $UpdatesCount"
if ($UpdatesCount -gt 0) {
$UpdatesToDownload = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($Update in $SearchResult.Updates) {
$UpdatesToDownload.Add($Update) | Out-Null
}
$Downloader = $UpdateSession.CreateUpdateDownloader()
$Downloader.Updates = $UpdatesToDownload
$DownloadResult = $Downloader.Download()
Write-Output "Download Result: $($DownloadResult.ResultCode)"
$UpdatesToInstall = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($Update in $SearchResult.Updates) {
$UpdatesToInstall.Add($Update) | Out-Null
}
$Installer = $UpdateSession.CreateUpdateInstaller()
$Installer.Updates = $UpdatesToInstall
$InstallationResult = $Installer.Install()
Write-Output "Installation Result: $($InstallationResult.ResultCode)"
if ($InstallationResult.RebootRequired) {
Write-Output "A reboot is required to complete the update installation."
}
}
} while ($UpdatesCount -gt 0)
Write-Output "No more Windows Updates found. Proceeding with system reboot."
# stop the log
Stop-Transcript
#reboot
Restart-Computer -Force
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment