#########################################################################################################################
#
# 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
8/02/2013
Powershell - Report on Group Policy Objects
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
$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
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
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
############################################################################
#
# 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
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
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