Monday, 18 June 2012

Setting Power Management Options on a Network Card

I'm currently working on implementing Wake on LAN (WOL) for a customer's network.  I'll probably post more on what I've found out will researching this in the future.  Today I thought I'd share a script I've created to enable the correct power management options, that are needed on the appropriate network adaptors, to ensure WOL works.
 I wanted a script to ensure the three options in the screen grab below are enabled.  PowerShell is my preferred scripting solution, and this customer also wants as much scripting done in PowerShell as possible.  I found a number of VBScripts examples that I then used to construct my PowerShell script, so I don't take credit for the logic here but I couldn't find a complete PowerShell solution so I hope this is useful for someone.  I'm no PowerShell guru, so if anyone sees ways to improve this script - please feel free to share ideas.


Anyway, here is the screen grab showing the settings I wanted to set:




Here are some links to where I got my logic and ideas from:


ConfigMgr 2007: Implementing Wake-on-LAN (WoL):  This article explains setting up WOL with ConfigMgr very well and includes a VBScript that was my main source for understanding what WMI exposed that I could use for my script


Configure a Network Adapter to Wake a Computer Via PowerShell:  This article was where I found the base I used for my script in PowerShell, it shows how to get at one of the properties via WMI, after figuring this out the rest of the script was easy.


My script follows below.  One thing I've added that is different from the two great articles above is that I look only for physical ethernet adaptors.  I don't try to configure these settings on virtual adaptors or wireless adaptors (others might want to do this for wireless adaptors, Windows 7 does support WOL over wireless, but that isn't a requirement for my customer).  Eliminating virtual adaptors from being configured stops the script touching the various virtual adaptors that various remote access solutions like to add to Windows.


#
# 
# Purpose:  Enables Wake on LAN (WOL) settings on active wired network cards
# 
# Usage : powershell.exe -f .\EnableWOL.ps1
# 
# Version 1.0
# 
# Maintenance History
# ----------------------------------------------------------------------
# Version   -    Date      -    Change           -       Author
# ----------------------------------------------------------------------
# 1.0            18/06/12       Script Created           justanothertechnicalblog
# 
# 

$nics = Get-WmiObject Win32_NetworkAdapter -filter "AdapterTypeID = '0' AND PhysicalAdapter = 'true'"
 
 
foreach ($nic in $nics)
  {

   $nicName = $nic.Name

   Write-Host "--- Enable `"Allow the computer to turn off this device to save power`" on $nicName ---"
   $nicPower = Get-WmiObject MSPower_DeviceEnable -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }
   $nicPower.Enable = $True
   $nicPower.psbase.Put()
  
   Write-Host "--- Enable `"Allow this device to wake the computer`" on $nicName ---"
   $nicPowerWake = Get-WmiObject MSPower_DeviceWakeEnable -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }
   $nicPowerWake.Enable = $True
   $nicPowerWake.psbase.Put()
  
   Write-Host "--- Enable `"Only allow a magic packet to wake the computer`" on $nicName ---"
   $nicMagicPacket = Get-WmiObject MSNdis_DeviceWakeOnMagicPacketOnly -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }
   $nicMagicPacket.EnableWakeOnMagicPacketOnly = $True
   $nicMagicPacket.psbase.Put()
  }



UPDATE 19 June 2012:
Testing today on a laptop I found the above script will identify the inbuilt Intel Centrino Ultimate-N 6300 AGN on a Dell Latitude E6510 as an Ethernet adaptor when it plainly isn't. It then fails to set some of the properties above as they are not supported. Not a big deal, the inbuilt Ethernet adaptor is treated correctly so the result is successful, but messy.  I might have to use the 'netenabled' filter used in the PowerShell Guys' posting above.

UPDATE 06 July 2012:
Here is my updated script to exclude wireless and other cards:



# ---------------------------------------------------------------------- 
#
# Purpose:  Enables Wake on LAN (WOL) settings on active wired network cards
#
# Usage : powershell.exe -f .\EnableWOL.ps1
#
# Version 1.0
#
# Maintenance History
# ----------------------------------------------------------------------
# Version   -    Date      -    Change           -       Author
# ---------------------------------------------------------------------- 
# 1.0            18/06/12       Script Created           justanothertechnicalblog
# 2.0            04/07/12       Updated to exclude       justanothertechnicalblog
#                               Wireless/WiFi/Bluetooth


# Get all physical ethernet adaptors
$nics = Get-WmiObject Win32_NetworkAdapter -filter "AdapterTypeID = '0' `
                                                    AND PhysicalAdapter = 'true' `
                                                    AND NOT Description LIKE '%Centrino%' `
                                                    AND NOT Description LIKE '%wireless%' `
                                                    AND NOT Description LIKE '%WiFi%' `
                                                    AND NOT Description LIKE '%Bluetooth%'"


foreach ($nic in $nics)
  {
  
  $nicName = $nic.Name
  
   Write-Host "--- Enable `"Allow the computer to turn off this device to save power`" on $nicName ---"
   $nicPower = Get-WmiObject MSPower_DeviceEnable -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }
   $nicPower.Enable = $True
   $nicPower.psbase.Put()
   
   Write-Host "--- Enable `"Allow this device to wake the computer`" on $nicName ---"
   $nicPowerWake = Get-WmiObject MSPower_DeviceWakeEnable -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }
   $nicPowerWake.Enable = $True
   $nicPowerWake.psbase.Put()
   
   Write-Host "--- Enable `"Only allow a magic packet to wake the computer`" on $nicName ---"
   $nicMagicPacket = Get-WmiObject MSNdis_DeviceWakeOnMagicPacketOnly -Namespace root\wmi | where {$_.instancename -match [regex]::escape($nic.PNPDeviceID) }
   $nicMagicPacket.EnableWakeOnMagicPacketOnly = $True
   $nicMagicPacket.psbase.Put()
  }



10 comments:

  1. Hi,
    I am wondering. We also need enable "Shutdown Wake Up" in advanced settings of nic to be able to wake that computer via network. But I am not able to find that class in wmi.

    ReplyDelete
  2. Hey,

    Thanks for posting this script. I'm working with it to turn ont he NICs in my company's computers. I'm having one problem. It works on our laptops, but not our desktops. The desktops are using Intel 82578DC gigabit ethernet cards. Any idea why that would be? Any pointers would be awesome!

    ReplyDelete
  3. Hi Ondrej - Sorry for the slow response, I've been busy with other things and haven't been here since late December. I did have another post to go on how to configure settings on the advanced settings tab for a NIC, but haven't posted it. I'll see if I can find that draft and get it posted, or a least post back here with some comments on the solution. I had to solve a similar problem when I was doing the work above.

    ReplyDelete
    Replies
    1. Just posted some Windows PowerShell code below that might help you figure this out. I hope it is of some use.

      Delete
  4. Hi Anonymous - The desktops I worked with when I did the work that resulted in the post above were all configured correctly so I didn't have any issues. I've moved on to new things since doing the work above and don't have any access to a test lab or desktops at the moment, I'm working on a big Active Directory rollout at the moment. Sorry, nothing pops into my head what that might be. I do have some other draft posts on this topic that I never posted. I'll take a look at those and see if I can refresh my memory and come up with anything useful

    ReplyDelete
  5. Hi Ondrej - The advanced setting I had to set was for certain Intel cards. They have an option "Enable PME". This is a snippet of the script I used. Not sure how well this will display here ....

    # This function tests if a registry value exists, returning True if the value exists
    function Test-RegistryValue ([string] $key, [string] $name)
    {
    Get-ItemProperty -Path "$key" -Name "$name" -ErrorAction SilentlyContinue | Out-Null;
    return $?;
    }


    # List of Intel NICs that we want to check
    $IntelCardsOfInterest = @("Intel(R) 82566MM Gigabit Network Connection", `
    "Intel(R) 82566DM Gigabit Network Connection", `
    "Intel(R) 82576LM Gigabit Network Connection", `
    "Intel(R) 82577LM Gigabit Network Connection", `
    "Intel(R) 82578DM Gigabit Network Connection", `
    "Intel(R) 82579LM Gigabit Network Connection")


    # Registry path where NIC driver settings are stored
    $NICRegPathRoot = "HKLM:SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\"


    # Get all physical ethernet adaptors
    # This will also get wireless adaptors, but the whitelist above will exlude those
    $nics = Get-WmiObject Win32_NetworkAdapter -filter "AdapterTypeID = '0' AND PhysicalAdapter = 'true'"

    foreach ($nic in $nics)
    {
    # NIC index value we use this to find the right registry
    # key for the NIC we are working with
    $nicDeviceID = $nic.Caption.Substring(5,4)

    # Registry path to the for the specific NIC we are looking at
    $nicKey = $NICRegPathRoot + $nicDeviceID

    # Test if the NIC is in our whitelist above and if the "EnablePME value exists
    # Some cards are in our whitelist but don't have this setting on all models where
    # the particualr NIC installed. We only want to change this value if it exists
    If ($IntelCardsOfInterest -contains $nic.Name -and (Test-RegistryValue $nicKey "EnablePME"))
    {
    Set-ItemProperty -Path $nicKey -Name "EnablePME" -Value 1
    }
    }

    ReplyDelete
  6. Hello,

    This is great for windows7 and higher machines but can you post a vbscript version. I still have a huge number of XP machines and they don't have powershell installed.

    Lu

    ReplyDelete
  7. Hi,
    Wondering if there is a Windows 10 update for this? I see it is erroring out in our Windows 10 device event logs. I assume the WMI objects have changed?

    ReplyDelete