Featured image of post Monitoring with PowerShell: monitor and enabling WOL for HP, Lenovo, Dell

Monitoring with PowerShell: monitor and enabling WOL for HP, Lenovo, Dell

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.

The remediation script

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. 🙂

All blogs are posted under AGPL3.0 unless stated otherwise
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy