Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/scriptAnalyzer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ on:
- master
paths:
- "**/*.ps1"
- "**/*.psm1"
push:
paths:
- "**/*.ps1"
- "**/*.psm1"

permissions:
contents: read # Needed to check out the code
Expand All @@ -26,7 +28,8 @@ jobs:
- name: Run PSScriptAnalyzer
run: |
# Run PSScriptAnalyzer on all PowerShell scripts
$results = Get-ChildItem -Recurse -Filter *.ps1 | Invoke-ScriptAnalyzer
$results = @(Get-ChildItem -Recurse -Filter *.ps1 | Invoke-ScriptAnalyzer)
$results += @(Get-ChildItem -Recurse -Filter *.psm1 | Invoke-ScriptAnalyzer)
if ($results) {
Write-Output $results | Format-List -GroupBy ScriptName
}
Expand Down
193 changes: 193 additions & 0 deletions Tools/Build-MinWinVHD.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# ================================
# Minimal Windows 11 VHDX Builder
# ================================
# Run as Administrator

#Requires -Version 5.1
#Requires -RunAsAdministrator
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'This script is not intended to have any outputs piped')]

param
(
[Parameter(
Mandatory = $true,
HelpMessage = 'Drive letter where Windows 11 ISO is mounted (e.g., D:)'
)] [string] $IsoDrive = 'D:',
[Parameter(
Mandatory = $true,
HelpMessage = 'Index of the Windows 11 edition to install from the image (use /Get-ImageInfo to check)'
)] [ValidateRange(1, 10)] [int] $ImageIndex = 1,
[Parameter(
Mandatory = $true,
HelpMessage = 'Path to create the VHDX file (e.g., C:\MinWin11.vhdx)'
)] [string] $VhdPath = 'C:\MinWin11.vhdx',
[Parameter(
Mandatory = $false,
HelpMessage = 'Size of the VHDX in GB'
)] [ValidateRange(20, [int]::MaxValue)] [int] $VhdSizeGB = 25,
[Parameter(
Mandatory = $false,
HelpMessage = 'Name of the Hyper-V VM to create (optional)'
)] [string] $VmName = 'MinWin11'
)

Write-Host '=== Step 0: Prepare paths and image info ===' -ForegroundColor Cyan

# Determine install.wim or install.esd path
$InstallWim = Join-Path $IsoDrive 'sources\install.wim'
if (-not (Test-Path $InstallWim)) {
$InstallWim = Join-Path $IsoDrive 'sources\install.esd'
}

# Verify image file exists
if (-not (Test-Path $InstallWim)) {
throw "Cannot find install.wim or install.esd on $IsoDrive. Mount a Windows 11 ISO and update `\$IsoDrive`."
}

Write-Host "Using image file: $InstallWim" -ForegroundColor Yellow

Write-Host '=== Step 1: Create and initialize VHDX ===' -ForegroundColor Cyan

# Create VHDX
New-VHD -Path $VhdPath -SizeBytes ("${VhdSizeGB}GB") -Dynamic | Out-Null

# Mount and initialize
$disk = Mount-VHD -Path $VhdPath -Passthru
Initialize-Disk -Number $disk.Number -PartitionStyle GPT | Out-Null

# Create EFI + OS partitions
$efiPartition = New-Partition -DiskNumber $disk.Number -Size 100MB -GptType '{C12A7328-F81F-11D2-BA4B-00A0C93EC93B}' -AssignDriveLetter
$osPartition = New-Partition -DiskNumber $disk.Number -UseMaximumSize -AssignDriveLetter

# Format partitions
Format-Volume -Partition $efiPartition -FileSystem FAT32 -NewFileSystemLabel 'System' -Confirm:$false | Out-Null
Format-Volume -Partition $osPartition -FileSystem NTFS -NewFileSystemLabel 'Windows' -Confirm:$false | Out-Null

$EfiDrive = ($efiPartition | Get-Volume).DriveLetter + ':'
$OsDrive = ($osPartition | Get-Volume).DriveLetter + ':'

Write-Host "EFI drive: $EfiDrive OS drive: $OsDrive" -ForegroundColor Yellow


Write-Host '=== Step 2: Apply Windows image to OS partition ===' -ForegroundColor Cyan

# If using ESD, DISM can still apply directly
dism /Apply-Image /ImageFile:$InstallWim /Index:$ImageIndex /ApplyDir:$OsDrive | Out-Null


Write-Host '=== Step 3: Basic boot configuration ===' -ForegroundColor Cyan

# Create boot files on EFI partition
bcdboot "$OsDrive\Windows" /s $EfiDrive /f UEFI | Out-Null


Write-Host '=== Step 4: Mount offline image for servicing ===' -ForegroundColor Cyan

# Mount the OS volume as an offline image for DISM servicing
$MountDir = 'D:\Mount_MinWin11'
if (-not (Test-Path $MountDir)) {
New-Item -ItemType Directory -Path $MountDir | Out-Null
}

# Use DISM to mount the offline image
dism /Mount-Image /ImageFile:$InstallWim /Index:$ImageIndex /MountDir:$MountDir /ReadOnly | Out-Null

# NOTE:
# We will service the *applied* OS at $OsDrive, not the ISO image.
# For feature removal, we target the offline OS with /Image:$OsDrive not /Image:$MountDir.

Write-Host '=== Step 5: Remove optional features (offline) ===' -ForegroundColor Cyan

# You can see available features with:
# dism /Image:$OsDrive /Get-Features

# Aggressive feature removal list (adjust to taste)
$featuresToDisable = @(
'FaxServicesClientPackage',
'Printing-Foundation-Features',
'Printing-PrintToPDFServices-Features',
'Printing-XPSServices-Features',
'MSRDC-Infrastructure',
'Microsoft-Windows-Subsystem-Linux',
'MediaPlayback' ,
'WindowsMediaPlayer',
'WorkFolders-Client',
'SMB1Protocol',
'WCF-Services45',
'WCF-TCP-PortSharing45',
'IIS-WebServerRole',
'IIS-WebServer',
'IIS-DefaultDocument',
'IIS-DirectoryBrowsing',
'IIS-HttpErrors',
'IIS-StaticContent',
'IIS-HttpRedirect',
'IIS-ApplicationDevelopment',
'IIS-ISAPIExtensions',
'IIS-ISAPIFilter',
# "IIS-NetFxExtensibility45",
'IIS-ASPNET45',
'IIS-HealthAndDiagnostics',
'IIS-HttpLogging',
'IIS-LoggingLibraries',
'IIS-RequestMonitor',
'IIS-HttpTracing',
'IIS-Security',
'IIS-RequestFiltering',
'IIS-IPSecurity',
'IIS-Performance',
'IIS-HttpCompressionStatic',
'IIS-WebServerManagementTools',
'IIS-IIS6ManagementCompatibility',
'IIS-Metabase',
'IIS-HostableWebCore'
)

foreach ($feature in $featuresToDisable) {
Write-Host "Disabling feature: $feature" -ForegroundColor DarkYellow
dism /Image:$OsDrive /Disable-Feature /FeatureName:$feature /Remove | Out-Null
}

Write-Host '=== Step 6: Remove provisioned apps (offline) ===' -ForegroundColor Cyan

# Remove all provisioned appx packages except Store and framework (adjust as needed)
$ProvisionedApps = dism /Image:$OsDrive /Get-ProvisionedAppxPackages | Select-String 'PackageName'
foreach ($line in $ProvisionedApps) {
$pkg = $line.ToString().Split(':')[1].Trim()
if ($pkg -notlike '*Store*' -and $pkg -notlike '*NET*' -and $pkg -notlike '*AppInstaller*') {
Write-Host "Removing provisioned app: $pkg" -ForegroundColor DarkYellow
dism /Image:$OsDrive /Remove-ProvisionedAppxPackage /PackageName:$pkg | Out-Null
}
}

Write-Host '=== Step 7: WinSxS cleanup and image optimization ===' -ForegroundColor Cyan

# Component store cleanup to reduce size
dism /Image:$OsDrive /Cleanup-Image /StartComponentCleanup /ResetBase | Out-Null

Write-Host '=== Step 8: Unmount temporary mount and clean up ===' -ForegroundColor Cyan

# Unmount DISM image
dism /Unmount-Image /MountDir:$MountDir /Discard | Out-Null
# Remove mount directory
Remove-Item $MountDir -Recurse -Force | Out-Null

# Dismount VHD (you can leave it mounted if you want to inspect it)
Dismount-VHD -Path $VhdPath

Write-Host '=== Step 9: (Optional) Create a Hyper-V VM using this VHDX ===' -ForegroundColor Cyan

# Create a Hyper-V VM if Hyper-V module is available
if (Get-Command New-VM -ErrorAction SilentlyContinue) {
if (-not (Get-VM -Name $VmName -ErrorAction SilentlyContinue)) {
New-VM -Name $VmName -MemoryStartupBytes 2GB -Generation 2 -VHDPath $VhdPath | Out-Null
Set-VMFirmware -VMName $VmName -FirstBootDevice (Get-VMFirmware -VMName $VmName).BootOrder[0]
Write-Host "Created Hyper-V VM '$VmName' using $VhdPath" -ForegroundColor Green
} else {
Write-Host "Hyper-V VM '$VmName' already exists. Attach $VhdPath manually if needed." -ForegroundColor Yellow
}
} else {
Write-Host "Hyper-V module not available. Create a VM manually and attach $VhdPath." -ForegroundColor Yellow
}

Write-Host "=== DONE. Minimal Windows 11 VHDX created at $VhdPath ===" -ForegroundColor Green
96 changes: 96 additions & 0 deletions doc/tools/Build-MinWinVHD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Using Build-MinWin11.ps1

The [Build-MinWinVHD.ps1](Tools/Build-MinWinVHD.ps1) script creates a new `V`irtual `H`ard `D`isk (VHD) using a mounted Windows ISO for use with a virtual machine. This image will have as few dependencies and apps enabled as possible, to provide the best approximation of the images uses by the validation pipelines. Although this is not the same image, it should be close enough to use for testing manifests for those who are unable to use Windows Sandbox and [SandboxTest.ps1](doc/tools/SandboxTest.ps1).

## Summary

This script creates a dynamically sized VHDX, initializes GPT partitions (EFI + OS), applies a Windows image from a mounted ISO, configures basic UEFI boot, services the offline image (removes features / provisioned apps), and optionally creates a Hyper-V VM using the VHDX.

Check warning on line 7 in doc/tools/Build-MinWinVHD.md

View workflow job for this annotation

GitHub Actions / Check Spelling

`UEFI` is not a recognized word. (unrecognized-spelling)

Check warning on line 7 in doc/tools/Build-MinWinVHD.md

View workflow job for this annotation

GitHub Actions / Check Spelling

`GPT` is not a recognized word. (unrecognized-spelling)

Check warning on line 7 in doc/tools/Build-MinWinVHD.md

View workflow job for this annotation

GitHub Actions / Check Spelling

`VHDX` is not a recognized word. (unrecognized-spelling)

Check warning on line 7 in doc/tools/Build-MinWinVHD.md

View workflow job for this annotation

GitHub Actions / Check Spelling

`UEFI` is not a recognized word. (unrecognized-spelling)

Check warning on line 7 in doc/tools/Build-MinWinVHD.md

View workflow job for this annotation

GitHub Actions / Check Spelling

`GPT` is not a recognized word. (unrecognized-spelling)

Check warning on line 7 in doc/tools/Build-MinWinVHD.md

View workflow job for this annotation

GitHub Actions / Check Spelling

`VHDX` is not a recognized word. (unrecognized-spelling)

## Prerequisites

- **Run as Administrator:** The script must be executed from an elevated PowerShell session.
- **PowerShell version:** Requires PowerShell 5.1 or newer due to use of built-in cmdlets and DISM commands.
- **Windows ISO downloaded and mounted:** Mount the Windows 11 ISO (right-click -> Mount, or use `Mount-DiskImage`) and note the assigned drive letter (e.g., `D:`). ISO images can be downloaded from the official Microsoft page: https://www.microsoft.com/software-download/windows11
- **DISM and bcdboot:** The script uses the built-in `dism` and `bcdboot` utilities. Ensure these commands are present on your path.
- **Hyper-V (optional):** If the Hyper-V module is available and you want a VM created automatically, ensure Hyper-V is enabled and that you can manually create a new VM.

> [!IMPORTANT]
> The script includes an "aggressive" list of features and provisioned app removals. Review the script before running if you need specific Windows features or provisioned packages preserved.

## Parameters

| Argument | Description | Required | Default |
|------------------------------|-----------------------------------------------------------------------------|:--------:|:-------:|
| **-IsoDrive** | Drive letter where the Windows ISO is mounted (string). Example: D:. | true | — |
| **-ImageIndex** | Index of the Windows image within `install.wim` or `install.esd` (int). Use DISM to list available indexes (for example `dism /Get-WimInfo /WimFile:D:\sources\install.wim`). | true | — |
| **-VhdPath** | Full path to create the VHDX file (string). Example: `C:\MinWin11.vhdx`. | true | — |
| **-VhdSizeGB** | Size of the VHDX in GB (int). | false | 25 |
| **-VmName** | Name of the Hyper-V VM to create (string). | false | MinWin11 |

## How to determine image index

Use DISM to list images in the WIM/ESD on the mounted ISO. Replace `D:` with your ISO drive letter:

```powershell
# For WIM
dism /Get-WimInfo /WimFile:D:\sources\install.wim

# For ESD (DISM supports reading ESD similarly)
dism /Get-ImageInfo /ImageFile:D:\sources\install.esd
```

Look for the `Index :` value you want to apply (for example, 1 for the first edition).

## Basic usage examples

Open an elevated PowerShell prompt and run (example values shown):

```powershell
# From the Tools folder
cd <path-to-repo>\Tools

# Basic: create a 25GB dynamic VHDX from the image at D:, using index 1
.\Build-MinWin11.ps1 -IsoDrive D: -ImageIndex 1 -VhdPath C:\MinWin11.vhdx

# With custom size and VM name
.\Build-MinWin11.ps1 -IsoDrive D: -ImageIndex 2 -VhdPath C:\MinWin11.vhdx -VhdSizeGB 40 -VmName "MyMinWin11"
```

## What the script does (high level)

- Locates `install.wim` or `install.esd` on the mounted ISO at `\sources`.
- Creates a dynamic VHDX at the path provided (`-VhdPath`) and mounts it.
- Initializes the disk as GPT and creates a 100MB EFI partition and the remaining OS partition.
- Formats the partitions (EFI = FAT32, OS = NTFS).
- Applies the Windows image to the OS partition using `dism /Apply-Image`.
- Creates UEFI boot files with `bcdboot`.
- Mounts an offline copy of the image for servicing and removes a predefined list of optional features and provisioned appx packages (see script for the removal list).
- Runs component-store cleanup (`/StartComponentCleanup /ResetBase`) to reduce size.
- Dismounts VHD and optionally creates a Hyper-V VM named `-VmName` if the Hyper-V cmdlets are present.

## Output

- A VHDX file at the path specified by `-VhdPath` (e.g., `C:\MinWin11.vhdx`).
- If Hyper-V is available and `-VmName` does not exist, a new Gen 2 VM is created and attached to the VHDX.

## Warnings & tips

- The script will throw an error if it cannot locate `install.wim` or `install.esd` in the ISO `sources` folder.
- Review and edit the features/provisioned-app removal lists in the script before running in production environments — the defaults are aggressive and intended for minimal builds.
- If you prefer to inspect the VHD before dismounting, modify the script or run the VHD mounting steps manually.
- Ensure sufficient free space on the volume where `-VhdPath` is located.

## Troubleshooting

- If the ISO is not mounted as a drive letter, use `Mount-DiskImage -ImagePath "C:\path\to\Win11.iso"` and then run `Get-Volume` or check Explorer to find the assigned drive letter.
- If `dism /Apply-Image` fails, verify the `-ImageIndex` value, and confirm whether the image file is `install.wim` or `install.esd`.
- If Hyper-V VM creation fails, verify the `Hyper-V` Windows feature is enabled and that you are running elevated PowerShell.

## Using with other VM Providers

- The produced VHDX (`C:\MinWin11.vhdx`) can be used with other hypervisors, but many providers require a different disk format; convert the VHDX to the format your provider expects before attaching.
- QEMU/KVM: convert to `qcow2` with `qemu-img convert -O qcow2`.
- VMware: convert to `vmdk` with `qemu-img convert -O vmdk` (or use VMware tools if available).
- VirtualBox: use `VBoxManage clonemedium disk --format VDI` or convert with `qemu-img` to `vdi`/`vmdk` as needed.
- Before converting, ensure the VHDX is dismounted and not in use. After conversion, attach the converted disk to a VM configured for UEFI/GPT (Gen2/EFI) and the appropriate disk controller.
- Expect to install or enable guest additions/tools for the target hypervisor and verify drivers (network, storage) inside the guest; hardware differences may require small post-boot fixes.
20 changes: 20 additions & 0 deletions manifests/c/CPUID/HWMonitor/1.61/CPUID.HWMonitor.installer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Created with YamlCreate.ps1 Dumplings Mod
# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.10.0.schema.json

PackageIdentifier: CPUID.HWMonitor
PackageVersion: "1.61"
InstallerLocale: en-US
InstallerType: inno
Scope: machine
UpgradeBehavior: install
ProductCode: CPUID HWMonitor_is1
ReleaseDate: 2025-12-26
ElevationRequirement: elevatesSelf
InstallationMetadata:
DefaultInstallLocation: '%ProgramFiles%\CPUID\HWMonitor'
Installers:
- Architecture: x86
InstallerUrl: https://download.cpuid.com/hwmonitor/hwmonitor_1.61.exe
InstallerSha256: 604E2F00D7571FAB62ACFE0E71E9E3D09F49D812CFB5C34B542A652F6D0C086D
ManifestType: installer
ManifestVersion: 1.10.0
50 changes: 50 additions & 0 deletions manifests/c/CPUID/HWMonitor/1.61/CPUID.HWMonitor.locale.en-US.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Created with YamlCreate.ps1 Dumplings Mod
# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.10.0.schema.json

PackageIdentifier: CPUID.HWMonitor
PackageVersion: "1.61"
PackageLocale: en-US
Publisher: CPUID, Inc.
PublisherUrl: https://www.cpuid.com/
PublisherSupportUrl: https://www.cpuid.com/contact.html
PrivacyUrl: https://www.cpuid.com/privacy-policy.html
Author: CPUID, Inc.
PackageName: CPUID HWMonitor
PackageUrl: https://www.cpuid.com/softwares/hwmonitor.html
License: Freeware
LicenseUrl: https://www.cpuid.com/softwares/hwmonitor-pro/eula.html
Copyright: Copyright © CPUID - 2025
CopyrightUrl: https://www.cpuid.com/softwares/hwmonitor-pro/eula.html
ShortDescription: Voltages, temperatures and fans speed monitoring
Description: |-
HWMonitor for Windows® x86/x64 is a hardware monitoring program that reads PC systems main health sensors : voltages, temperatures, powers, currents, fans speed, utilizations, clock speeds ...

The program handles :
- CPU and GPU-level hardware monitoring
- LPCIO chips with monitoring features (ITE® IT87 series, Winbond® and Nuvoton® ICs)
- memory modules with thermal sensors
- SSD / hard disks via S.M.A.R.T.
- batteries
- and more ...
Moniker: hwmonitor
Tags:
- cpu
- fan-speed
- gpu
- hard-drive
- hardware
- hardware-monitoring
- monitor
- sensor
- temerature-monitoring
- temps
- thermal
- utility
ReleaseNotes: |-
- AMD Ryzen 7 9850X3D (Granite Ridge).
- AMD Ryzen 5 7500X3D (Raphael).
- Preliminary support of AMD Medusa Point.
- Intel Core Ultra 9 290K Plus, Ultra 7 270K Plus and Ultra 5 250K Plus (Arrow Lake Refresh).
ReleaseNotesUrl: https://www.cpuid.com/softwares/hwmonitor.html#version-history
ManifestType: defaultLocale
ManifestVersion: 1.10.0
Loading
Loading