Project: Apply Windows hotfixes to certain users in AD group by using PowerShell

20. April 2015

ps

PowerShell Version: >2
Modules: none

Today I am documenting a little script I worked on that needed some workarounds and tweaks to function. Basically, we have a GPO that acts on shutdown (to save users a restart after hotfix installation) and should be applied for the whole domain. Some users in this domain use RDP and need these specific hotfixes so I had to find a way to apply a machine based GPO with a script to a group of users. Also, the RDC 8.1 hotfixes need to be applied in a specific order (KB2574819, KB2830477, KB2857650, KB2913751, KB3036965, KB2862019), which is why I can not work with foreach here.

#receive username from logon script
$user = Get-Content 'C:\tmp\$variables.txt' | select -index 0

$os = (Get-WMIObject Win32_OperatingSystem).name
$wusa = "C:\windows\system32\wusa.exe"
$userGroups = ([Security.Principal.WindowsIdentity]"$($user)").Groups.Translate([System.Security.Principal.NTAccount])
$LogPath = "c:\tmp\hotfixes.log"
$date = Get-Date -Format "dd.MM.yyyy hh:mm"

Start-Transcript -Path $LogPath
# Windows 7 Client hotfixes
if ($os -like "*Windows 7*")
{
    # Remotedesktop hotfixes
    if ($userGroups -like "*main_rdp_group")
    {
    "##########################################################"
    "#                   $date"
    "##########################################################"
    "User: $user"
    "Hostname: $env:COMPUTERNAME"
    "##########################################################"
    # https://support.microsoft.com/en-us/kb/2830477
    # Remote Desktop Connection (RDC) 8.1
    "Installing Windows6.1-KB2574819-v2-x64.msu..."
    & $wusa \\path_to_ad_share\Windows6.1-KB2574819-v2-x64.msu /quiet /norestart
    "Installing Windows6.1-KB2830477-x64.msu..."
    & $wusa \\path_to_ad_share\Windows6.1-KB2830477-x64.msu /quiet /norestart
    "Installing Windows6.1-KB2857650-x64.msu..."
    & $wusa \\hpath_to_ad_share\Windows6.1-KB2857650-x64.msu /quiet /norestart
    "Installing Windows6.1-KB2913751-x64.msu..."
    & $wusa \\path_to_ad_share\Windows6.1-KB2913751-x64.msu /quiet /norestart
    
    # https://support.microsoft.com/en-us/kb/3036965
    # Printing preferences window appears behind a RemoteApp window in Windows
    "Installing Windows6.1-KB3036965-x6.msu..."
    & $wusa \\path_to_ad_share\Windows6.1-KB3036965-x64.msu /quiet /norestart

    # https://support.microsoft.com/en-us/kb/2862019
    # A RemoteApp application main window takes the focus after the applications windows are maximized in Windows
    "Installing Windows6.1-KB2862019-x64.msu..."
    & $wusa \\path_to_ad_share\Windows6.1-KB2862019-x64.msu /quiet /norestart
    }
}
Stop-Transcript

As the computer based GPO would use the computername$ as the username when running, I had to find a way to get the actual username for my group-filter:

$user = Get-Content 'C:\tmp\$variables.txt' | select -index 0

I simply added some lines at the end of the existing logon script:

# check if c:\tmp exists...
$path_to_c_tmp = Test-Path c:\tmp
if ($path_to_c_tmp -eq $true)
    {
    # Gather variables for further scripts
    $env:USERNAME | Out-File 'C:\tmp\$variables.txt'
    $env:COMPUTERNAME | Out-File 'C:\tmp\$variables.txt'-Append
    $PSVersionTable.PSVersion.Major | Out-File 'C:\tmp\$variables.txt'-Append
    }
    else
    {
    # if c:\tmp does not exist create it and continue with gathering variables for further scripts
    "c:\tmp does not exist, creating...."
    New-Item c:\tmp -type directory
    # check if creation was successfull
    if ($? -eq $true)
        {
        "Success!"
        # Gather variables for further scripts
        $env:USERNAME | Out-File 'C:\tmp\$variables.txt'
        $env:COMPUTERNAME | Out-File 'C:\tmp\$variables.txt'-Append
        $PSVersionTable.PSVersion.Major | Out-File 'C:\tmp\$variables.txt'-Append
        }
        else
        {
        "Something went wrong..."
        }
    }

In this example we would only use the $env:USERNAME but I added computername and psversion also for further projects. I can now call every line of the C:\tmp\$variables.txt file with  | select -index number_of_line and use this to make the if ($userGroups -like “*main_rdp_group”) work. (If c:\tmp does not exist it will create it and gather the information again.)

I will continue working on this script to enable results in the logs and more filter options for other hotfixes. The goal here is to have one script to apply all hotfixes in the environment to the assigned target group.

#PowerShell

Leave a Reply

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


*