Pages

Showing posts with label WSUS. Show all posts
Showing posts with label WSUS. Show all posts

8/02/2013

Powershell - Report on Group Policy Objects


#########################################################################################################################
#
#   GPO-REPORT.PS1
#
#   Create a report of the status of all WSUS GPO's
#

import-module grouppolicy

$today = get-date
$outfile = "gpostatus.html"
$key = "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\au"

$days = @{"0" = "Every Day"; "1" = "Every Sunday"; "2" = "Every Monday"; "3" = "Every Tuesday"; "4" = "Every Wednesday"; "5" = "Every Thursday"; "6" = "Every Friday"; "7" = "Every Saturday"}

$gpobjs = get-gpo -all -domain usa.DOMAIN.com | where {$_.DisplayName -like "Software Update*"}

"<HTML>" | out-file $outfile
"<HEAD>" | out-file $outfile -append
"<TITLE></TITLE>" | out-file $outfile -append
"</HEAD>" | out-file $outfile -append
'<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">' | out-file $outfile -append
'<H2>WSUS Group Policy Status</H2>' | out-file $outfile -append
'<H4>' + $today + '</H4><table bordercolor=#000000;  border=2px; cellspacing=0;>' | out-file $outfile -append
'<tr><td ><b><font face="monospace" size="3"> Policy </font></td>' | out-file $outfile -append
'<td ><b><font face="monospace" size="3"> Modified </font></td>' | out-file $outfile -append
'<td ><b><font face="monospace" size="3"> Enabled/Disabled </font></td>' | out-file $outfile -append
'<td ><b><font face="monospace" size="3"> Configuration </font></td>' | out-file $outfile -append
'<td ><b><font face="monospace" size="3"> Install Day </font></td>' | out-file $outfile -append
'<td ><b><font face="monospace" size="3"> Install Hour </font></td>' | out-file $outfile -append
'</tr>' | out-file $outfile -append

$gpobjs | foreach-object {
    $name = $_.DisplayName
 
write-host $name
 
    $modified = $_.ModificationTime
    $enabledvalue = get-gpregistryvalue -name $name -key $key -valuename noautoupdate
    if ($enabledvalue.value -eq "0") {
        $enabled = "enabled"
        }
    else {
        $enabled = "disabled"
        }
    $optionvalue = get-gpregistryvalue -name $name -key $key -valuename auoptions

    if ($optionvalue.value -eq "2") {
        $option = "2-Notify Only"
        }
    elseif ($optionvalue.value -eq "3") {
        $option = "3-Download & Notify"
        }
    elseif ($optionvalue.value -eq "4") {
        $option = "4-Download & Install"
        }
    else {
        $option = $optionvalue.value
        }

    $dayvalue = (get-gpregistryvalue -name $name -key $key -valuename scheduledinstallday).value | out-string
    $dayvalue = $dayvalue -replace "\s+", ""
    $day = $days[$dayvalue]
    $hour = (get-gpregistryvalue -name $name -key $key -valuename scheduledinstalltime).value
    
    if ($enabled -eq "disabled") {
    $option = " "
    $day = " "
    $hour = " "
    }
    '<tr><td ><font face="monospace" size="2">' + $name + '</font></td>' | out-file $outfile -append
    '<td ><font face="monospace" size="2">' + $modified + '</font></td>'  | out-file $outfile -append
    '<td ><font face="monospace" size="2">' + $enabled + '</font></td>'  | out-file $outfile -append
    '<td ><font face="monospace" size="2">' + $option + '</font></td>'  | out-file $outfile -append
    '<td ><font face="monospace" size="2">' + $day + '</font></td>'  | out-file $outfile -append
    '<td ><font face="monospace" size="2">' + $hour + '</font></td></tr>'  | out-file $outfile -append

}#foreach object

"</TABLE></BODY></HTML>" | out-file $outfile -append

9/04/2011

Powershell: reset WSUS client for list of servers

##################################################################################
#
# WSUS Client Cleanup and Reinitialize
#
##################################################################################

$today = get-date

$list = get-content LIST.TXT

"=========================================================================="
" WSUS Client Cleanup and Reinitialize"
$today

foreach($server in $list) {
"--------------------------------------------------------------------------"
#net stop wuauserv
($svc = Get-WmiObject Win32_Service -ComputerName $server -Filter "name='wuauserv'") | out-null
if ($svc.started -eq $true) {
write $server "stopping wuauserv"
$result=$svc.StopService()
}
($svc = Get-WmiObject Win32_Service -ComputerName $server -Filter "name='wuauserv'") | out-null
if ($svc.started -eq $false) {
write $server "wuauserv stopped"
}

#Backup Registry
$result=([WmiClass]"\\$server\ROOT\CIMV2:Win32_Process").create("c:\windows\regedit /e c:\WSUS.REG HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate")
write $server "Backup Registry RESULT=" $result.returnvalue

#Cleanup Registry
write $server "Reg Clean"
$key = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate"
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $server)
$regKey = $reg.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate", $true)
if ($regKey.getvalue('AccountDomainSid')) {
$regKey.DeleteValue('AccountDomainSid')
"...removed AccountDomainSid"
}
if ($regKey.getvalue('PingID')) {
$regKey.DeleteValue('PingID')
"...removed PingID"
}
if ($regKey.getvalue('SusClientId')) {
$regKey.DeleteValue('SusClientId')
"...removed SusClientId"
}

$key2 = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update"
$regKey = $reg.OpenSubKey($key2, $true)
if ($regKey.getvalue('LastWaitTimeout')) {
$regKey.DeleteValue('LastWaitTimeout')
"...removed LastWaitTimeout"
}
if ($regKey.getvalue('DetectionStartTime')) {
$regKey.DeleteValue('DetectionStartTime')
"...removed DetectionStartTime"
}
if ($regKey.getvalue('NextDetectionTime')) {
$regKey.DeleteValue('NextDetectionTime')
"...removed NextDetectionTime"
}
if ($regKey.getvalue('AUState')) {
$regKey.DeleteValue('AUState')
"...removed AUState"
}
write $server "WSUS Reg Clean Completed"

#net start wuauserv
($svc = Get-WmiObject Win32_Service -ComputerName $server -Filter "name='wuauserv'") | out-null
if ($svc.StartMode -ne "Disabled") { $svc.StartService() | out-null } else {"wuauserv startup was disabled"}
($svc = Get-WmiObject Win32_Service -ComputerName $server -Filter "name='wuauserv'") | out-null
if ($svc.started) {
write $server "wuauserv started successfully"
}

#RESET WUAUCLT
$result=([WmiClass]"\\$server\ROOT\CIMV2:Win32_Process").create("wuauclt /resetauthorization /detectnow")
write $server "wuauclt reset RESULT=" $result.returnvalue

} #foreach
"=========================================================================="
##################################################################################

#is it necessary to clear WMI connections to free resources? If so how?
#if exist before attempting reg key remove

#RESULT CODES
# 0 {"$s Successful Completion."}
# 2 {"$s Access Denied."}
# 3 {"$s Insufficient Privilege."}
# 8 {"$s Unknown failure."}
# 9 {"$s Path Not Found."}
# 21 {"$s Invalid Parameter."}

Groups.ps1

#powershell to create text files in a subdirectory with group members of a list of groups

$root=([ADSI]"").distinguishedName

$Groups=get-content groups.txt
$Folder=".\wsus-groups\"

foreach ($Group in $Groups) {
$out = $Folder+$Group+".TXT"
$outfile = $out -replace ' ','-'
#delete output file if it exists
if ( test-path $outfile ) { remove-item $outfile }

# "-----------------------------------"
# $Group+":"
$Group = [ADSI]("LDAP://CN=$Group,CN=Users,"+$root)
$list1 = $Group.member -Replace '\,.*$', ''
$list = $list1 -Replace 'CN=',''
# $list
$list | out-file -encoding ASCII $outfile -append
}

6/09/2011

POWERSHELL List Updates in WSUS

[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer('WSUS02',$False,80)
#Get all updates
$updates = $wsus.GetUpdates()
#Iterate every update and output some basic info about it
$collection = @()
ForEach ($update in $updates) {
#$update
$product = $update.ProductTitles
$product.type
 $obj = New-Object System.Object
 $obj | Add-Member -type NoteProperty -name Date -value $update.CreationDate.ToString()
 $obj | Add-Member -type NoteProperty -name Approved -value $update.IsApproved.ToString()
 $obj | Add-Member -type NoteProperty -name Class -value $update.UpdateClassificationTitle
 $obj | Add-Member -type NoteProperty -name Product -value $product
 $obj | Add-Member -type NoteProperty -name Title -value $update.Title
 $collection += $obj 
}#ForEach

$collection | Sort-Object Date | export-csv .\updates.csv -force

5/25/2011

Re-register WSUS Client with Powershell

I went ahead and coded this using PowerShell. But I find that using WMI in PowerShell I think I seem to have more failures. But I did not take the time to confirm that suspicion.

$server = 'MACHINE-NAME'
 
#net stop wuauserv
$svc = Get-WmiObject Win32_Service -ComputerName $server -Filter "name='wuauserv'"
    if ($svc.started -eq $true) {
        write-host $server "stopping wuauserv"
        $svc.StopService()
    }
    if ($svc.started -eq $false) {
        write-host $server "wuauserv stopped"
    }
 
#Backup Registry
$result=([WmiClass]"\\$server\ROOT\CIMV2:Win32_Process").create("c:\windows\regedit /e c:\WSUS.REG HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate")
write-host $server "Backup Registry RESULT=" $result.returnvalue
 
#Cleanup Registry
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $server)
$regKey = $reg.OpenSubKey('SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate', $true)
$regKey.DeleteSubKey('AccountDomainSid')
$regKey.DeleteSubKey('PingID')
$regKey.DeleteSubKey('SusClientId')
$regKey = $reg.OpenSubKey('SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update', $true)
$regKey.DeleteSubKey('LastWaitTimeout')
$regKey.DeleteSubKey('DetectionStartTime')
$regKey.DeleteSubKey('NextDetectionTime')
$regKey.DeleteSubKey('AUState')
 
write-host $server "WSUS Reg Clean Completed"
 
#net start wuauserv
$svc = Get-WmiObject Win32_Service -ComputerName $server -Filter "name='wuauserv'"
$svc.StartService()
    if ($svc.started -eq $true) {
        write-host $server "wuauserv started"
    }
 
#RESET WUAUCLT
$result=([WmiClass]"\\$server\ROOT\CIMV2:Win32_Process").create("wuauclt /resetauthorization /detectnow")
write-host $server "wuauclt reset RESULT=" $result.returnvalue

3/28/2011

WSUS Client Troubleshooting - Getting Serious

Tons of good stuff here: wsuswiki.com

I found several VM's that weren't deployed properly (Geez SYSPREP for petes sake!!!!!)

I'm probably just going to run the following on all 400 of them just to be sure:

psexec @list.txt -u administrator -C c:\rereg.bat
Which references the following that must be on c:\ of the machine where the above is run:

@echo off
net stop wuauserv
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate" /v AccountDomainSid /f
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate" /v PingID /f
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate" /v SusClientId /f
REG DELETE "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v LastWaitTimeout /f
REG DELETE "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v DetectionStartTime /f
REG DELETE "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v NextDetectionTime /f
REG DELETE "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v AUState /f
net start wuauserv
wuauclt /resetauthorization /detectnow 

WSUS Client Troubleshooting

From Technet

Test all the following from the client machine.
- Check network communications with server
- ping WSUS-Server
- http://WSUS-Server[:port] - should get response - e.g. Under Construction
- http://WSUSServerName/selfupdate/wuident.cab
- Should result in offer to download a file - hit cancel
- if not, go to this URL: Check Self-Update Tree
- Check Automatic Update Client
- Open CMD prompt and type
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate
- Should display something like:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate
WUServer    REG_SZ  http://WSUSServerName
WUStatusServer      REG_SZ  http://WSUSServerName
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU
- Reset Automatic Update Client
- Open CMD prompt and type wuauclt.exe /resetauthorization /detectnow
- Wait 10 minutes
- Check C:\Windows\WindowsUpdate.log
- Check "All Computers" group on the WSUS Server to see if it appears.

3/27/2011

Powershell: Import Group Members

This script will be used to import a file of the same format that I export from the previous post. After using Excel to review and change the listings. I use these group memberships to filter group policy permissions to apply WSUS client settings to servers.

############################################################################
#
# IMPORT-SERVER-GROUP.PS1
#
# Assign servers to WSUS group from CSV file.  
# Note:  removes server from any existing groups that contain WSUS
#
# CSV Format:  (include headings)
#
#  Server, Group
#  SERVER01, WSUS Test Group
#
############################################################################

$list = @(Import-Csv WSUS-TEST.CSV)
$today = get-date

"==========================================================================="
" CHANGE LOG - " + $today

foreach ( $item in $list ) {
 $account = $item.Server;
 $target = $item.Group;

"---------------------------------------------------------------------------"
 "    " + $account

#Find computer object and remove it from groups
 $ds = new-object directoryServices.directorySearcher 
 $ds.filter = "(&(objectCategory=computer)(objectClass=user)(name=$account))" 
 $dn = $ds.findOne() 
 if ($dn) { #found
  #remove computer from groups
  $user = [ADSI]$dn.path 
  "      Removed from groups:"
  foreach ($group in $user.memberof)
   {
   $groupDE = [ADSI]"LDAP://$group" 
   "        "+$group
   if ($strGroup -match "WSUS") {
    $groupDE.remove("LDAP://$($user.distinguishedName)")  
    }#if
   }#foreach
 }#if

$dn=0;

#Find group object and add server to it
 $ds = new-object directoryServices.directorySearcher 
 $ds.filter = "(&(objectClass=Group)(name=$target))" 
 $dn = $ds.findOne() 
 if ($dn) { #found Group
  $group = [ADSI]$dn.path 
  $groupDE = [ADSI]"LDAP://$($group.distinguishedname)" 
  $ds.filter = "(&(objectCategory=computer)(objectClass=user)(name=$account))" 
  $dn = $ds.findOne()
  if ($dn) { #found machine account
   $usr = [ADSI]$dn.path
   $ADuser = [ADSI]"LDAP://$($usr.distinguishedname)"
   "      Added to " + $target
   $groupDE.add("LDAP://$($ADuser.distinguishedName)")  
   }#if
 }#if
}#foreach
"==========================================================================="
############################################################################

Powershell: Export Group Membership

Putting the pieces together
This post pulls together some of my previous fragments into something more specifically useful.

###########################################################################
#
#  server-group.ps1
#
#       Export group membership for each Windows Server in AD
#              if the group name contains WSUS
#
###########################################################################

#delete output file if it exists
if ( test-path wsus-server-groups.csv ) { remove-item wsus-server-groups.csv }

# Create $list of AD machine accounts for Windows Servers 
$strCategory = "computer" 
$strOS = "Windows*Server*"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry 
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher 
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = ("OperatingSystem=$strOS")
$colProplist = "dnshostname"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults) { 
    $objComputer = $objResult.Properties;  
    $Server = $objComputer.dnshostname
    $Server = $Server -replace "\s{2,}", ""
    $Server = $Server -replace "\.USA\.DOMAIN\.COM", ""
    if ($Server) { $list = $list + $Server } #skip a null value
    }#foreach
"Server, Group" | out-file -encoding ASCII  wsus-server-groups.csv # output headings
foreach ($target in $list) {
    $ds = new-object directoryServices.directorySearcher 
    $ds.filter = "(&(objectCategory=computer)(objectClass=user)(name=$target))" 
    $dn = $ds.findOne() 
    if ($dn) { #found
       $user = [ADSI]$dn.path 
       $userDE = [ADSI]"LDAP://$($user.distinguishedname)" 
       $user.name
       $groups = $user.memberof
       foreach($group in $groups) {               {
           $strGroup = $group.split(',')[0]
           $strGroup = $strGroup.split('=')[1] 
           "     "+$strGroup
           if ($strGroup -match "WSUS") {
               $Target+", "+$strGroup | out-file -encoding ASCII  wsus-server-groups.csv -append
               }#if
           }#foreach
    }#if
}#foreach
###########################################################################

1/24/2011

Powershell: WSUS

I suppose you might just say "DUH!" but I have to say again to myself if nobody else, PowerShell is very powerful and useful.
Here are some useful fragments I've got from a little tinkering with dates.
Again it's no surprise that TechNet was very useful. Especially this Powershell Tip about dates.

List the computers from WSUS and all info about them.
$WSUSserver="WSUS02"
$WSUSList="c:\export\WSUS\DATA\WSUSLIST.TXT"
New-Item $WSUSList -Type file -Force >$nul
#Get WSUS list
function Get-WSUSComputers()
{
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($WSUSserver,$false)
$wsus.GetComputerTargets()
}
Get-WSUSComputers | Sort LastReportedStatusTime |`
Select * | `
Out-File -FilePath $WSUSList -Force
And, how about a list of machines for which last reported status was over a week ago.
$WSUSserver="WSUS02"
$today = Get-Date
$today = $today.touniversaltime()
$datecheck = $today.adddays(-7)
$WSUSList="c:\audit\DATA\NOTREPORTING.TXT"
New-Item $WSUSList -Type file -Force >$nul
#Get WSUS list
function Get-WSUSComputers()
{
    [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
    $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($WSUSserver,$false)
    $wsus.GetComputerTargets()
}
Get-WSUSComputers | Sort LastReportedStatusTime |`
Select FullDomainName, LastReportedStatusTime | where {$_.LastReportedStatusTime -le $datecheck} | `
ft -auto | `
Out-File -FilePath $WSUSList -Force