Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

Sunday, 28 July 2013

Joining a Domain with Windows PowerShell

Another quick Windows PowerShell post.  Once again I'm sitting in front of a newly built Windows Server 2012 machine running only Server Core.  This time I want to join the machine to my Active Directory domain.

All very easy with Windows PowerShell ...

New-Computer -Domain home.lab -Credential HOME\Administrator -Restart

Provide the password when prompted and wait for the machine to restart.

Easy easy easy .....

IP Address Configuration with Windows PowerShell

Once again I'm sitting in front of a newly built Windows Server 2012 machine running only Server Core in my lab at home.  This time I want to configure some IP address settings on the new machine.

The following Windows PowerShell commands get the job done:

Step #1

I need to get details about my network adapters so I run the following command.

Get-NetAdapter

Get-NetAdapter Results










Step #2

Now I can configure the adaptor I want.  I this case there is only one, so it is easy to select the correct one.  My address details are as follows:

IP: 192.168.33.10
Gateway: 192.168.33.1
Mask: 255.255.255.0

To configure this configuration I run the following command:

New-NetIPAddress -IPAddress 192.168.33.10 `
   -Default Gateway 192.168.33.1 `
   -AddressFamily IPv4 `
   -PrefixLength 24 `
   -InterfaceIndex 19

New-NetIPAddress Results

















Step #3

Finally I want to configure some DNS settings. This is the command I run:

Set-DnsClientServerAddress `
       -ServerAddress 192.168.33.2 `
       -InterfaceIndex 19
                  

That's it!!! Easy.

Friday, 26 July 2013

Rename a Computer Using Windows PowerShell

Short and sweet.  I'm sitting in front of a newly built Windows Server 2012 machine running only Server Core and I want to rename the machine.  It is a new machine not yet in a domain and I'm logged in with the default Administrator account.

It is easy with Windows PowerShell ...

Rename-Computer -NewName LABSVR2 -Restart

How easy is that?

Monday, 29 April 2013

Adding Audit Rules (SACLs) to Active Directory Objects

As part of the work I'm currently doing with Active Directory, my customer requires auditing of user, group and computer object deletions.  The group policy setting "Audit Directory Service Changes" enables the required auditing at an audit policy level, but the system access control lists (SACLs) for the objects don't include deletions by default.  I needed a way to configure all user, group and computer objects in the domain to include such a SACL entry.

Firstly, what are SACLs?  SACLs identify the users and groups that you want to audit when they successfully access or fail to access an object and can be configured not only to include the user or group you are interested in, but also the type of access.  The following screen grab shows the default auditing configured at the root of a new Windows Server 2012 Active Directory domain.


Default auditing on the root of a W2K12 Active Directory



I wanted to configure the SACLs as a task sequence action during the System Center Configuration Manager OSD task sequence I have developed for my customer, so I turned to Windows PowerShell.  After running my script, the auditing configured at the root of the domain looks like this:


Auditing on the root of the domain after the script has run


This is the script I came up with:



#------------------------------------------------------
# | File : ADDSAuditSettings.ps1                                        
# |                                            
# | Purpose : Configures extra auditing (SACLs) at for the
# | new domain
# |
# | Usage : PowerShell.exe -FILE .\ADDSAuditSettings.ps1 
#------------------------------------------------------
# |                                         
# | Author:          JustAnotherTechnicalBlog
# | Creation Date:   26 April 2013
# |
# |
# | Maintenance History                                            
# | ------------------- 
# | 
# | Version:  1.00  2013-04-26  Initial Version  JustAnotherTechnicalBlog
# |
# |
#------------------------------------------------------


# Clear the error variable
#------------------------------------------------------
$error.clear()


# Import the ActiveDirectory PowerShell Module if required
#------------------------------------------------------
if (-not (Get-Module ActiveDirectory))
  {
   Import-Module ActiveDirectory
  }

# This fuction takes a schema GUID ID and a security  
# principal and enables a new SACL entry so deletions
# of target object type by the specified security 
# principal will be audited
#------------------------------------------------------
Function AuditDeletions {

  Param (
         [Parameter(Mandatory=$true)]
         [system.guid]$SchemaIDGUID,
         [Security.Principal.NTAccount]$SecurityPrincipal  
        )

  # Get the DN for the current domain
  #------------------------------------------------------
  $dn = (Get-ADDomain).DistinguishedName

  # Get the current ACLs for the root of the domain
  #------------------------------------------------------
  $acl = Get-ACL -Audit -Path AD:\$dn

  # Build the new SACL rule.
  # This rule will enable auditing of succesful deletion 
  # of our target object.  The rule will be inherited 
  # throughout the domain
  #------------------------------------------------------
  $Rule = New-Object System.DirectoryServices.ActiveDirectoryAuditRule `
                     $SecurityPrincipal, `
                     "DeleteChild", `
                     "Success", `
                     $SchemaIDGUID, `
                     "All"

  # Add the new audit rule to the ACL we 
  # opened earlier
  #------------------------------------------------------
  $acl.AddAuditRule($Rule)

  # Commit the new audit rule
  #------------------------------------------------------
  Set-ACL -Path AD:\$dn -AclObject $acl

}


# To work with AD objects we need the relevent schema
# ID GUIDs. variables to hold these:
#------------------------------------------------------
$ComputerSchemaIDGUID = "bf967a86-0de6-11d0-a285-00aa003049e2"
$GroupSchemaIDGUID    = "bf967a9c-0de6-11d0-a285-00aa003049e2"
$UserSchemaIDGUID     = "bf967aba-0de6-11d0-a285-00aa003049e2"


# The AuditDeletions function above requires a security 
# principal.  user/group we want to audit?
#------------------------------------------------------
$who = "Everyone"


# Put the AuditDeletions function to use ....
#------------------------------------------------------
AuditDeletions $ComputerSchemaIDGUID $who
AuditDeletions $GroupSchemaIDGUID $who
AuditDeletions $UserSchemaIDGUID $who


# Basic error handling
#------------------------------------------------------
If ($error)
  {
   Write-Host "Audit setting configurations failed"
   Exit 1003
  }
Else
  {
   Write-Host "Audit setting configurations completed OK"
  }

Tuesday, 23 April 2013

Automating Active Directory Setup - Install a Child Domain

In previous posts over the past few weeks I've explained how I've installed the Active Directory Domain Services role and provisioned the first domain controller in a root domain using Configuration Manager OSD task sequences and some Windows PowerShell code. The next thing I need to do is install the first domain controller in a subordinate child domain in the new forest. The child domain will hold all my computing resources and users.

The following script:

  • Installs a new domain controller in a child domain, creating that new domain.
  • Gets the variables you will see in the script from Configuration Manager.
  • Creates the new domain within the previously created forest
  • Ensures DNS delegations are created
#-------------------------------------------------------------------
# | File : NewChildDomain.ps1                                           
# |                                            
# | Purpose : Installs the first Domain Controller in a child domain, 
# |           thus creating the new domain
# |           - Designed to be run from a Configuration Manager OSD 
# |             task sequence
# |           - Designed for Windows Server 2012 environments
# |           - Reboot handled by task sequence
# |
# | Usage : PowerShell.exe -FILE .\NewChildDomain.ps1 
#-------------------------------------------------------------------
# |                                         
# | Author:          JustAnotherTechnicalBlog
# | Creation Date:   23 April 2013
# |
# |
# | Maintenance History                                            
# | ------------------- 
# | 
# | Version:  1.00  2013-04-23  Initial Version  JustAnotherTechnicalBlog
# |
# |
#-------------------------------------------------------------------


# Clear the error variable
#-------------------------------------------------------------------
$error.clear()


# Import the ActiveDirectory PowerShell Module if required
#-------------------------------------------------------------------
if (-not (Get-Module ActiveDirectory))
  {
   Import-Module ActiveDirectory
  }


# Here we get access to the Task Sequence variables
#-------------------------------------------------------------------
$objTSenv = New-Object -COMObject Microsoft.SMS.TSEnvironment


# Grab the data we need from the task sequence variables
#-------------------------------------------------------------------
$strTSNetBIOSName =  $objTSenv.Value("RoleVariable1")
$strTSDomainName  =  $objTSenv.Value("RoleVariable2")
$strTSPrntNBName  =  $objTSenv.Value("RoleVariable3")
$strTSPrntDmnName =  $objTSenv.Value("RoleVariable4")
$strTSPrntDmnAcct = "$strTSPrntNBName\" + $objTSenv.Value("RoleAccount2")
$strTSDNSAccount  = "$strTSPrntNBName\" + $objTSenv.Value("RoleAccount3")


# Convert our password to the data type required by Install-ADDSDomain
#-------------------------------------------------------------------
$secstrSafeModePassword = $objTSenv.Value("RoleAccountPassword1") | `
      ConvertTo-SecureString -asPlainText -Force


# Convert our accounts and passwords strings to the data type required
# by Install-ADDSDomain
#-------------------------------------------------------------------
$secstrDomainPassword = $objTSenv.Value("RoleAccountPassword2") | `
     ConvertTo-SecureString -asPlainText -Force
$DomainCreds = New-Object `
     System.Management.Automation.PSCredential("$strTSPrntDmnAcct",$secstrDomainPassword)

$secstrDNSPassword = $objTSenv.Value("RoleAccountPassword3") | `
     ConvertTo-SecureString -asPlainText -Force
$DNSCreds = New-Object `
     System.Management.Automation.PSCredential("$strTSDNSAccount",$secstrDNSPassword)



# Install our first forest Domain Controller, creating a new forest
#-------------------------------------------------------------------
Install-ADDSDomain `
  -Force `
  -NoRebootOnCompletion `
  -CreateDNSDelegation `
  -DomainType Child `
  -DomainMode Win2012 `
  -ParentDomainName "$strTSPrntDmnName" `
  -NewDomainNetBIOSName "$strTSNetBIOSName" `
  -NewDomainName "$strTSDomainName" `
  -SafeModeAdministratorPassword $secstrSafeModePassword `
  -DNSDelegationCredential $DNSCreds `
  -Credential $DomainCreds



# Basic error handling
#-------------------------------------------------------------------
If ($error)
  {
   Write-Host "Child domain creation failed"
   Exit 1001
  }
Else
  {
   Write-Host "Child domain created successfully"



Task Sequence Snippet:  Active Directory Installation

Installing an Active Directory Child Domain with Windows PowerShell

Monday, 15 April 2013

Automating Active Directory Setup - Installing the Active Directory Domain Services Role

I've been working on a OSD task sequence to deploy Active Directory in a Windows 2012 environment for my current customer.  They have many environments in production, and many more in the development, testing and quality assurance environments, so this is something they need to be automated and repeatable.

The screen sot below shows the snippet of a larger task sequence that installs many different roles, features, and applications all in one task sequence.  Variables assigned to the computer object when we provision the computer object in Configuration Manager drive what roles, features and applications get installed.  I'm not going to show how that works here, but it may be something I explain in separate posts at some stage.

The first step to install Active Directory is to install the Active Directory Domain Services role.  The screen shots below show how that is done in the task sequence.  I just use Windows PowerShell to do this with the following command:

#-----------
PowerShell.exe -COMMAND Install-WindowsFeature -Name AD-Domain-Services `
   -IncludeManagementTools

The code above does not create an domain controller. It just installs the Active Directory Domain Services role.  Other steps in the task sequence see the server promoted to be a domain controller.

Including the 'IncludeManagementTools' option sees the appropriate management tools, and Windows PowerShell modules, get installed.  This works on both the standard and core installations of Windows, with the installer being intelligent enough to know what to install base on what edition of Windows Server is being installed.


Task Sequence Snippet:  Active Directory Installation


Installing the Active Directory Domain Services Role with Windows PowerShell

Wednesday, 21 November 2012

Script to fix SCCM Multicast Issue (KB2419357)

I've been working with getting multicast distribution points working with SCCM 2007 R2 recently and one of the challenges is that there is a bug where some WDS settings are not correctly updated on the target server. Microsoft Knowledge Base article KB2419357 documents the issue.

I wrote the following script to update the required settings instead of having to do this manually. The script also makes a change to the ‘ApBlockSize’ setting for WDS, in our environment, where the server is on a 1GB switch port and the clients are on a remote segment on a 100MB switch port, this setting significantly reduced packet fragmentation and increased the speed of the multicast download. I have it in a package and advertise the script to servers hosting multicast enabled distribution points.

# ------------------------------------------------------------------
# Purpose: Applies some registry settings, mostly related to the 
# problem identified in KB2419357. It also makes a change to WDS 
# network settings to improvea packet fragmentation issue identified
# during testing of multicast with SCCM
# 
# Usage : powershell.exe -file .\wdsconfig.ps1
# 
# Version 1.0
# 
# Maintenance History
# ------------------------------------------------------------------
# Version - Date - Change - Author
# ------------------------------------------------------------------
# 1.0 21/11/12 Script Created JustAnotherTechnicalBlog
# 
# ------------------------------------------------------------------

# Set variables
$WDSRegRoot = "HKLM:System\CurrentControlSet\Services\WDSServer"
$WDSService = "Windows Deployment Services Server"


# Write the required SCCM options to the WDS configuration settings
# to the registry
If (Test-Path $WDSRegRoot\Parameters)
{
 Set-ItemProperty -Path $WDSRegRoot\Parameters -Name McStartAddr `
                                               -Value "239.10.10.10"
 Set-ItemProperty -Path $WDSRegRoot\Parameters -Name McEndAddr `
                                               -Value "239.10.10.10"
 Set-ItemProperty -Path $WDSRegRoot\Parameters -Name UdpStartPort `
                                               -Value "63000"
 Set-ItemProperty -Path $WDSRegRoot\Parameters -Name UdpEndPort `
                                               -Value "64000"
}


# Tune the network settings for the WDS server to reduce likelihood
# of packet fragmentation
If (Test-Path $WDSRegRoot\Providers\WDSMC\Protocol)
{
 Set-ItemProperty -Path $WDSRegRoot\Providers\WDSMC\Protocol `
                                               -Name ApBlockSize `
                                               -Value 1385
}


# Restart the Windows Deployment Services Server service
if (Get-Service $WDSService -ea SilentlyContinue)
{
 Restart-Service -displayname $WDSService
}

Wednesday, 27 June 2012

Scripting Balloon Messages in Windows

Do you know those balloons that pop-up in the notification area in Windows to tell you something? I've always thought it would be nice to be able to use those in certain situations when doing something to an end user computer in the corporate environments I work in. Several months ago I figured this out and then today I was reminded of it when I was shown a script at a new customer site that uses the same idea. With that thought in my head I figured it would make a good topic to write about here. I'm going to show two examples.

The first example is the script I've 'borrowed' from a colleague today. In the environment this script was written for, the available Configuration Manager notification options after software updates have been installed doesn't quiet meet the business requirements so a script has been created to notify the user a restart is required and the Configuration Manager software update deployments have been configured to neither notify the end user nor restart the computer. The script is triggered whenever an end user logs on or unlocks their workstation. I’ll explain how that has been configured later.

The script is very simple in that it queries the operating system to see if it is waiting for a restart after patching. If Windows Update is waiting for a restart the script pops a balloon message to the end user.  Here is the script:


#
# 
# Purpose:  Prompts end user to restart if Windows is waiting for a restart after
#           patching
# 
# Usage : powershell.exe -file .\PatchingRestartNagBalloon.ps1
# 
# Version 1.0
# 
# Maintenance History
# ----------------------------------------------------------------------
# Version   -    Date      -    Change           -       Author
# ----------------------------------------------------------------------
# 1.0            25/06/12       Script Created           justanothertechnicalblog
# 
# 


$SoftwareUpdateRestartStatus = New-Object -ComObject "Microsoft.Update.SystemInfo"
$IsRebootRequired = $SoftwareUpdateRestartStatus.RebootRequired

If ($IsRebootRequired -eq $True)
{
[void] [System.Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms”)

$notification = New-Object System.Windows.Forms.NotifyIcon 

#Define the icon for the system tray
$notification.Icon = [System.Drawing.SystemIcons]::Information

#Display title of balloon window
$notification.BalloonTipTitle = “Software Updates”

#Type of balloon icon
$notification.BalloonTipIcon = “Info”

#Notification message
$notification.BalloonTipText = “Software updates have been installed on your computer. Please save your work and restart your computer as soon as possible”

#Make balloon tip visible when called
$notification.Visible = $True

#Call the balloon notification
$notification.ShowBalloonTip(0)
start-sleep -s 10

#Make balloon tip invisible when called
$notification.Visible = $False
 Exit-PSSession
}
Else
{
 Exit-PSSession
}

The second example is the script I wrote some months ago for another customer. When we built new machines for that customer, new computer objects were created in a 'Provisioning' OU in Active Directory and it was up to the technical staff who built machines to then move the new computer object to the correct Active Directory OU. Like busy first level support teams the world over, these guys were busy and often forgot this step, especially when the rest to of the workstation provisioning process was fully automated. Trying to dynamically determin the correct OU for a new machine was not possible for several reasons, so instead I wrote this script to notify the end user to take action if the machine was still in the OU where the Configuration Manager task sequence put it. I wanted a notification balloon and if the user clicked the balloon I wanted Ineternet Explorer to open to the Service Delivery team's web site so a ticket could be logged. This is what I came up with after stealing ideas from a number of places and asking for a bit of help from the resident Exchange guru who knew his PowerShell better than me. I'd reference where I got the ideas from, but it was months ago and I don't recall them all.  I also don't have enough comments in the script to remind me why I've done certain things, but that just makes reading the code more fun right?

#
# 
# Purpose:  Prompts end user to contact the Service Desk and opens IE to the
#           Service Desk home page
# 
# Usage : powershell.exe -f .\ActiveDirectoryOUNagBalloon.ps1
# 
# Version 1.0
# 
# Maintenance History
# ----------------------------------------------------------------------
# Version   -    Date      -    Change           -       Author
# ----------------------------------------------------------------------
# 1.0            25/06/12       Script Created           justanothertechnicalblog
# 
# 

function Show-BalloonTip
{
    # Requires -Version 2.0
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNull()]
        [String]$BalloonTipText,
        [Parameter(Position = 1)]
        [String]$BalloonTipTitle = 'PowerShell Event Notificaton',
        [Parameter(Position = 2)]
        [ValidateSet('Error', 'Info', 'None', 'Warning')]
        [String]$BalloonTipIcon = 'Info'
    )
    end 
    {
        Add-Type -AssemblyName System.Windows.Forms
        Add-Type -AssemblyName System.Drawing
        [Windows.Forms.ToolTipIcon]$BalloonTipIcon = $BalloonTipIcon
        $NotifyIcon = New-Object Windows.Forms.NotifyIcon -Property @{
            BalloonTipIcon = $BalloonTipIcon
            BalloonTipText = $BalloonTipText
            BalloonTipTitle = $BalloonTipTitle
            Icon = [Drawing.Icon]::ExtractAssociatedIcon((Get-Command powershell).Path)
            Text = -join $BalloonTipText[0..62]
            Visible = $true
        }
        switch ($BalloonTipIcon) 
        {
            Error {[Media.SystemSounds]::Hand.Play()}
            Info {[Media.SystemSounds]::Asterisk.Play()}
            None {[Media.SystemSounds]::Beep.Play()}
            Warning {[Media.SystemSounds]::Exclamation.Play()}
        }
        $NotifyIcon.ShowBalloonTip(0)
        switch ($Host.Runspace.ApartmentState) 
        {
            STA 
            {
                $null = Register-ObjectEvent -InputObject $NotifyIcon -SourceIdentifier "BalloonTipClicked_event" -EventName BalloonTipClicked -Action{
                    #Write-Host "Starting IE"
                    Start-Process 'c:\Program Files\Internet Explorer\iexplore.exe' -ArgumentList 'http://justanothertechnicalblog.blogspot.com.au/' -WindowStyle Maximized -Verb Open
                    $Sender.Dispose()
                    $global:clicked = $true
                    Unregister-Event $EventSubscriber.SourceIdentifier
                    Remove-Job $EventSubscriber.Action
                }
            }
            default 
            {
                continue
            }
        }
     }
 }
 
Get-EventSubscriber | Unregister-Event | Out-Null
#Write-Host $Host.Runspace.ApartmentState
Show-BalloonTip "Some location information for this computer has not been configured correctly.  Please contact the Service Desk resolve this issue.  This is a minor issue and should not impact your use of this machine" "Computer Configuration Warning" "Warning"

$global:clicked = $false
$timeOut=20 #20 Seconds
for($timeOut;$timeOut -gt 0;$timeOut--)
{
    if($global:clicked)
    {
        break;
    }
    #Write-Host "Sleeping 1 second"
    Start-Sleep -Milliseconds 1000
    
}


NOTE: This script doesn't exit properly when run from the PowerShell ISE. It runs without issue if run from the command prompt.

Update: After doing some reading today I found this article from Microsoft. I definately used this when I originaly wrote my script above:

Displaying a Message in the Notification Area

How and when do I run these scripts?  Well in both instanaces at both customers the scripts are run via a scheduled task.  Group Policy Preferences lets you schedule tasks across your desktop fleet and that is what has been used.  The task scheduler can fire a scrript on an event and two very useful events are a logon event and a screen unlock event.  I'm not going to detail how to set up scheduled tasks using Group Policy Preferences today, that sounds like a nice topic for another post, but take a look at GPP and you'll figure it out.

The other thing to note about the scripts above is that they display a command prompt when run.  Yuk.  This is no good when you have gone to the work to implement a nice neat balloon pop-up solution to notify your end users of something.  How do we stop PowerShell displaying the command prompt window?  Well, that is also a topic for another post, but I've written it along with this one.  Click here to view two solutions I've used.

Tuesday, 26 June 2012

Hide the PowerShell Window

I have a number of scripts I run in the desktop environment that are triggered using scheduled tasks.  These scripts run in the user context.  An unfortunate problem with PowerShell is that it displays a window when it runs, even if it is running as a batch job and no user input or output is involved.  I don't want my end users seeing this window (a black command window), so have tried a number of things and have found two ways to hide it.  Neither of these are ideal, it would be nice to hide this window using PowerShell itself but I haven't found a way to do that.

Method One
This is the method I've used for some time, though I think that the second method below might be the better solution as it uses native tools available in Windows, where this solution requires a third party tool.

Download Hidden Start

Once you have the utility, you can use it like this to hide a running PowerShell script:

%SystemDir%\Scripts\hstart.exe /NOCONSOLE /SILENT "POWERSHELL.EXE -FILE %SystemDir%\Scripts\MyScript.ps1"

Warning:  Some security software suites will detect this tool as 'bad' so if you have problems with it, check you security software logs to see if the utility is being treated as malware.

Update: While writing this post I found the Hidden Start now requires a license for commercial use. I'm pretty sure this was a free tool in the past when I've downloaded it.  This will rule it out for a lot of you I'm sure.

Method Two
This method uses a vbScript to call the PowerShell script as a hidden window. This is not sophisticated but does work. There are a number of ways to do this, but the following little script is quiet cute as you can reuse this code and just pass a new script to it on the command line. The scheduled task would run something like this:

cscript.exe %SystemDrive%\Scripts\RunPowerShellScriptHidden.vbs %SystemDrive%\Scripts\MyScript.ps1

' ----------------------------------------------------------------------

' 
' Purpose:  Prompts end user to contact the Service Desk and opens IE to the
'           Service Desk home page
' 
' Usage : cscript.exe RunPowerShellScriptHidden.vbs mypath\myscript.ps1
' 
' Version 1.0
' 
' Maintenance History
' ----------------------------------------------------------------------
' Version   -    Date      -    Change           -       Author
' ----------------------------------------------------------------------
' 1.0            25/06/12       Script Created           justanothertechnicalblog
' 
' 


Option Explicit

'Variables
Dim oShell, ScriptName, appCmd

' Read target script path from command line argument or echo usage details if arguments are wrong
If WScript.Arguments.Count = 1 Then
ScriptName = WScript.Arguments.Item(0)
Else
Wscript.Echo "Usage: RunPowerShellScriptHidden path\powershellscript"
Wscript.Quit
End If


'Create objects
Set oShell = CreateObject("WScript.Shell")

' Build the command line
appCmd = "PowerShell.exe -file " + ScriptName 

'Run the PowerShell script now
oShell.Run appCmd, 0, false

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()
  }