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.

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

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

Kelvin Tegelaar
Follow me

8 thoughts on “Monitoring with PowerShell: monitor and enabling WOL for HP, Lenovo, Dell

  1. Trevor Henry

    Hi Kelvin, Interesting project. I think it’s a bit late for some… Will the script set the BIOS to enable Wake-on -LAN ?
    I don’t know for sure, but I imagine the PC will have to be ON for the script to work ?
    I apologise for the naivety of the question, please cut me some slack !

    Reply
    1. Kelvin Tegelaar Post author

      Yeah the script’s been out for a while now, but I think a lot of people already covered it. 🙂

      No worries about questions – We’re all in this to learn. The PC will have to be on, and the script will change the BIOS settings. 🙂

      Reply
  2. Chris

    I had to change the values/settings the HP and Lenovo were using to get it to work on the two PCs I tested.

    (Get-WmiObject -ErrorAction Stop -class “Lenovo_SetBiosSetting” -namespace “root\wmi”).SetBiosSetting(‘WakeOnLAN,Enable’) | Out-Null

    ‘WakeOnLAN,Enable’ instead of ‘WakeOnLAN,Primary’

    on the HP Side

    Set-HPBIOSSettingValue -name $($WOLType.name) -Value “Follow Boot Order” -ErrorAction Stop

    “Follow Boot Order” instead of “Boot to Hard Drive”

    Reply
    1. Kelvin Tegelaar Post author

      Yeah that’s the issue with so many different models – Each option is named a little different. We customized this for the models we use most, but it will need more customization for your own fleet of devices, hence the experimental comment 🙂

      Reply
  3. Jeison F.

    Hello! Amazing work! I’m trying to know if it’s possible to listen an incoming WOL Packet using CMD or Powershell? You may knows, considering your experience. Could you help me? Thanks!

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.