Incident
Law firm with 85 workstations, critical security patches that had to ship that week, and partners who bill in six-minute increments and lose their minds if a patch restart interrupts a redline. We scheduled the maintenance window for 2 AM to stay out of everybody's way. Morning-after report came in: 34 of 85 machines patched. The rest never phoned home because they were either powered off at the wall or asleep under the desk, and the RMM agent has no way to wake a machine that isn't online.
The challenge
Fleet was mixed vendor, which is where WoL gets annoying. Wake-on-LAN has two layers: the BIOS has to be configured to allow wake packets, and Windows has to be configured to let the NIC respond to them. Each vendor exposes BIOS settings differently, and none of them let you touch the BIOS through a regular Windows session without a vendor-specific tool. Doing 85 machines by hand with F2 at boot would have been a week of after-hours work.
- Dell OptiPlex: 45 machines
- HP EliteDesk: 28 machines
- Lenovo ThinkCentre: 12 machines
- WoL status: unknown across the fleet
Solution
We built one script that auto-detects the manufacturer via Win32_ComputerSystem and calls the right vendor tooling for each. Dell gets the DellBIOSProvider PowerShell module. HP gets the HP Client Management Script Library (CMSL). Lenovo gets direct WMI calls against the Lenovo_SetBiosSetting class. After BIOS is handled, the script configures Windows-side wake on all physical NICs using the MSPower_DeviceWakeEnable WMI class and enables the matching "Allow this device to wake the computer" and "Only allow a magic packet to wake the computer" settings.
$ErrorActionPreference = 'Stop'
<#
██╗ ██╗███╗ ███╗███████╗██╗ ██╗ █████╗ ██╗ ██╗██╗ ██╗
██║ ██║████╗ ████║██╔════╝██║ ██║██╔══██╗██║ ██║██║ ██╔╝
██║ ██║██╔████╔██║█████╗ ███████║███████║██║ █╗ ██║█████╔╝
██║ ██║██║╚██╔╝██║██╔══╝ ██╔══██║██╔══██║██║███╗██║██╔═██╗
███████╗██║██║ ╚═╝ ██║███████╗██║ ██║██║ ██║╚███╔███╔╝██║ ██╗
╚══════╝╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝
================================================================================
SCRIPT : Wake-on-LAN Enable v1.0.3
AUTHOR : Limehawk.io
DATE : January 2026
USAGE : .\wol_enable.ps1
================================================================================
FILE : wol_enable.ps1
DESCRIPTION : Enables Wake-on-LAN settings for Ethernet adapters
--------------------------------------------------------------------------------
README
--------------------------------------------------------------------------------
PURPOSE
Enables Wake-on-LAN (WOL) in both BIOS/UEFI and Windows NIC settings.
Supports Dell, HP, and Lenovo systems with manufacturer-specific BIOS modules.
Also enables WOL on all capable network adapters in Windows.
DATA SOURCES & PRIORITY
1) System manufacturer detection (CIM)
2) Manufacturer-specific BIOS modules (Dell, HP, Lenovo)
3) Windows NIC WOL settings (CIM)
REQUIRED INPUTS
None - script auto-detects manufacturer and configures accordingly.
SETTINGS
- Dell: Uses DellBIOSProvider module, sets WakeOnLan to "LANOnly"
- HP: Uses HPCMSL module, sets Wake On Lan to "Boot to Hard Drive"
- Lenovo: Uses WMI, sets WakeOnLAN to "Primary"
- Windows: Enables MSPower_DeviceWakeEnable on all capable NICs
BEHAVIOR
1. Checks/installs required PowerShell modules (NuGet, PSGallery)
2. Detects system manufacturer
3. Installs manufacturer-specific BIOS module if needed
4. Configures BIOS WOL setting
5. Enables WOL on all capable Windows NICs
PREREQUISITES
- Windows 10/11
- Admin privileges required
- Internet connectivity for module installation
- Supported manufacturer: Dell, HP, or Lenovo
SECURITY NOTES
- No secrets in logs
- Modifies BIOS settings (requires admin)
- Installs PowerShell modules from PSGallery
EXIT CODES
- 0: Success
- 1: Warning (rerun required after PowerShellGet update)
- Other: Manufacturer not supported or error
EXAMPLE RUN
[INFO] SYSTEM DETECTION
==============================================================
Manufacturer : Dell Inc.
[RUN] BIOS CONFIGURATION
==============================================================
Installing DellBIOSProvider module...
Setting WakeOnLan to LANOnly...
BIOS WOL configured successfully
[RUN] NIC CONFIGURATION
==============================================================
Enabling WOL for Intel(R) Ethernet...
NIC WOL enabled successfully
[OK] RESULT
==============================================================
Status : Success
[OK] SCRIPT COMPLETE
==============================================================
--------------------------------------------------------------------------------
CHANGELOG
--------------------------------------------------------------------------------
2026-01-19 v1.0.3 Fixed EXAMPLE RUN section formatting
2026-01-19 v1.0.2 Updated to two-line ASCII console output style
2025-12-23 v1.0.1 Updated to Limehawk Script Framework
2025-11-29 v1.0.0 Initial Style A implementation
================================================================================
#>
Set-StrictMode -Version Latest
# ==== STATE ====
$errorOccurred = $false
$errorText = ""
$resultCode = 0
$summary = ""
# ==== RUNTIME OUTPUT ====
Write-Host ""
Write-Host "[INFO] DEPENDENCY CHECK"
Write-Host "=============================================================="
# Check and install NuGet provider
$PPNuGet = Get-PackageProvider -ListAvailable | Where-Object { $_.Name -eq "Nuget" }
if (-not $PPNuGet) {
Write-Host "[RUN] Installing NuGet provider..."
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
$summary += "Installed NuGet. "
} else {
Write-Host "[OK] NuGet provider already installed"
}
# Check PSGallery
$PSGallery = Get-PSRepository -Name PSGallery -ErrorAction SilentlyContinue
if (-not $PSGallery) {
Write-Host "[RUN] Configuring PSGallery..."
Set-PSRepository -InstallationPolicy Trusted -Name PSGallery
$summary += "Configured PSGallery. "
} else {
Write-Host "[OK] PSGallery already configured"
}
# Check PowerShellGet version
$PsGetVersion = (Get-Module PowerShellGet -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1).Version
if ($PsGetVersion -lt [version]'2.0') {
Write-Host "[RUN] PowerShellGet version $PsGetVersion is outdated, updating..."
try {
Install-Module -Name PowerShellGet -MinimumVersion 2.2 -Force -AllowClobber -ErrorAction Stop
Write-Host "[WARN] PowerShellGet updated. Please rerun this script."
$summary += "Updated PowerShellGet. "
$resultCode = 1
} catch {
Write-Host "[WARN] Could not update PowerShellGet: $($_.Exception.Message)"
$summary += "PowerShellGet update failed. "
}
}
if ($resultCode -eq 1) {
Write-Host ""
Write-Host "[WARN] RESULT"
Write-Host "=============================================================="
Write-Host "Status : Rerun Required"
Write-Host "Summary : $summary"
Write-Host ""
Write-Host "[INFO] SCRIPT COMPLETE"
Write-Host "=============================================================="
exit 1
}
Write-Host ""
Write-Host "[INFO] SYSTEM DETECTION"
Write-Host "=============================================================="
# Detect manufacturer
$Manufacturer = (Get-CimInstance -ClassName Win32_ComputerSystem).Manufacturer
Write-Host "Manufacturer : $Manufacturer"
Write-Host ""
Write-Host "[INFO] BIOS CONFIGURATION"
Write-Host "=============================================================="
try {
if ($Manufacturer -like "*Dell*") {
$summary += "Dell system. "
Write-Host "[RUN] Detected Dell system"
# Install Dell BIOS Provider if needed
$Mod = Get-Module -ListAvailable -Name DellBIOSProvider
if (-not $Mod) {
Write-Host "[RUN] Installing DellBIOSProvider module..."
Install-Module -Name DellBIOSProvider -Force -ErrorAction Stop
$summary += "Installed DellBIOSProvider. "
}
Import-Module DellBIOSProvider -Global
# Set WOL
Write-Host "[RUN] Setting WakeOnLan to LANOnly..."
Set-Item -Path "DellSmBios:\PowerManagement\WakeOnLan" -Value "LANOnly" -ErrorAction Stop
Write-Host "[OK] Dell BIOS WOL configured successfully"
$summary += "Dell WOL updated. "
} elseif ($Manufacturer -like "*HP*" -or $Manufacturer -like "*Hewlett*") {
$summary += "HP system. "
Write-Host "[RUN] Detected HP system"
# Install HP CMSL if needed
$Mod = Get-Module -ListAvailable -Name HPCMSL
if (-not $Mod) {
Write-Host "[RUN] Installing HPCMSL module..."
Install-Module -Name HPCMSL -Force -AcceptLicense -ErrorAction Stop
$summary += "Installed HPCMSL. "
}
Import-Module HPCMSL -Global
# Set WOL for all WOL-related settings
Write-Host "[RUN] Configuring HP Wake On LAN settings..."
$WolTypes = Get-HPBIOSSettingsList | Where-Object { $_.Name -like "*Wake On Lan*" }
foreach ($WolType in $WolTypes) {
Write-Host " Setting: $($WolType.Name)"
Set-HPBIOSSettingValue -Name $($WolType.Name) -Value "Boot to Hard Drive" -ErrorAction Stop
}
Write-Host "[OK] HP BIOS WOL configured successfully"
$summary += "HP WOL updated. "
} elseif ($Manufacturer -like "*Lenovo*") {
$summary += "Lenovo system. "
Write-Host "[RUN] Detected Lenovo system"
# Set WOL via WMI
Write-Host "[RUN] Setting WakeOnLAN via WMI..."
(Get-WmiObject -Class "Lenovo_SetBiosSetting" -Namespace "root\wmi" -ErrorAction Stop).SetBiosSetting('WakeOnLAN,Primary') | Out-Null
(Get-WmiObject -Class "Lenovo_SaveBiosSettings" -Namespace "root\wmi" -ErrorAction Stop).SaveBiosSettings() | Out-Null
Write-Host "[OK] Lenovo BIOS WOL configured successfully"
$summary += "Lenovo WOL updated. "
} else {
Write-Host "[WARN] Manufacturer '$Manufacturer' not supported for BIOS WOL configuration"
Write-Host "Supported manufacturers: Dell, HP, Lenovo"
$summary += "$Manufacturer not supported. "
}
} catch {
Write-Host "[WARN] BIOS WOL configuration failed: $($_.Exception.Message)"
$summary += "BIOS WOL error. "
}
Write-Host ""
Write-Host "[INFO] NIC CONFIGURATION"
Write-Host "=============================================================="
# Enable WOL on all capable NICs
$NicsWithWake = Get-CimInstance -ClassName "MSPower_DeviceWakeEnable" -Namespace "root/wmi" -ErrorAction SilentlyContinue
if ($NicsWithWake) {
foreach ($Nic in $NicsWithWake) {
Write-Host "[RUN] Enabling WOL for: $($Nic.InstanceName)"
try {
Set-CimInstance -InputObject $Nic -Property @{Enable = $true} -ErrorAction Stop
Write-Host "[OK] Success"
$summary += "$($Nic.InstanceName) WOL enabled. "
} catch {
Write-Host "[WARN] $($_.Exception.Message)"
$summary += "$($Nic.InstanceName) WOL error. "
}
}
} else {
Write-Host "[WARN] No NICs with Wake-on-LAN capability found"
$summary += "No WOL NICs found. "
}
Write-Host ""
Write-Host "[INFO] RESULT"
Write-Host "=============================================================="
Write-Host "Status : Success"
Write-Host "Summary : $summary"
Write-Host ""
Write-Host "[INFO] FINAL STATUS"
Write-Host "=============================================================="
Write-Host "[OK] Wake-on-LAN configuration completed."
Write-Host "A reboot may be required for BIOS changes to take effect."
Write-Host ""
Write-Host "[INFO] SCRIPT COMPLETE"
Write-Host "=============================================================="
exit 0
Manufacturer handling
The script installs the required PowerShell module or library if it's missing, then sets the BIOS parameter by the vendor-specific name (Dell calls it "WakeOnLan", HP calls it "Wake on LAN", Lenovo uses "WakeOnLAN"). For Dell and Lenovo the BIOS password can be passed in as a parameter if the fleet has a shared admin password — HP's CMSL handles the BIOS setup PIN similarly. After BIOS is set, the Windows NIC side gets configured the same way across all three vendors because that part is OS-level, not firmware.
- Dell: DellBIOSProvider PowerShell module
- HP: HP Client Management Script Library (CMSL)
- Lenovo: WMI (Lenovo_SetBiosSetting class)
- Windows NIC: MSPower_DeviceWakeEnable WMI class
- all of it driven from a single deployment
One thing worth calling out — BIOS changes don't take effect until reboot. The script applies the setting, then flags the machine for a reboot on next maintenance window. If you try to send a magic packet before the reboot, nothing happens and you'll think the script failed.
Outcome
Deployed to the whole fleet through the RMM. 85 of 85 reported successful configuration. We coordinated a single reboot cycle during the next lunch hour to apply the BIOS changes — nobody noticed because laptops get rebooted all the time. The following maintenance window: RMM sent magic packets at 1:55 AM, every machine came up, patches installed, and the RMM put them back to sleep at 4 AM. Next morning report: 85 of 85 patched. Zero user disruption, zero billable time lost to "why is my computer on this morning."
- machines configured: 85 of 85
- next patch window: 100% reached
- deployment time: about 15 minutes running in parallel
- patches installed on next overnight window: 85 of 85