Categories

9227

Patch Tuesdays 2012

I’ve shown these functions before but as we head rapidly towards 2012 we need to plan next years schedules.  One perennial for Windows administrators is patching – therefore we need to know patch Tuesdays. This is next years offenders

10 January 2012
14 February 2012
13 March 2012
10 April 2012
08 May 2012
12 June 2012
10 July 2012
14 August 2012
11 September 2012
09 October 2012
13 November 2012
11 December 2012

 

How do we arrive at these dates – simple look at a Calendar or better still use these functions

function get-secondTuesday {            
param([datetime]$date)            
    switch ($date.DayOfWeek){            
        "Sunday"    {$patchTuesday = $date.AddDays(9); break}             
        "Monday"    {$patchTuesday = $date.AddDays(8); break}             
        "Tuesday"   {$patchTuesday = $date.AddDays(7); break}             
        "Wednesday" {$patchTuesday = $date.AddDays(13); break}             
        "Thursday"  {$patchTuesday = $date.AddDays(12); break}             
        "Friday"    {$patchTuesday = $date.AddDays(11); break}             
        "Saturday"  {$patchTuesday = $date.AddDays(10); break}             
     }            
     $patchTuesday.ToLongDateString()            
}            
            
function Get-PatchTuesday {            
param (            
    [parameter(ValueFromPipeline=$true)]            
    [int]$year = (Get-Date).Year,            
                
    [switch]$nextmonth            
    )            
                 
    if ($nextmonth){            
        $now = Get-Date            
        $d = Get-Date -Day 1 -Month $($now.Month + 1) -Year $now.Year            
        get-secondTuesday $d            
    }            
    else {            
        1..12 | foreach {            
            $d = [datetime]"$_/1/$year"            
            get-secondTuesday $d            
        }                
    }            
}


We run the function like this



Get-PatchTuesday -year 2012



It takes the year and for each month in the year creates a datetime object for the first of the month.  That date is fed to the get-secondtuesday function which looks at the day of the week and calculates the second Tuesday.



If your patching Window is a specific day in the month then modify the functions to calculate those dates and feed them straight to your change control process

Using AccountManagement classes to set local accounts expiry

This is a little more verbose than the WinNT example

function set-expirydate {            
[CmdletBinding(SupportsShouldProcess=$true)]            
param (            
 [parameter(ValueFromPipeline=$true,            
   ValueFromPipelineByPropertyName=$true)]            
 [string]$computer,            
             
 [parameter(ValueFromPipeline=$true,            
   ValueFromPipelineByPropertyName=$true)]            
 [string]$id              
)            
BEGIN {Add-Type -AssemblyName System.DirectoryServices.AccountManagement}             
PROCESS {               
 switch ($computer){            
  "."    {$computer = $env:computername}            
  "localhost" {$computer = $env:computername}            
 }            
             
 $ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine            
 $context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext `
    -ArgumentList $ctype, $computer            
            
 $user = [System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($context, $id)            
             
## set the expiry date            
if ($psCmdlet.ShouldProcess("$id", "Expiry date set ")) {            
    $user.AccountExpirationDate = (Get-Date).AddDays(2)            
    $user.Save()            
  }            
}              
}


Set the context to machine and use the machine name to define which machine.  Find the user and set the AccountExpirationDate property then save

Setting local account expiry dates

Setting expiry dates on AD accounts is a common occurrence and is well documented. Setting expiry dates on local accounts is also possible

$user = [adsi]"WinNT://./Test1, user"            
            
$expirydate = (Get-Date).AddDays(2)            
            
$user.Put("AccountExpirationDate", $expirydate)            
$user.SetInfo()            
            
$user.RefreshCache()            
            
$user | Format-List *


This uses the WinNT (remember its case sensitive) ADSI connector to get a local account.  We then set the AccountExpirationDate property to the desired date – in this case two days from now.



Quick call to SetInfo() and we are done

Windows updates: 4 tidy up get-update

Looking at the get-update function we created earlier I wanted to tidy it up a bit.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033

function get-update {
[CmdletBinding()] 
param
 ( 
 
[switch]$hidden
 
) 

PROCESS{

$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()

# 0 = false & 1 = true
if ($hidden
){
 
$result = $searcher.Search("IsInstalled=0 and Type='Software' and ISHidden=1"
 )
}

else
 {
 
$result = $searcher.Search("IsInstalled=0 and Type='Software' and ISHidden=0"
 )
}


if ($result.Updates.Count -gt 0
){
 
$result.Updates |
 
 
select Title, IsHidden, IsDownloaded, IsMandatory,
 
 
IsUninstallable, RebootRequired, Description
}
else
 {
 
Write-Host " No updates available"
} 

}
#process

<# .SYNOPSIS Discovers available updates .DESCRIPTION Interrogates Windows updates for available software updates only. Optional parameter to display hidden updates .PARAMETER hidden A switch to display the hidden updates .EXAMPLE get-update Displays non-hidden updates .EXAMPLE get-update -hidden Displays hidden updates #>



}

Primary changes are:

  • to add a switch to the function to control the display of hidden updates
  • count the available updates and display message if there aren’t any
  • add more properties to the output- 7 properties defaults to a list so more readable as well
  • add comment based help

Windows Updates: 3 Installing Updates

Now we have discovered the updates we have available we can think about installing them.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037

function install-update {

$session = New-Object -ComObject Microsoft.Update.Session
$searcher = $session.CreateUpdateSearcher()

$result = $searcher.Search("IsInstalled=0 and Type='Software' and ISHidden=0" )

if ($result.Updates.Count -eq 0
) {
 
Write-Host "No updates to install"
}
else {
$result.Updates | select Title
}

$downloads = New-Object -ComObject Microsoft.Update.UpdateColl

foreach ($update in $result.
Updates){
 
$downloads.Add($update
)
}
 

$downloader = $session.CreateUpdateDownLoader()
$downloader.Updates = 
$downloads
$downloader
.Download()

$installs = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($update in $result.
Updates){
 
if ($update.
IsDownloaded){
  
$installs.Add($update
)
 }
}


$installer = $session.CreateUpdateInstaller()
$installer.Updates = 
$installs
$installresult
 = $installer.Install()
$installresult

}

 

The function looks for non-hidden software updates that aren’t hidden.  At the moment I want some control over driver updates. If there are updates available they are added to a download collection and then downloaded.

The update collection returned from our original search is automatically updated with the fact the update is now downloaded.

We create an installer, add the updates to it and install.

The function is still a bit rough but it works and better still illustrates how the COM objects work.

Next jobs are to tidy up the functions and extend the functionality to remote machines!

Identity and Access Management

Realtime Publishers have just published my "book" The Essentials Series: Enterprise Identity and Access Management.  Its a free download from http://nexus.realtimepublishers.com/ESEIAM.htm.

Enjoy

 

Share this post :

 

Technorati Tags: ,,