Some of my friends (Hi Joe! Hi Tyler!) recently requested a script to both monitor and enable WOL for workstations at their clients. WOL stands for Wake-On-Lan and is used to boot machines without user intervention. There are two forms of WOL: OS based, to let a machine start up from standby or hibernation, and BIOS based to boot computers which are completely turned off.
With the current stress of everyone wanting to work from home via all sorts of tools, my friends found some devices that aren’t replying to WOL packets or machines that simply were not configured for WOL yet.
I figured this could be a pretty cool exercise, I’ve seen a bunch of people making very device specific scripts to enable WOL, but not a lot of manufacture specific scripts that would enable it for an entire line of devices. During my discoveries I’ve found that the three biggest manufactures all have a method to enable WOL directly with PowerShell. Two of them use a module, the other uses a WMI class.
The script will work for Dell, HP, and Lenovo. Disclaimer: I tested the script on a handful of devices, so no guarantees of course. 🙂
The monitoring script
The monitoring script only works with PowerShell 5.0 or higher. It will also update PowerShell Get and also download the correct module for the device. We match based on the device manufacture in WMI.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
$PPNuGet = Get-PackageProvider -ListAvailable | Where-Object { $_.Name -eq "Nuget" }
if (!$PPNuget) {
Write-Host "Installing Nuget provider" -foregroundcolor Green
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
}
$PSGallery = Get-PSRepository -Name PsGallery
if (!$PSGallery) {
Write-Host "Installing PSGallery" -foregroundcolor Green
Set-PSRepository -InstallationPolicy Trusted -Name PSGallery
}
$PsGetVersion = (get-module PowerShellGet).version
if ($PsGetVersion -lt [version]'2.0') {
Write-Host "Installing latest version of PowerShellGet provider" -foregroundcolor Green
install-module PowerShellGet -MinimumVersion 2.2 -Force
Write-Host "Reloading Modules" -foregroundcolor Green
Remove-Module PowerShellGet -Force
Remove-module PackageManagement -Force
Import-Module PowerShellGet -MinimumVersion 2.2 -Force
Write-Host "Updating PowerShellGet" -foregroundcolor Green
Install-Module -Name PowerShellGet -MinimumVersion 2.2.3 -force
Write-Host "You must rerun the script to succesfully get the WOL status. PowerShellGet was found out of date." -ForegroundColor red
exit 1
}
Write-Host "Checking Manufacturer" -foregroundcolor Green
$Manufacturer = (Get-WmiObject -Class:Win32_ComputerSystem).Manufacturer
if ($Manufacturer -like "*Dell*") {
Write-Host "Manufacturer is Dell. Installing Module and trying to get WOL state" -foregroundcolor Green
Write-Host "Installing Dell Bios Provider if needed" -foregroundcolor Green
$Mod = Get-Module DellBIOSProvider
if (!$mod) {
Install-Module -Name DellBIOSProvider -Force
}
import-module DellBIOSProvider
try {
$WOLMonitor = get-item -Path "DellSmBios:\PowerManagement\WakeOnLan" -ErrorAction SilentlyContinue
if ($WOLMonitor.currentvalue -eq "LanOnly") { $WOLState = "Healthy" }
}
catch {
write-host "an error occured. Could not get WOL setting."
}
}
if ($Manufacturer -like "*HP*" -or $Manufacturer -like "*Hewlett*") {
Write-Host "Manufacturer is HP. Installing module and trying to get WOL State." -foregroundcolor Green
Write-Host "Installing HP Provider if needed." -foregroundcolor Green
$Mod = Get-Module HPCMSL
if (!$mod) {
Install-Module -Name HPCMSL -Force -AcceptLicense
}
import-module HPCMSL
try {
$WolTypes = get-hpbiossettingslist | Where-Object { $_.Name -like "*Wake On Lan*" }
$WOLState = ForEach ($WolType in $WolTypes) {
write-host "Setting WOL Type: $($WOLType.Name)"
get-HPBIOSSettingValue -name $($WolType.name) -ErrorAction Stop
}
}
catch {
write-host "an error occured. Could not find WOL state"
}
}
if ($Manufacturer -like "*Lenovo*") {
Write-Host "Manufacturer is Lenovo. Trying to get via WMI" -foregroundcolor Green
try {
Write-Host "Getting BIOS." -foregroundcolor Green
$currentSetting = (Get-WmiObject -ErrorAction Stop -class "Lenovo_BiosSetting" -namespace "root\wmi") | Where-Object { $_.CurrentSetting -ne "" }
$WOLStatus = $currentSetting.currentsetting | ConvertFrom-Csv -Delimiter "," -Header "Setting", "Status" | Where-Object { $_.setting -eq "Wake on lan" }
$WOLStatus = $WOLStatus.status -split ";"
if ($WOLStatus[0] -eq "Primary") { $WOLState = "Healthy" }
}
catch {
write-host "an error occured. Could not find WOL state"
}
}
$NicsWithWake = Get-CimInstance -ClassName "MSPower_DeviceWakeEnable" -Namespace "root/wmi" | Where-Object { $_.Enable -eq $False }
if (!$NicsWithWake) {
$NICWOL = "Healthy - All NICs enabled for WOL within the OS."
}
else {
$NICWOL = "Unhealthy - NIC does not have WOL enabled inside of the OS."
}
if (!$WOLState) {
$NICWOL = "Unhealthy - Could not find WOL state"
}
|
After running the script we can check the contents of $WOLState for the current state of the WOL setting in the BIOS. You can also check $NICWOL for the Operating System’s WOL state.
So on the remediation side we tackle enabling WOL in both the BIOS and inside of the Operating System. We always install the module in this case, as often module updates are released when newer systems are too.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
$PPNuGet = Get-PackageProvider -ListAvailable | Where-Object { $_.Name -eq "Nuget" }
if (!$PPNuget) {
Write-Host "Installing Nuget provider" -foregroundcolor Green
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
}
$PSGallery = Get-PSRepository -Name PsGallery
if (!$PSGallery) {
Write-Host "Installing PSGallery" -foregroundcolor Green
Set-PSRepository -InstallationPolicy Trusted -Name PSGallery
}
$PsGetVersion = (get-module PowerShellGet).version
if ($PsGetVersion -lt [version]'2.0') {
Write-Host "Installing latest version of PowerShellGet provider" -foregroundcolor Green
install-module PowerShellGet -MinimumVersion 2.2 -Force
Write-Host "Reloading Modules" -foregroundcolor Green
Remove-Module PowerShellGet -Force
Remove-module PackageManagement -Force
Import-Module PowerShellGet -MinimumVersion 2.2 -Force
Write-Host "Updating PowerShellGet" -foregroundcolor Green
Install-Module -Name PowerShellGet -MinimumVersion 2.2.3 -force
write-host "You must rerun the script to succesfully set the WOL status. PowerShellGet was found out of date." -ForegroundColor red
}
Write-Host "Checking Manufacturer" -foregroundcolor Green
$Manufacturer = (Get-WmiObject -Class:Win32_ComputerSystem).Manufacturer
if ($Manufacturer -like "*Dell*") {
Write-Host "Manufacturer is Dell. Installing Module and trying to enable Wake on LAN." -foregroundcolor Green
Write-Host "Installing Dell Bios Provider" -foregroundcolor Green
Install-Module -Name DellBIOSProvider -Force
import-module DellBIOSProvider
try {
set-item -Path "DellSmBios:\PowerManagement\WakeOnLan" -value "LANOnly" -ErrorAction Stop
}
catch {
write-host "an error occured. Could not set BIOS to WakeOnLan. Please try setting WOL manually"
}
}
if ($Manufacturer -like "*HP*" -or $Manufacturer -like "*Hewlett*") {
Write-Host "Manufacturer is HP. Installing module and trying to enable WakeOnLan. All HP Drivers are required for this operation to succeed." -foregroundcolor Green
Write-Host "Installing HP Provider" -foregroundcolor Green
Install-Module -Name HPCMSL -Force -AcceptLicense
import-module HPCMSL
try {
$WolTypes = get-hpbiossettingslist | Where-Object { $_.Name -like "*Wake On Lan*" }
ForEach ($WolType in $WolTypes) {
write-host "Setting WOL Type: $($WOLType.Name)"
Set-HPBIOSSettingValue -name $($WolType.name) -Value "Boot to Hard Drive" -ErrorAction Stop
}
}
catch {
write-host "an error occured. Could not set BIOS to WakeOnLan. Please try manually"
}
}
if ($Manufacturer -like "*Lenovo*") {
Write-Host "Manufacturer is Lenovo. Trying to set via WMI. All Lenovo Drivers are required for this operation to succeed." -foregroundcolor Green
try {
Write-Host "Setting BIOS." -foregroundcolor Green
(Get-WmiObject -ErrorAction Stop -class "Lenovo_SetBiosSetting" -namespace "root\wmi").SetBiosSetting('WakeOnLAN,Primary') | Out-Null
Write-Host "Saving BIOS." -foregroundcolor Green
(Get-WmiObject -ErrorAction Stop -class "Lenovo_SaveBiosSettings" -namespace "root\wmi").SaveBiosSettings() | Out-Null
}
catch {
write-host "an error occured. Could not set BIOS to WakeOnLan. Please try manually"
}
}
write-host "Setting NIC to enable WOL" -ForegroundColor Green
$NicsWithWake = Get-CimInstance -ClassName "MSPower_DeviceWakeEnable" -Namespace "root/wmi"
foreach ($Nic in $NicsWithWake) {
write-host "Enabling for NIC" -ForegroundColor green
Set-CimInstance $NIC -Property @{Enable = $true }
}
|
Like I said in the start – This still is slightly experimental for me. I did not have a large stack of devices to test on other than Dell devices, so if you find any issues with Lenovo or HP devices, let me know and send me a transcript, maybe I can help you figure it out!
And that’s it. As always, Happy PowerShelling.
update: N-Central remediation AMP can be found here. The monitoring AMP can be found here.
Update 2: Fixed a small encoding issue that crashed the script in some cases.
Update 3: Added better detection logic for nuget which causes a script hang, fixed an import and install module issue. This has not been updated inside of the monitoring AMPs. Please copy and paste the latest script in there. 🙂