15 April 2019

Configuring Wake-On-LAN for Dell Systems

If you have been wanting to wake your Dell systems up from sleep, hibernate, or shutdown states, this is how you do it. Starting out with this article from Dell, I got the list of things needed to set up the system for WOL. There are three areas that have to be configured on Dell systems, at least for the systems we have which range from the Optiplex 990 to the Latitude 7490. The areas are BIOS, advanced NIC, and power management settings. This site helped with the final setting to disable fast startup, which is required. WOL did not work on our systems until I implemented this final setting.

Before implementing this baseline, you will need to make sure Dell Command | Configure is installed on all systems. To ensure this, I have it deployed as an application to all Dell systems. Dell Command | Configure is what the baseline PowerShell scripts use to query and configure the BIOS settings. I also made a collection called All Dell Systems since we also have a few Microsoft Surfaces.

NOTE: This was created on April 15, 2019. New Dell models and BIOS updates are constantly released. It is likely there will be changes that need to be made in the future to these scripts to work with those updates.

The Wake-On-LAN Compliance item is set up to use a script that returns a Boolean value as shown below.


The discovery script is the following PowerShell script:


 ##Find Dell Command | Configure for 64-bit  
 $CCTK = Get-ChildItem -Path ${env:ProgramFiles(x86)}, $env:ProgramFiles -Filter cctk.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.Directory -like '*x86_64*'}  
 ##Get all available Dell Command | Configure commands for current system  
 $Commands = Invoke-Command -ScriptBlock {c:\Windows\system32\cmd.exe /c $CCTK.FullName -h} -ErrorAction SilentlyContinue  
 ##Configure BIOS --wakeonlan=enable  
 #Test if wakeonlan exists on current system  
 If ($Commands -like '*wakeonlan*') {  
      [string]$WakeOnLANSetting = 'wakeonlan=enable'  
      [string]$Output = Invoke-Command -ScriptBlock {c:\Windows\system32\cmd.exe /c $CCTK.FullName --wakeonlan} -ErrorAction SilentlyContinue  
      If ($Output -ne $WakeOnLANSetting) {  
           $WakeOnLAN = $false  
      } else {  
           $WakeOnLAN = $true  
      }  
 }  
 ##Configure BIOS --deepsleepctrl=disable  
 #Test if deepsleepctrl exists on current system  
 If ($Commands -like '*deepsleepctrl*') {  
      [string]$DeepSleepCtrlSetting = 'deepsleepctrl=disable'  
      [string]$Output = Invoke-Command -ScriptBlock {c:\Windows\system32\cmd.exe /c $CCTK.FullName --deepsleepctrl} -ErrorAction SilentlyContinue  
      If ($Output -ne $DeepSleepCtrlSetting) {  
           $DeepSleepCtrl = $false  
      } else {  
           $DeepSleepCtrl = $true  
      }  
 }  
 ##Configure BIOS --blocks3=disable  
 #Test if blocks3 exists on current system  
 If ($Commands -like '*blocks3*') {  
      [string]$BlockS3Setting = 'blocks3=disable'  
      [string]$Output = Invoke-Command -ScriptBlock { c:\Windows\system32\cmd.exe /c $CCTK.FullName --blocks3} -ErrorAction SilentlyContinue  
      If ($Output -ne $BlockS3Setting) {  
           $BlockS3 = $false  
      } else {  
           $BlockS3 = $true  
      }  
 }  
 ##Configure BIOS --cstatesctrl=disable  
 #Test if cstatesctrl exists on current system  
 If ($Commands -like '*cstatesctrl*') {  
      [string]$CStateCTRLSetting = 'cstatesctrl=disable'  
      [string]$Output = Invoke-Command -ScriptBlock { c:\Windows\system32\cmd.exe /c $CCTK.FullName --cstatesctrl} -ErrorAction SilentlyContinue  
      If ($Output -ne $CStateCTRLSetting) {  
           $CStateCTRL = $false  
      } else {  
           $CStateCTRL = $true  
      }  
 }  
 ##Disable Energy Efficient Ethernet  
 #Energy Efficient Ethernet disable registry value  
 $RegistryValue = '0'  
 #Find ethernet adapter  
 $Adapter = (Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}).Name  
 $DisplayName = (Get-NetAdapterAdvancedProperty -Name $Adapter | Where-Object {$_.DisplayName -like '*Efficient Ethernet*'}).DisplayName  
 #Test for presence of Energy-Efficient Ethernet  
 If ($DisplayName -like '*Efficient Ethernet*') {  
      [string]$CurrentState = (Get-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName).RegistryValue  
      If ($CurrentState -ne $RegistryValue) {  
           $EnergyEfficientEthernet = $false  
      } else {  
           $EnergyEfficientEthernet = $true  
      }  
 }  
 ##Enable Wake on Magic Packet  
 $State = 'Enabled'  
 $Adapter = (Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}).Name  
 $DisplayName = (Get-NetAdapterAdvancedProperty -Name $Adapter | Where-Object {$_.DisplayName -like '*Magic Packet*'}).DisplayName  
 #Test if Magic Packet exists  
 If ($DisplayName -like '*Magic Packet*') {  
      [string]$CurrentState = (Get-NetAdapterPowerManagement -Name $Adapter).WakeOnMagicPacket  
      If ($CurrentState -ne $State) {  
           $WakeOnMagicPacket = $false  
      } else {  
           $WakeOnMagicPacket = $true  
      }  
 }  
 ##Disable Shutdown Wake-On-Lan  
 $RegistryValue = '0'  
 $Adapter = (Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}).Name  
 $DisplayName = (Get-NetAdapterAdvancedProperty -Name $Adapter -ErrorAction SilentlyContinue | Where-Object {$_.DisplayName -eq 'Shutdown Wake-On-Lan'}).DisplayName  
 If ($DisplayName -eq 'Shutdown Wake-On-Lan') {  
      [string]$CurrentState = (Get-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName).RegistryValue  
      If ($CurrentState -ne $RegistryValue) {  
           $ShutdownWakeOnLAN = $false  
      } else {  
           $ShutdownWakeOnLAN = $true  
      }  
 }  
 ##Enable Allow the computer to turn off this device  
 $KeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\'  
 #Test if KeyPath exists  
 If ((Test-Path $KeyPath) -eq $true) {  
      $PnPValue = 256  
      $Adapter = Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}  
      foreach ($Entry in (Get-ChildItem $KeyPath -ErrorAction SilentlyContinue).Name) {  
           If ((Get-ItemProperty REGISTRY::$Entry).DriverDesc -eq $Adapter.InterfaceDescription) {  
                $Value = (Get-ItemProperty REGISTRY::$Entry).PnPCapabilities  
                If ($Value -ne $PnPValue) {  
                     $PowerManagement = $false  
                } else {  
                     $PowerManagement = $true  
                }  
           }  
      }  
 }  
 ##Disable Fast Startup  
 $KeyPath = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power"  
 #Test if KeyPath exists  
 If ((Test-Path -Path ('REGISTRY::' + $KeyPath)) -eq $true) {  
      If ((Get-ItemProperty -Path ('REGISTRY::' + $KeyPath)).HiberbootEnabled -eq 0) {  
           $FastStartup = $false  
      } else {  
           $FastStartup = $true  
      }  
 }  
 #Write-Host 'Wake-On-LAN:'$WakeOnLAN  
 #Write-Host 'Deep Sleep Control:'$DeepSleepCtrl  
 #Write-Host 'BlockS3:'$BlockS3  
 #Write-Host 'CState Control:'$CStateCTRL  
 #Write-Host 'Energy Efficient Ethernet:'$EnergyEfficientEthernet  
 #Write-Host 'Wake-On-Magic-Packet:'$WakeOnMagicPacket  
 #Write-Host 'Shutdown Wake-On-LAN:'$ShutdownWakeOnLAN  
 #Write-Host 'Allow Computer to Turn Off this Device:'$PowerManagement  
 If ((($WakeOnLAN -eq $null) -or ($WakeOnLAN -eq $true)) -and ($FastStartup -eq $false) -and (($DeepSleepCtrl -eq $null) -or ($DeepSleepCtrl -eq $true)) -and (($BlockS3 -eq $null) -or ($BlockS3 -eq $true)) -and (($CStateCTRL -eq $null) -or ($CStateCTRL -eq $true)) -and (($EnergyEfficientEthernet -eq $null) -or ($EnergyEfficientEthernet -eq $true)) -and (($WakeOnMagicPacket -eq $null) -or ($WakeOnMagicPacket -eq $true)) -and (($ShutdownWakeOnLAN -eq $null) -or ($ShutdownWakeOnLAN -eq $true)) -and (($PowerManagement -eq $null) -or ($PowerManagement -eq $true))) {  
      echo $true  
 } else {  
      echo $false  
 }  
   

The remediation script is as follows:


 ##Find Dell Command | Configure for 64-bit  
 $CCTK = Get-ChildItem -Path ${env:ProgramFiles(x86)}, $env:ProgramFiles -Filter cctk.exe -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.Directory -like '*x86_64*'}  
 ##Get all available Dell Command | Configure commands for current system  
 $Commands = Invoke-Command -ScriptBlock {c:\Windows\system32\cmd.exe /c $CCTK.FullName -h} -ErrorAction SilentlyContinue  
 ##Configure BIOS --wakeonlan=enable  
 #Test if wakeonlan exists on current system  
 If ($Commands -like '*wakeonlan*') {  
      [string]$WakeOnLANSetting = 'wakeonlan=enable'  
      [string]$Output = Invoke-Command -ScriptBlock {c:\Windows\system32\cmd.exe /c $CCTK.FullName --wakeonlan} -ErrorAction SilentlyContinue  
      If ($Output -ne $WakeOnLANSetting) {  
           $ErrCode = (Start-Process -FilePath $CCTK.FullName -ArgumentList ('--' + $WakeOnLANSetting) -Wait -Passthru).ExitCode  
           If ($ErrCode -eq 0) {  
                $WakeOnLAN = $true  
           } elseif ($ErrCode -eq 119) {  
                $WakeOnLAN = $true  
           } else {  
                $WakeOnLAN = $false  
           }  
           Remove-Variable -Name ErrCode  
      } else {  
           $WakeOnLAN = $true  
      }  
      Remove-Variable -Name WakeOnLANSetting  
      Remove-Variable -Name Output  
 }  
 ##Configure BIOS --deepsleepctrl=disable  
 #Test if deepsleepctrl exists on current system  
 If ($Commands -like '*deepsleepctrl*') {  
      [string]$DeepSleepCtrlSetting = 'deepsleepctrl=disable'  
      [string]$Output = Invoke-Command -ScriptBlock {c:\Windows\system32\cmd.exe /c $CCTK.FullName --deepsleepctrl} -ErrorAction SilentlyContinue  
      If ($Output -ne $DeepSleepCtrlSetting) {  
           $ErrCode = (Start-Process -FilePath $CCTK.FullName -ArgumentList ('--' + $DeepSleepCtrlSetting) -Wait -Passthru).ExitCode  
           If ($ErrCode -eq 0) {  
                $DeepSleepCtrl = $true  
           } elseif ($ErrCode -eq 119) {  
                $DeepSleepCtrl = $true  
           } else {  
                $DeepSleepCtrl = $false  
           }  
           Remove-Variable -Name ErrCode  
      }  
      Remove-Variable -Name DeepSleepCtrlSetting  
      Remove-Variable -Name Output  
 }  
 ##Configure BIOS --blocks3=disable  
 #Test if blocks3 exists on current system  
 If ($Commands -like '*blocks3*') {  
      [string]$BlockS3Setting = 'blocks3=disable'  
      [string]$Output = Invoke-Command -ScriptBlock { c:\Windows\system32\cmd.exe /c $CCTK.FullName --blocks3} -ErrorAction SilentlyContinue  
      If ($Output -ne $BlockS3Setting) {  
           $ErrCode = (Start-Process -FilePath $CCTK.FullName -ArgumentList ('--' + $BlockS3Setting) -Wait -Passthru).ExitCode  
           If ($ErrCode -eq 0) {  
                $BlockS3 = $true  
           } elseif ($ErrCode -eq 119) {  
                $BlockS3 = $true  
           } else {  
                $BlockS3 = $false  
           }  
           Remove-Variable -Name ErrCode  
      } else {  
           $BlockS3 = $true  
      }  
      Remove-Variable -Name BlockS3Setting  
      Remove-Variable -Name Output  
 }  
 ##Configure BIOS --cstatesctrl=disable  
 #Test if cstatesctrl exists on current system  
 If ($Commands -like '*cstatesctrl*') {  
      [string]$CStateCTRLSetting = 'cstatesctrl=disable'  
      [string]$Output = Invoke-Command -ScriptBlock { c:\Windows\system32\cmd.exe /c $CCTK.FullName --cstatesctrl} -ErrorAction SilentlyContinue  
      If ($Output -ne $CStateCTRLSetting) {  
           $ErrCode = (Start-Process -FilePath $CCTK.FullName -ArgumentList ('--' + $CStateCTRLSetting) -Wait -Passthru).ExitCode  
           If ($ErrCode -eq 0) {  
                $CStateCTRL = $true  
           } elseif ($ErrCode -eq 119) {  
                $CStateCTRL = $true  
           } else {  
                $CStateCTRL = $false  
           }  
           Remove-Variable -Name ErrCode  
      } else {  
           $CStateCTRL = $true  
      }  
      Remove-Variable -Name CStateCTRLSetting  
      Remove-Variable -Name Output  
 }  
 ##Disable Energy Efficient Ethernet  
 #Energy Efficient Ethernet disable registry value  
 $RegistryValue = '0'  
 #Find ethernet adapter  
 $Adapter = (Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}).Name  
 $DisplayName = (Get-NetAdapterAdvancedProperty -Name $Adapter | Where-Object {$_.DisplayName -like '*Efficient Ethernet*'}).DisplayName  
 #Test for presence of Energy-Efficient Ethernet  
 If ($DisplayName -like '*Efficient Ethernet*') {  
      [string]$CurrentState = (Get-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName).RegistryValue  
      If ($CurrentState -ne $RegistryValue) {  
           Set-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName -RegistryValue $RegistryValue  
           Do {  
                Try {  
                     [string]$CurrentState = (Get-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName).RegistryValue  
                     $Err = $false  
                } Catch {  
                     $Err = $true  
                }  
           } While ($Err -eq $true)  
           If ($RegistryValue -eq $CurrentState) {  
                $EnergyEfficientEthernet = $true  
           } else {  
                $EnergyEfficientEthernet = $false  
           }  
           Remove-Variable -Name Err  
      } else {  
           $EnergyEfficientEthernet = $true  
      }  
      Remove-Variable -Name RegistryValue  
      Remove-Variable -Name Adapter  
      Remove-Variable -Name DisplayName  
      Remove-Variable -Name CurrentState  
 }  
 ##Enable Wake on Magic Packet  
 $State = 'Enabled'  
 $Adapter = (Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}).Name  
 $DisplayName = (Get-NetAdapterAdvancedProperty -Name $Adapter | Where-Object {$_.DisplayName -like '*Magic Packet*'}).DisplayName  
 #Test if Magic Packet exists  
 If ($DisplayName -like '*Magic Packet*') {  
      [string]$CurrentState = (Get-NetAdapterPowerManagement -Name $Adapter).WakeOnMagicPacket  
      If ($CurrentState -ne $State) {  
           Set-NetAdapterPowerManagement -Name $Adapter -WakeOnMagicPacket $State  
           Do {  
                Try {  
                     [string]$CurrentState = (Get-NetAdapterPowerManagement -Name $Adapter).WakeOnMagicPacket  
                     $Err = $false  
                } Catch {  
                     $Err = $true  
                }  
           } While ($Err -eq $true)  
           If ($State -eq $CurrentState) {  
                $WakeOnMagicPacket = $true  
           } else {  
                $WakeOnMagicPacket = $false  
           }  
           Remove-Variable -Name Err  
      } else {  
           $WakeOnMagicPacket = $true  
      }  
      Remove-Variable -Name State  
      Remove-Variable -Name Adapter  
      Remove-Variable -Name DisplayName  
      Remove-Variable -Name CurrentState  
 }  
 ##Disable Shutdown Wake-On-Lan  
 $RegistryValue = '0'  
 $Adapter = (Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}).Name  
 $DisplayName = (Get-NetAdapterAdvancedProperty -Name $Adapter -ErrorAction SilentlyContinue | Where-Object {$_.DisplayName -eq 'Shutdown Wake-On-Lan'}).DisplayName  
 If ($DisplayName -eq 'Shutdown Wake-On-Lan') {  
      [string]$CurrentState = (Get-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName).RegistryValue  
      If ($CurrentState -ne $RegistryValue) {  
           Set-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName -RegistryValue $RegistryValue  
           Do {  
                Try {  
                     [string]$CurrentState = (Get-NetAdapterAdvancedProperty -Name $Adapter -DisplayName $DisplayName).RegistryValue  
                     $Err = $false  
                } Catch {  
                     $Err = $true  
                }  
           } While ($Err -eq $true)  
           If ($RegistryValue -eq $CurrentState) {  
                $ShutdownWakeOnLAN = $true  
           } else {  
                $ShutdownWakeOnLAN = $false  
           }  
           Remove-Variable -Name Err  
      } else {  
           $ShutdownWakeOnLAN = $true  
      }  
      Remove-Variable -Name RegistryValue  
      Remove-Variable -Name Adapter  
      Remove-Variable -Name DisplayName  
      Remove-Variable -Name CurrentState  
 }  
 ##Enable Allow the computer to turn off this device  
 $KeyPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\'  
 #Test if KeyPath exists  
 If ((Test-Path $KeyPath) -eq $true) {  
      $PnPValue = 256  
      $Adapter = Get-NetAdapter | Where-Object {($_.Status -eq 'Up') -and ($_.PhysicalMediaType -eq '802.3')}  
      foreach ($Entry in (Get-ChildItem $KeyPath -ErrorAction SilentlyContinue).Name) {  
           If ((Get-ItemProperty REGISTRY::$Entry).DriverDesc -eq $Adapter.InterfaceDescription) {  
                $Value = (Get-ItemProperty REGISTRY::$Entry).PnPCapabilities  
                If ($Value -ne $PnPValue) {  
                     Set-ItemProperty -Path REGISTRY::$Entry -Name PnPCapabilities -Value $PnPValue -Force  
                     Disable-PnpDevice -InstanceId $Adapter.PnPDeviceID -Confirm:$false  
                     Enable-PnpDevice -InstanceId $Adapter.PnPDeviceID -Confirm:$false  
                     $Value = (Get-ItemProperty REGISTRY::$Entry).PnPCapabilities  
                }  
                If ($Value -eq $PnPValue) {  
                     $PowerManagement = $true  
                } else {  
                     $PowerManagement = $false  
                }  
                Remove-Variable -Name Value  
           }  
      }  
      Remove-Variable -Name PnPValue  
      Remove-Variable -Name Adapter  
      Remove-Variable -Name KeyPath  
 }  
 ##Disable Fast Startup  
 $KeyPath = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power"  
 #Test if KeyPath exists  
 If ((Test-Path -Path ('REGISTRY::' + $KeyPath)) -eq $true) {  
      Set-ItemProperty -Path ('REGISTRY::' + $KeyPath) -Name 'HiberbootEnabled' -Value 0  
      If ((Get-ItemProperty -Path ('REGISTRY::' + $KeyPath)).HiberbootEnabled -eq 0) {  
           $FastStartup = $false  
      } else {  
           $FastStartup = $true  
      }  
 }  
 #Write-Host 'Wake-On-LAN:'$WakeOnLAN  
 #Write-Host 'Deep Sleep Control:'$DeepSleepCtrl  
 #Write-Host 'BlockS3:'$BlockS3  
 #Write-Host 'CState Control:'$CStateCTRL  
 #Write-Host 'Energy Efficient Ethernet:'$EnergyEfficientEthernet  
 #Write-Host 'Wake-On-Magic-Packet:'$WakeOnMagicPacket  
 #Write-Host 'Shutdown Wake-On-LAN:'$ShutdownWakeOnLAN  
 #Write-Host 'Allow Computer to Turn Off this Device:'$PowerManagement  
 If ((($WakeOnLAN -eq $null) -or ($WakeOnLAN -eq $true)) -and ($FastStartup -eq $false) -and (($DeepSleepCtrl -eq $null) -or ($DeepSleepCtrl -eq $true)) -and (($BlockS3 -eq $null) -or ($BlockS3 -eq $true)) -and (($CStateCTRL -eq $null) -or ($CStateCTRL -eq $true)) -and (($EnergyEfficientEthernet -eq $null) -or ($EnergyEfficientEthernet -eq $true)) -and (($WakeOnMagicPacket -eq $null) -or ($WakeOnMagicPacket -eq $true)) -and (($ShutdownWakeOnLAN -eq $null) -or ($ShutdownWakeOnLAN -eq $true)) -and (($PowerManagement -eq $null) -or ($PowerManagement -eq $true))) {  
      echo $true  
 } else {  
      echo $false  
 }  
   


Finally, the compliance rule is as follows:


You may wonder why I included Remove-Variable cmdlets. I used those when I was debugging so it was easier to track variable values.

For the configuration baseline, I have it configured as shown below:


0 comments:

Post a Comment