Created
June 7, 2012 01:44
-
-
Save cable729/2886029 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$Global:VerbosePreference = 'silentlycontinue' | |
$Global:DebugPreference = 'silentlycontinue' | |
#Ensure that we are running the GUI from the correct location | |
Set-Location $(Split-Path $MyInvocation.MyCommand.Path) | |
$Global:Path = $(Split-Path $MyInvocation.MyCommand.Path) | |
Write-Debug "Current location: $Path" | |
#Check for PSExec | |
Write-Verbose "Checking for psexec.exe" | |
If (-Not (Test-Path psexec.exe)) { | |
Write-Warning ("Psexec.exe missing from {0}!`n Please place file in the path so UI can work properly" -f (Split-Path $MyInvocation.MyCommand.Path)) | |
Break | |
} | |
#Determine if this instance of PowerShell can run WPF | |
Write-Verbose "Checking the apartment state" | |
If ($host.Runspace.ApartmentState -ne "STA") { | |
Write-Warning "This script must be run in PowerShell started using -STA switch!`nScript will attempt to open PowerShell in STA and run re-run script." | |
Start-Process -File PowerShell.exe -Argument "-STA -noprofile -WindowStyle hidden -file $($myinvocation.mycommand.definition)" | |
Break | |
} | |
#Validate user is an Administrator | |
Write-Verbose "Checking Administrator credentials" | |
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(` | |
[Security.Principal.WindowsBuiltInRole] "Administrator")) { | |
Write-Warning "You are not running this as an Administrator!`nRe-running script and will prompt for administrator credentials." | |
Start-Process -Verb "Runas" -File PowerShell.exe -Argument "-STA -noprofile -file $($myinvocation.mycommand.definition)" | |
Break | |
} | |
#Stop and remove any jobs currently running | |
Write-Verbose "Removing PS jobs" | |
Get-Job | Remove-Job -Force -ea silentlycontinue | |
#Load Required Assemblies | |
Add-Type –assemblyName PresentationFramework | |
Add-Type –assemblyName PresentationCore | |
Add-Type –assemblyName WindowsBase | |
Add-Type –assemblyName Microsoft.VisualBasic | |
Add-Type –assemblyName System.Windows.Forms | |
#DotSource Help script | |
. ".\HelpFiles\HelpOverview.ps1" | |
#DotSource About script | |
. ".\HelpFiles\About.ps1" | |
Function Set-PoshPAIGOption { | |
If (Test-Path (Join-Path $Path 'options.xml')) { | |
$Optionshash = Import-Clixml -Path (Join-Path $Path 'options.xml') | |
$Global:maxConcurrentJobs = $Optionshash['MaxJobs'] | |
$Global:MaxRebootJobs = $Optionshash['MaxRebootJobs'] | |
If ($Optionshash['ReportPath']) { | |
$Global:reportpath = $Optionshash['ReportPath'] | |
} Else { | |
$Optionshash['ReportPath'] = $Global:reportpath = (Join-Path $Home 'Desktop') | |
} | |
} Else { | |
#Default Options | |
$optionshash = @{ | |
MaxJobs = 20 | |
MaxRebootJobs = 5 | |
ReportPath = (Join-Path $Home 'Desktop') | |
} | |
} | |
$optionshash | Export-Clixml -Path (Join-Path $pwd 'options.xml') -Force | |
} | |
#Function for Debug output | |
Function Global:Show-DebugState { | |
Write-Debug ("Number of Items: {0}" -f $Global:Listview.ItemsSource.count) | |
Write-Debug ("First Item: {0}" -f $Global:Listview.ItemsSource[0].Computer) | |
Write-Debug ("Last Item: {0}" -f $Global:Listview.ItemsSource[$($Global:Listview.ItemsSource.count) -1].Computer) | |
Write-Debug ("Max Progress Bar: {0}" -f $Global:ProgressBar.Maximum) | |
} | |
Function Global:Start-JobCleanup { | |
[Float]$Global:ProgressBar.Value = $Global:ProgressBar.Maximum | |
$End = New-Timespan $Start (Get-Date) | |
$Global:StatusTextBox.Text = "Completed in: {0}" -f $end | |
$Global:Runbutton.IsEnabled = $True | |
$StartImage.Source = "$pwd\Images\Start.jpg" | |
$Global:Cancelbutton.IsEnabled = $False | |
$CancelImage.Source = "$pwd\Images\Stop_locked.jpg" | |
} | |
#Reboot Warning Message | |
Function Show-RebootWarning { | |
$title = "Reboot Server Warning" | |
$message = "You are about to reboot servers which can affect the environment! `nAre you sure you want to do this?" | |
$button = [System.Windows.Forms.MessageBoxButtons]::YesNo | |
$icon = [Windows.Forms.MessageBoxIcon]::Warning | |
[windows.forms.messagebox]::Show($message,$title,$button,$icon) | |
} | |
Function Get-Error { | |
Process { | |
ForEach ($err in $error) { | |
Switch ($err) { | |
{$err -is [System.Management.Automation.ErrorRecord]} { | |
$hash = @{ | |
Category = $err.categoryinfo.Category | |
Activity = $err.categoryinfo.Activity | |
Reason = $err.categoryinfo.Reason | |
Type = $err.GetType().ToString() | |
Exception = ($err.exception -split ": ")[1] | |
QualifiedError = $err.FullyQualifiedErrorId | |
CharacterNumber = $err.InvocationInfo.OffsetInLine | |
LineNumber = $err.InvocationInfo.ScriptLineNumber | |
Line = $err.InvocationInfo.Line | |
TargetObject = $err.TargetObject | |
} | |
} | |
Default { | |
$hash = @{ | |
Category = $err.errorrecord.categoryinfo.category | |
Activity = $err.errorrecord.categoryinfo.Activity | |
Reason = $err.errorrecord.categoryinfo.Reason | |
Type = $err.GetType().ToString() | |
Exception = ($err.errorrecord.exception -split ": ")[1] | |
QualifiedError = $err.errorrecord.FullyQualifiedErrorId | |
CharacterNumber = $err.errorrecord.InvocationInfo.OffsetInLine | |
LineNumber = $err.errorrecord.InvocationInfo.ScriptLineNumber | |
Line = $err.errorrecord.InvocationInfo.Line | |
TargetObject = $err.errorrecord.TargetObject | |
} | |
} | |
} | |
$object = New-Object PSObject -Property $hash | |
$object.PSTypeNames.Insert(0,'ErrorInformation') | |
$object | |
} | |
} | |
} | |
Function Add-Server { | |
$server = [Microsoft.VisualBasic.Interaction]::InputBox("Enter a server name or names. Separate servers with a comma (,).", "Add Server/s") | |
If (-Not [System.String]::IsNullOrEmpty($server)) { | |
If ($server -match ",") { | |
[array]$servers = $server -split "," | |
ForEach ($server in $servers) { | |
If (-NOT [System.String]::IsNullOrEmpty($server)) { | |
$dr = $DataTable.NewRow() | |
#Add Data To Row | |
$dr.Computer = $server | |
$dr.Audited = 0 | |
$dr.Installed = 0 | |
$dr.InstallErrors = 0 | |
$dr.Services = 0 | |
$dr.Notes = $Null | |
#Add Row To Data Table | |
$DataTable.Rows.Add($dr) | |
$Global:Listview.DataContext = $DataTable | |
$b = new-object System.Windows.Data.Binding | |
$b.source = $DataTable | |
[void]$Global:Listview.SetBinding([System.Windows.Controls.ListView]::ItemsSourceProperty,$b) | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
Show-DebugState | |
} | |
} | |
} Else { | |
$dr = $DataTable.NewRow() | |
#Add Data To Row | |
$dr.Computer = $server | |
$dr.Audited = 0 | |
$dr.Installed = 0 | |
$dr.InstallErrors = 0 | |
$dr.Services = 0 | |
$dr.Notes = $Null | |
#Add Row To Data Table | |
$DataTable.Rows.Add($dr) | |
$Global:Listview.DataContext = $DataTable | |
$b = new-object System.Windows.Data.Binding | |
$b.source = $DataTable | |
[void]$Global:Listview.SetBinding([System.Windows.Controls.ListView]::ItemsSourceProperty,$b) | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
Show-DebugState | |
} | |
} | |
} | |
Function Remove-Server { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
ForEach ($server in $servers) { | |
$Global:Listview.DataContext.Rows.Find($Server).Delete() | |
} | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
Show-DebugState | |
} | |
#Report Generation function | |
Function Start-Report { | |
Write-Debug ("Data: {0}" -f $ReportComboBox.SelectedItem.Text) | |
Switch ($ReportComboBox.SelectedItem.Text) { | |
"Audit CSV Report" { | |
If ($AuditPatchReport.count -gt 0) { | |
$Global:StatusTextBox.Foreground = "Black" | |
$savedreport = Join-Path $reportpath "AuditReport.csv" | |
$AuditPatchReport | Export-Csv $savedreport -NoTypeInformation | |
$Global:StatusTextBox.Text = "Report saved to $savedreport" | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
"Audit UI Report" { | |
If ($AuditPatchReport.count -gt 0) { | |
$AuditPatchReport | Out-GridView -Title 'Audit Report' | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
"Install CSV Report" { | |
If ($InstallPatchReport.count -gt 0) { | |
$Global:StatusTextBox.Foreground = "Black" | |
$savedreport = Join-Path $reportpath "InstallReport.csv" | |
$InstallPatchReport | Export-Csv $savedreport -NoTypeInformation | |
$Global:StatusTextBox.Text = "Report saved to $savedreport" | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
"Install UI Report" { | |
If ($InstallPatchReport.count -gt 0) { | |
$InstallPatchReport | Out-GridView -Title 'Install Report' | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
"Host File List" { | |
If ($Global:Listview.Items.count -gt 0) { | |
$Global:StatusTextBox.Foreground = "Black" | |
$savedreport = Join-Path $reportpath "hosts.txt" | |
$Listview.DataContext | Select -Expand Computer | Out-File $savedreport | |
$Global:StatusTextBox.Text = "Report saved to $savedreport" | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
"Computer List Report" { | |
If ($Global:Listview.Items.count -gt 0) { | |
$Global:StatusTextBox.Foreground = "Black" | |
$savedreport = Join-Path (Join-Path $home Desktop) "serverlist.csv" | |
$Listview.DataContext | Export-Csv -NoTypeInformation $savedreport | |
$Global:StatusTextBox.Text = "Report saved to $savedreport" | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
"Error UI Report" {Get-Error | Out-GridView -Title 'Error Report'} | |
"Services UI Report" { | |
If (@($ServicesReport).count -gt 0) { | |
$ServicesReport | Out-GridView -Title 'Services Report' | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
"Services CSV Report" { | |
If (@($ServicesReport).count -gt 0) { | |
$Global:StatusTextBox.Foreground = "Black" | |
$savedreport = Join-Path $reportpath "ServicesReport.csv" | |
$ServicesReport | Export-Csv $savedreport -NoTypeInformation | |
$Global:StatusTextBox.Text = "Report saved to $savedreport" | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
} | |
} | |
} | |
#start-RunJob function | |
Function Start-RunJob { | |
Write-Debug ("ComboBox {0}" -f $RunOptionComboBox.Text) | |
If ($Global:Listview.SelectedItems.Count -gt 0) { | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
#Install Patches | |
If ($RunOptionComboBox.Text -eq 'Install Patches') { | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Installing Patches for all servers...Please Wait" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Global:Listview.SelectedItems | Select -Expand Computer) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
InstallJobFromQueue | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
InstallJobFromQueue | |
} | |
} | |
$server = $Null | |
} ElseIf ($RunOptionComboBox.Text -eq 'Audit Patches') { | |
#Audit Patches | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Auditing Patches for all servers...Please Wait" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
Write-Verbose "Creating collection queue" | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Global:Listview.ItemsSource | Select -Expand Computer) { | |
Write-Verbose "Adding $item to queue" | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
AuditJobFromQueue | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
AuditJobFromQueue | |
} | |
} | |
} ElseIf ($RunOptionComboBox.Text -eq 'Reboot Systems') { | |
#Reboot | |
If ((Show-RebootWarning) -eq "Yes") { | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Rebooting Servers..." | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
Write-Verbose "Creating collection queue" | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Global:Listview.SelectedItems | Select -Expand Computer) { | |
Write-Verbose "Adding $item to queue" | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $MaxRebootJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
RebootServerFromQueue | |
} | |
} Else { | |
for( $i = 0; $i -lt $MaxRebootJobs; $i++ ) { | |
RebootServerFromQueue | |
} | |
} | |
} | |
} ElseIf ($RunOptionComboBox.Text -eq 'Ping Sweep') { | |
#Ping | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Checking server connection..." | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
Write-Verbose "Creating collection queue" | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Global:Listview.SelectedItems | Select -Expand Computer) { | |
Write-Verbose "Adding $item to queue" | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
PingJobFromQueue | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
PingJobFromQueue | |
} | |
} | |
} ElseIf ($RunOptionComboBox.Text -eq 'Check Pending Reboot') { | |
#Check Pending Reboot | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Checking for servers with a pending reboot..." | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Global:Listview.SelectedItems | Select -Expand Computer) { | |
Write-Verbose "Adding $item to queue" | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
PendingRebootJobQueue | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
PendingRebootJobQueue | |
} | |
} | |
} ElseIf ($RunOptionComboBox.Text -eq 'Services Check') { | |
#Check Services | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Auditing Service Status on all servers...Please Wait" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
Write-Verbose "Creating collection queue" | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Global:Listview.SelectedItems | Select -Expand Computer) { | |
Write-Verbose "Adding $item to queue" | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
Get-NonRunningServicesJob | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
Get-NonRunningServicesJob | |
} | |
} | |
} | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No server/s selected!" | |
} | |
} | |
#Function to check for Non-Running services set to Automatic | |
Function Global:Get-NonRunningServicesJob { | |
Write-Debug "Queue Count: $($queue.count)" | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Checking for non running services" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location) | |
Set-Location $location | |
Try { | |
@(Get-WmiObject -ComputerName $Server -Class Win32_Service -Filter "StartMode='Auto' AND State!='Running'" -ErrorAction Stop) | |
} Catch { | |
New-Object PSObject -Property @{ | |
Error = $_.Exception.Message | |
} | |
} | |
} -ArgumentList $server,$path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
$servicedata = Receive-Job -Job $eventsubscriber.sourceobject | |
If (-Not $servicedata.Error) { | |
$servicesdata = $servicedata | | |
Select @{L='Server';E={$_.__Server}},Name,DisplayName,StartMode,State,ExitCode,StartName | |
} | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Removing Event Job" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering Event" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing background Job" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
#Update Service column | |
Write-Verbose ("Checking count of services") | |
[int]$count = ($ServiceData | Measure-Object -ErrorAction SilentlyContinue | Select -Expand Count) | |
Write-Debug ("Servicecount: {0}" -f $Count) | |
If ($ServiceData.Error) { | |
Write-Verbose ("{0}: Error returned on service check" -f $serverupdate) | |
$Listview.DataContext.Rows.Find($serverupdate).Services = 0 | |
$Listview.DataContext.Rows.Find($serverupdate).Notes = $ServiceData.Error | |
} Else { | |
Write-Verbose ("{0}: Found {1} Non running services" -f $serverupdate,$Count) | |
$Listview.DataContext.Rows.Find($serverupdate).Services = $Count | |
$Listview.DataContext.Rows.Find($serverupdate).Notes = 'Completed' | |
Write-Verbose ("Completed update of data rows") | |
If ($Count -gt 0) { | |
Write-Verbose ("Adding collection of services to global report") | |
[array]$Global:ServicesReport += $ServiceData | Where {$_.Server} | |
} Else { | |
Write-Verbose ("Nothing to report on") | |
} | |
} | |
Write-Verbose ("Checking to see if we need to continue running the jobs") | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running Get-NonRunningServicesJob" | |
Get-NonRunningServicesJob | |
} ElseIf (-NOT (Get-Job)) { | |
Write-Verbose ("Running global job cleanup") | |
Start-JobCleanup | |
} | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to check for pending patch reboot | |
Function Global:PendingRebootJobQueue { | |
Write-Debug "Queue Count: $($queue.count)" | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Checking for pending reboot" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location) | |
Set-Location $location | |
. .\Scripts\Get-ComputerRebootState.ps1 | |
Get-ComputerRebootState -Computer $server | |
} -ArgumentList $server,$path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
$status = Receive-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Removing Event Job" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering Event" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing background Job" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
Switch ($status.RebootRequired) { | |
$True {$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Reboot Required"} | |
$False {$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "OK"} | |
"NA" {$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Error"} | |
"Offline" {$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Offline"} | |
} | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running PendingRebootJobQueue" | |
PendingRebootJobQueue | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
} | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to Reboot Servers | |
Function Global:RebootServerFromQueue { | |
Param () | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Rebooting" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location) | |
$i=0 | |
If (Test-Connection -Computer $server -count 1 -Quiet) { | |
Try { | |
Restart-Computer -ComputerName $server -Force -ea stop | |
Do { | |
Start-Sleep -Seconds 2 | |
Write-Verbose "Waiting for $server to shutdown..." | |
} | |
While ((Test-Connection -ComputerName $server -Count 1 -Quiet)) | |
Do { | |
Start-Sleep -Seconds 5 | |
$i++ | |
Write-Verbose "$server down...$($i)" | |
If($i -eq 60) { | |
Write-Warning "$server did not come back online from reboot!" | |
Return $False | |
} | |
} | |
While (-NOT(Test-Connection -ComputerName $server -Count 1 -Quiet)) | |
Write-Verbose "$Server is back up" | |
Return $True | |
} Catch { | |
Write-Warning "$($Error[0])" | |
Return $False | |
} | |
} | |
} -ArgumentList $server,$path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
$results = Receive-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Updating Patch Report" | |
Write-Verbose "Removing: $($eventsubscriber.sourceobject)" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering: $($eventsubscriber.SourceIdentifier)" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing: $($eventsubscriber.SourceIdentifier)" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
If ($results) { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Online" | |
} Else { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Offline" | |
} | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running RebootServerFromQueue" | |
RebootServerFromQueue | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
} | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to gather Windows Update Log | |
Function Global:GetUpdateLogFromQueue { | |
Param ($last) | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Retrieving UpdateLog" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location,$Last) | |
Set-Location $location | |
. .\Scripts\Get-UpdateLog.ps1 | |
If ($Last) { | |
Get-UpdateLog -Computername $server -Last $last | |
} Else { | |
Get-UpdateLog -Computername $server | |
} | |
} -ArgumentList $server,$path,$last | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
$results = Receive-Job -Job $eventsubscriber.sourceobject | | |
Select Computer,Date,Time,Type,Message | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Updating Patch Report" | |
Write-Verbose "Removing: $($eventsubscriber.sourceobject)" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering: $($eventsubscriber.SourceIdentifier)" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing: $($eventsubscriber.SourceIdentifier)" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Completed" | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running GetUpdateLogFromQueue" | |
GetUpdateLogFromQueue | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
$results | Out-GridView -Title "Windows Update Log" | |
} | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to install patches in background | |
Function Global:InstallJobFromQueue { | |
If ($queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Installing Patches" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location) | |
Set-Location $location | |
. .\Scripts\Install-Patches.ps1 | |
Install-Patches -Computername $server | |
} -ArgumentList $server,$Global:path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke("Render", $Global:updatelayout, $null, $null) | |
[Array]$Global:InstallData = Receive-Job -Job $eventsubscriber.sourceobject | | |
Select Computer,Title,KB,IsDownloaded,Notes | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
If ($InstallData[0].Title -eq "NA") { | |
Write-Verbose "No updates to install" | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Installed = 0 | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Completed" | |
} Else { | |
[array]$good = $InstallData | Where {$_.Notes -ne "Failed to Install Patch"} | |
If ($good.count -lt 1) { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Installed = 0 | |
} Else { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Installed = $good.Count | |
} | |
$Global:Listview.DataContext.Rows.Find($serverupdate).InstallErrors = ($InstallData.Count - $good.Count) | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Completed" | |
} | |
Write-Verbose "Updating Patch Report" | |
[array]$Global:InstallPatchReport += $Global:InstallData | |
Write-Verbose "Removing: $($eventsubscriber.sourceobject)" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering: $($eventsubscriber.SourceIdentifier)" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing: $($eventsubscriber.SourceIdentifier)" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running InstallJobFromQueue" | |
InstallJobFromQueue | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
} | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to force Wuauclt Action of update client | |
Function Global:Invoke-WuaucltAction { | |
[cmdletbinding()] | |
Param ( | |
[string]$ServiceAction | |
) | |
Write-Debug "Queue Count: $($queue.count)" | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = ("Performing Action: {0}" -f $ServiceAction) | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location,$ServiceAction) | |
Switch ($Action) { | |
"DetectNow" { | |
Try { | |
If ((Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "wuauclt /detectnow" -ErrorAction Stop).ReturnValue -eq 0) { | |
$Result = 'Success' | |
} Else { | |
$Result = 'Failed' | |
} | |
} Catch { | |
$Result = 'Failed' | |
} | |
} | |
"ResetAuthorization" { | |
Try { | |
If ((Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "wuauclt /resetauthorization" -ErrorAction Stop).ReturnValue -eq 0) { | |
$Result = 'Success' | |
} Else { | |
$Result = 'Failed' | |
} | |
} Catch { | |
$Result = 'Failed' | |
} | |
} | |
} | |
Write-Output $Result | |
} -ArgumentList $server,$Global:path,$ServiceAction | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
Write-Verbose "Kicking off event action" | |
Write-Debug "Server: $($eventsubscriber.sourceobject.name)" | |
$result = Receive-Job -Job $eventsubscriber.sourceobject | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
If ($result = 'Success') { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = ("Completed Action: {0}" -f $ServiceAction) | |
} Else { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = ("Unable to Complete Action: {0}" -f $ServiceAction) | |
} | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Removing Event Job" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering Event" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing background Job" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
Write-Debug ("Queue: {0}" -f $queue.count) | |
Write-Debug ("Jobs: {0}" -f @(Get-Job).Count) | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running Invoke-WuaucltAction" | |
Invoke-WuaucltAction -ServiceAction $ServiceAction | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
} | |
Write-Verbose "Invoke-WuaucltAction started" | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to Invoke a service action against client wsus service | |
Function Global:Invoke-WSUSServiceAction { | |
[cmdletbinding()] | |
Param ( | |
[string]$ServiceAction | |
) | |
Write-Debug "Queue Count: $($queue.count)" | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = ("Performing Action: {0} WUAUSERVER service" -f $ServiceAction) | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location,$ServiceAction) | |
$Service = Get-Service -ComputerName $Server -Name wuauserv | |
Switch ($ServiceAction) { | |
"Stop" { | |
Try { | |
Stop-Service -InputObject $Service -ErrorAction Stop | |
$result = 'Success' | |
} Catch { | |
$result = 'Fail' | |
} | |
} | |
"Start" { | |
Try { | |
Start-Service -InputObject $Service -ErrorAction Stop | |
$result = 'Success' | |
} Catch { | |
$result = 'Fail' | |
} | |
} | |
"Restart" { | |
Try { | |
Restart-Service -InputObject $Service -ErrorAction Stop | |
$result = 'Success' | |
} Catch { | |
$result = 'Fail' | |
} | |
} | |
} | |
Write-Output $result | |
} -ArgumentList $server,$Global:path,$ServiceAction | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
Write-Verbose "Kicking off event action" | |
Write-Debug"Server: $($eventsubscriber.sourceobject.name)" | |
$result = Receive-Job -Job $eventsubscriber.sourceobject | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
If ($result = 'Success') { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = ("Completed Service {0}" -f $ServiceAction) | |
} Else { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = ("Unable to {0} service" -f $ServiceAction) | |
} | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Removing Event Job" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering Event" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing background Job" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running Invoke-WSUSServiceAction" | |
Invoke-WSUSServiceAction -ServiceAction $ServiceAction | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
Remove-Variable -Scope Global -Name Action | |
} | |
Write-Verbose "Invoke-WSUSServiceAction started" | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to Gather all installed patches on servers | |
Function Global:ListInstalledUpdates { | |
Write-Debug "Queue Count: $($queue.count)" | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Retrieving Installed Patches" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location) | |
Get-HotFix -ComputerName $server | Where {$_.Description -ne ""} | |
} -ArgumentList $server,$Global:path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
[Array]$Global:InstalledPatches += Receive-Job -Job $eventsubscriber.sourceobject | | |
Select @{L="Computer";E={$serverupdate}},Description,@{L="KB";E={$_.HotFixID}},InstalledBy,InstalledOn | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Removing Event Job" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering Event" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing background Job" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Completed" | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running ListInstalledUpdates" | |
ListInstalledUpdates | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
$Global:InstalledPatches | Out-GridView -Title "Installed Patches" | |
} | |
Write-Verbose "ListInstalledUpdates started" | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
#Function to check network connection to servers | |
Function Global:PingJobFromQueue { | |
Write-Debug "Queue Count: $($queue.count)" | |
if( $queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Checking connection" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location) | |
Test-Connection -ComputerName $server -Count 1 -Quiet | |
} -ArgumentList $server,$Global:path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
$status = Receive-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
Write-Verbose "Removing Event Job" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering Event" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing background Job" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
If ($status) { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Online" | |
} ElseIf (-Not $status) { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Offline" | |
} Else { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Unknown" | |
} | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running PingJobFromQueue" | |
PingJobFromQueue | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
} | |
Write-Verbose "PingJobFromQueue started" | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
# Function to Audit patches in background | |
Function Global:AuditJobFromQueue { | |
Write-Debug "Queue Count: $($queue.count)" | |
if ($queue.Count -gt 0) { | |
$server = $queue.Dequeue() | |
$Global:Listview.DataContext.Rows.Find($server).Notes = "Auditing Patches" | |
$j = Start-Job -Name $server -ScriptBlock { | |
param($server,$location) | |
Set-Location $location | |
. .\Scripts\Get-PendingUpdates.ps1 | |
Get-PendingUpdates -Computer $server | |
} -ArgumentList $server,$Global:path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
#Declare value for server to be updated in grid | |
$serverupdate = $eventsubscriber.sourceobject.name | |
$Global:ProgressBar.Value++ | |
$Global:Window.Dispatcher.Invoke( "Render", $Global:updatelayout, $null, $null) | |
[Array]$Global:AuditData = Receive-Job -Job $eventsubscriber.sourceobject | | |
Select Computer,Title,KB,IsDownloaded,Notes | |
Write-Verbose "Updating: $($eventsubscriber.sourceobject.name)" | |
If ($Global:AuditData[0].Title -eq "NA") { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Audited = 0 | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Completed" | |
} ElseIf ($Global:AuditData[0].Title -eq "ERROR") { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Audited = 0 | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Error with Audit" | |
} ElseIf ($Global:AuditData[0].Title -eq "OFFLINE") { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Audited = 0 | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Offline" | |
} Else { | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Audited = $Global:AuditData.Count | |
$Global:Listview.DataContext.Rows.Find($serverupdate).Notes = "Completed" | |
} | |
[array]$Global:AuditPatchReport += $Global:AuditData | |
Write-Verbose "Removing Event Job" | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Write-Verbose "Unregistering Event" | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Write-Verbose "Removing background Job" | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
If ($queue.count -gt 0 -OR (Get-Job)) { | |
Write-Verbose "Running AuditJob" | |
AuditJobFromQueue | |
} ElseIf (-NOT (Get-Job)) { | |
Start-JobCleanup | |
} | |
Write-Verbose "AuditJob started" | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
# Function to Query Active Directory for Servers | |
Function ActiveDirectoryJobFromQueue { | |
if( $queue.Count -gt 0) | |
{ | |
$domain = $queue.Dequeue() | |
Write-Verbose "Starting job for Active Directory against Domain: $domain" | |
$j = Start-Job -Name ActiveDirectoryQuery -ScriptBlock { | |
Param($domain,$location) | |
Write-Debug "Location: $location" | |
Set-Location $location | |
$strCategory = "computer" | |
$strOS = "Windows*Server*" | |
$objSearcher = [adsisearcher]"" | |
$objSearcher.SearchRoot= [adsi]"LDAP://$domain" | |
$objSearcher.Filter = ("(&(objectCategory=$strCategory)(OperatingSystem=$strOS))") | |
[void]$objSearcher.PropertiesToLoad.Add('name') | |
Write-Verbose "Checking for exempt list" | |
If (Test-Path Exempt.txt) { | |
Write-Verbose "Collecting systems from exempt list" | |
[array]$exempt = Get-Content Exempt.txt | |
} | |
$colResults = $objSearcher.FindAll() | |
foreach ($objResult in $colResults) { | |
[string]$Computer = $objResult.Properties.name | |
If ($Exempt -notcontains $Computer) { | |
Write-Output $Computer | |
} Else { | |
Write-Verbose "Excluding $computer" | |
} | |
} | |
} -ArgumentList $domain,$Path | |
Register-ObjectEvent -InputObject $j -EventName StateChanged -Action { | |
[Array]$Global:Data = Receive-Job -Job $eventsubscriber.sourceobject -Keep | Sort | |
If (-Not([string]::IsNullOrEmpty($data))) { | |
$data | ForEach { | |
$dr = $DataTable.NewRow() | |
#Add Data To Row | |
$dr.Computer = $_ | |
$dr.Audited = 0 | |
$dr.Installed = 0 | |
$dr.InstallErrors = 0 | |
$dr.Services = 0 | |
#Add Row To Data Table | |
$DataTable.Rows.Add($dr) | |
} | |
$Global:Listview.DataContext = $DataTable | |
$b = new-object System.Windows.Data.Binding | |
$b.source = $DataTable | |
[void]$Global:Listview.SetBinding([System.Windows.Controls.ListView]::ItemsSourceProperty,$b) | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
Show-DebugState | |
Remove-Job -Job $eventsubscriber.sourceobject | |
Unregister-Event $eventsubscriber.SourceIdentifier | |
Remove-Job -Name $eventsubscriber.SourceIdentifier | |
If (-NOT(Get-Job)) { | |
Start-JobCleanup | |
} Else { | |
ActiveDirectoryJobFromQueue | |
} | |
} | |
} | Out-Null | |
Write-Verbose "Created Event for $($J.Name)" | |
} | |
} | |
Function Open-FileDialog { | |
$dlg = new-object microsoft.win32.OpenFileDialog | |
$dlg.DefaultExt = "*.txt" | |
$dlg.Filter = "Text Files |*.txt;*.log" | |
$dlg.InitialDirectory = $path | |
[void]$dlg.showdialog() | |
Write-Output $dlg.FileName | |
} | |
Function Reset-DataTable { | |
#New Data Table | |
$Global:DataTable = New-Object System.Data.DataTable | |
$DataTable.TableName = 'WSUSClientTable' | |
#Create Columns with Names and Types | |
$colComp = New-Object System.Data.DataColumn Computer,([string]) | |
$colAudit = New-Object System.Data.DataColumn Audited, ([int]) | |
$colInstall = New-Object System.Data.DataColumn Installed, ([int]) | |
$colInstallError = New-Object System.Data.DataColumn InstallErrors, ([int]) | |
$colServices = New-Object System.Data.DataColumn Services, ([int]) | |
$colNotes = New-Object System.Data.DataColumn Notes, ([string]) | |
#Add Columns into Data Table | |
$DataTable.Columns.Add($colComp) | |
$DataTable.Columns.Add($colAudit) | |
$DataTable.Columns.Add($colInstall) | |
$DataTable.Columns.Add($colInstallError) | |
$DataTable.Columns.Add($colServices) | |
$DataTable.Columns.Add($colNotes) | |
#Set Primary Key for Computer | |
$DataTable.PrimaryKey = @($DataTable.Columns[0]) | |
} | |
Function Open-DomainDialog { | |
$domain = [Microsoft.VisualBasic.Interaction]::InputBox("Enter the LDAP path for the Domain or press OK to use the default domain.", | |
"Domain Query", "$(([adsisearcher]'').SearchRoot.distinguishedName)") | |
If (-Not [string]::IsNullOrEmpty($domain)) { | |
Write-Output $domain | |
} | |
} | |
#Build the GUI | |
[xml]$xaml = @" | |
<Window | |
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' | |
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' | |
x:Name='Window' Title='PowerShell Patch/Audit Utility' WindowStartupLocation = 'CenterScreen' | |
Width = '865' Height = '575' ShowInTaskbar = 'True'> | |
<Window.Background> | |
<LinearGradientBrush StartPoint='0,0' EndPoint='0,1'> | |
<LinearGradientBrush.GradientStops> <GradientStop Color='#C4CBD8' Offset='0' /> <GradientStop Color='#E6EAF5' Offset='0.2' /> | |
<GradientStop Color='#CFD7E2' Offset='0.9' /> <GradientStop Color='#C4CBD8' Offset='1' /> </LinearGradientBrush.GradientStops> | |
</LinearGradientBrush> | |
</Window.Background> | |
<Grid x:Name = 'Grid' ShowGridLines = 'false'> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*"/> | |
</Grid.ColumnDefinitions> | |
<Grid.RowDefinitions> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = '*'/> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = 'Auto'/> | |
</Grid.RowDefinitions> | |
<Menu Width = 'Auto' HorizontalAlignment = 'Stretch' Grid.Row = '0'> | |
<Menu.Background> | |
<LinearGradientBrush StartPoint='0,0' EndPoint='0,1'> | |
<LinearGradientBrush.GradientStops> <GradientStop Color='#C4CBD8' Offset='0' /> <GradientStop Color='#E6EAF5' Offset='0.2' /> | |
<GradientStop Color='#CFD7E2' Offset='0.9' /> <GradientStop Color='#C4CBD8' Offset='1' /> </LinearGradientBrush.GradientStops> | |
</LinearGradientBrush> | |
</Menu.Background> | |
<MenuItem x:Name = 'FileMenu' Header = '_File'> | |
<MenuItem x:Name = 'RunMenu' Header = '_Run' ToolTip = 'Initiate Run operation' InputGestureText ='F5'> </MenuItem> | |
<MenuItem x:Name = 'GenerateReportMenu' Header = 'Generate R_eport' ToolTip = 'Generate Report' InputGestureText ='F8'> </MenuItem> | |
<Separator /> | |
<MenuItem x:Name = 'OptionMenu' Header = '_Options' ToolTip = 'Open up options window.' InputGestureText ='Ctrl+O'> </MenuItem> | |
<Separator /> | |
<MenuItem x:Name = 'ExitMenu' Header = 'E_xit' ToolTip = 'Exits the utility.' InputGestureText ='Ctrl+E'> </MenuItem> | |
</MenuItem> | |
<MenuItem x:Name = 'EditMenu' Header = '_Edit'> | |
<MenuItem x:Name = 'SelectAllMenu' Header = 'Select _All' ToolTip = 'Selects all rows.' InputGestureText ='Ctrl+A'> </MenuItem> | |
<Separator /> | |
<MenuItem x:Name = 'ClearErrorMenu' Header = 'Clear ErrorLog' ToolTip = 'Clears error log.'> </MenuItem> | |
<MenuItem x:Name = 'ClearAllMenu' Header = 'Clear All' ToolTip = 'Clears everything on the WSUS utility.'> </MenuItem> | |
</MenuItem> | |
<MenuItem x:Name = 'ActionMenu' Header = '_Action'> | |
<MenuItem Header = 'Reports'> | |
<MenuItem x:Name = 'ClearAuditReportMenu' Header = 'Clear Audit Report' | |
ToolTip = 'Clears the current report.'> </MenuItem> | |
<MenuItem x:Name = 'ClearInstallReportMenu' Header = 'Clear Install Report' | |
ToolTip = 'Clears the current report.'> </MenuItem> | |
<MenuItem x:Name = 'ClearInstalledUpdateMenu' Header = 'Clear Installed Update Report' | |
ToolTip = 'Clears the installed update report.'> </MenuItem> | |
</MenuItem> | |
<MenuItem Header = 'Server List'> | |
<MenuItem x:Name = 'ClearServerListMenu' Header = 'Clear Server List' | |
ToolTip = 'Clears the server list.'> </MenuItem> | |
<MenuItem x:Name = 'ClearServerListNotesMenu' Header = 'Clear Server List Notes' | |
ToolTip = 'Clears the server list notes column.'> </MenuItem> | |
<MenuItem x:Name = 'OfflineHostsMenu' Header = 'Remove Offline Servers' | |
ToolTip = 'Removes all offline hosts from Server List'> </MenuItem> | |
<MenuItem x:Name = 'ResetDataMenu' Header = 'Reset Computer List Data' | |
ToolTip = 'Resets the audit and patch data on Server List'> </MenuItem> | |
</MenuItem> | |
<Separator /> | |
<MenuItem x:Name = 'HostListMenu' Header = 'Create Host List' | |
ToolTip = 'Creates a list of all servers and saves to a text file.'> </MenuItem> | |
<MenuItem x:Name = 'ServerListReportMenu' Header = 'Create Server List Report' | |
ToolTip = 'Creates a CSV file listing the current Server List.'> </MenuItem> | |
<Separator/> | |
<MenuItem x:Name = 'ViewErrorMenu' Header = 'View ErrorLog' ToolTip = 'Clears error log.'> </MenuItem> | |
</MenuItem> | |
<MenuItem x:Name = 'HelpMenu' Header = '_Help'> | |
<MenuItem x:Name = 'AboutMenu' Header = '_About' ToolTip = 'Show the current version and other information.'> </MenuItem> | |
<MenuItem x:Name = 'HelpFileMenu' Header = 'WSUS Utility _Help' | |
ToolTip = 'Displays a help file to use the WSUS Utility.' InputGestureText ='F1'> </MenuItem> | |
</MenuItem> | |
</Menu> | |
<ToolBarTray Grid.Row = '1' Grid.Column = '0'> | |
<ToolBarTray.Background> | |
<LinearGradientBrush StartPoint='0,0' EndPoint='0,1'> | |
<LinearGradientBrush.GradientStops> <GradientStop Color='#C4CBD8' Offset='0' /> <GradientStop Color='#E6EAF5' Offset='0.2' /> | |
<GradientStop Color='#CFD7E2' Offset='0.9' /> <GradientStop Color='#C4CBD8' Offset='1' /> </LinearGradientBrush.GradientStops> | |
</LinearGradientBrush> | |
</ToolBarTray.Background> | |
<ToolBar Background = 'Transparent' Band = '1' BandIndex = '1'> | |
<Button x:Name = 'RunButton' Width = 'Auto' ToolTip = 'Performs action against all servers in the server list based on checked radio button.'> | |
<Image x:Name = 'StartImage' Source = '$Pwd\Images\Start.jpg'/> | |
</Button> | |
<Separator Background = 'Black'/> | |
<Button x:Name = 'CancelButton' Width = 'Auto' ToolTip = 'Cancels currently running operations.' IsEnabled = 'False'> | |
<Image x:Name = 'CancelImage' Source = '$pwd\Images\Stop_locked.jpg' /> | |
</Button> | |
<Separator Background = 'Black'/> | |
<ComboBox x:Name = 'RunOptionComboBox' Width = 'Auto' IsReadOnly = 'True' | |
SelectedIndex = '0'> | |
<TextBlock> Audit Patches </TextBlock> | |
<TextBlock> Install Patches </TextBlock> | |
<TextBlock> Check Pending Reboot </TextBlock> | |
<TextBlock> Ping Sweep </TextBlock> | |
<TextBlock> Services Check </TextBlock> | |
<TextBlock> Reboot Systems </TextBlock> | |
</ComboBox> | |
</ToolBar> | |
<ToolBar Background = 'Transparent' Band = '1' BandIndex = '1'> | |
<Button x:Name = 'GenerateReportButton' Width = 'Auto' ToolTip = 'Generates a report based on user selection.'> | |
<Image Source = '$pwd\Images\Gen_Report.gif' /> | |
</Button> | |
<ComboBox x:Name = 'ReportComboBox' Width = 'Auto' IsReadOnly = 'True' | |
SelectedIndex = '0'> | |
<TextBlock> Audit CSV Report </TextBlock> | |
<TextBlock> Audit UI Report </TextBlock> | |
<TextBlock> Install CSV Report </TextBlock> | |
<TextBlock> Install UI Report </TextBlock> | |
<TextBlock> Services CSV Report </TextBlock> | |
<TextBlock> Services UI Report </TextBlock> | |
<TextBlock> Host File List </TextBlock> | |
<TextBlock> Computer List Report </TextBlock> | |
<TextBlock> Error UI Report </TextBlock> | |
</ComboBox> | |
<Separator Background = 'Black'/> | |
</ToolBar> | |
<ToolBar Background = 'Transparent' Band = '1' BandIndex = '1'> | |
<Button x:Name = 'BrowseFileButton' Width = 'Auto' | |
ToolTip = 'Open a file dialog to select a host file. Upon selection, the contents will be loaded into Server list.'> | |
<Image Source = '$pwd\Images\BrowseFile.gif' /> | |
</Button> | |
<Button x:Name = 'LoadADButton' Width = 'Auto' | |
ToolTip = 'Creates a list of computers from Active Directory to use in Server List.'> | |
<Image Source = '$pwd\Images\ActiveDirectory.gif' /> | |
</Button> | |
<Separator Background = 'Black'/> | |
</ToolBar> | |
</ToolBarTray> | |
<Grid Grid.Row = '2' Grid.Column = '0' ShowGridLines = 'false'> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*"/> | |
<ColumnDefinition Width="*"/> | |
<ColumnDefinition Width="*"/> | |
<ColumnDefinition Width="*"/> | |
<ColumnDefinition Width="*"/> | |
<ColumnDefinition Width="10"/> | |
<ColumnDefinition Width="Auto"/> | |
<ColumnDefinition Width="10"/> | |
<ColumnDefinition Width="Auto"/> | |
<ColumnDefinition Width="10"/> | |
<ColumnDefinition Width="Auto"/> | |
</Grid.ColumnDefinitions> | |
<Grid.RowDefinitions> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = '*'/> | |
<RowDefinition Height = '*'/> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = 'Auto'/> | |
<RowDefinition Height = 'Auto'/> | |
</Grid.RowDefinitions> | |
<GroupBox Header = "Computer List" Grid.Column = '0' Grid.Row = '2' Grid.ColumnSpan = '11' Grid.RowSpan = '3'> | |
<Grid Width = 'Auto' Height = 'Auto' ShowGridLines = 'false'> | |
<ListView x:Name = 'Listview' AllowDrop = 'True' | |
ToolTip = 'Server List that displays all information regarding statuses of servers and patches.'> | |
<ListView.View> | |
<GridView x:Name = 'GridView' AllowsColumnReorder = 'True'> | |
<GridViewColumn x:Name = 'ComputerColumn' Width = '110' DisplayMemberBinding = '{Binding Path = Computer}'> | |
<GridViewColumnHeader x:Name = 'ComputerColumnHeader' Content = 'Computer' /> | |
</GridViewColumn> | |
<GridViewColumn x:Name = 'AuditedColumn' Width = '110' DisplayMemberBinding = '{Binding Path = Audited}'> | |
<GridViewColumnHeader x:Name = 'AuditedColumnHeader' Content = 'Audited' /> | |
</GridViewColumn> | |
<GridViewColumn x:Name = 'InstalledColumn' Width = '110' DisplayMemberBinding = '{Binding Path = Installed}'> | |
<GridViewColumnHeader x:Name = 'InstalledColumnHeader' Content = 'Installed' /> | |
</GridViewColumn> | |
<GridViewColumn x:Name = 'InstallErrorColumn' Width = '110' DisplayMemberBinding = '{Binding Path = InstallErrors}'> | |
<GridViewColumnHeader x:Name = 'InstallErrorsColumnHeader' Content = 'InstallErrors' /> | |
</GridViewColumn> | |
<GridViewColumn x:Name = 'ServicesColumn' Width = '115' DisplayMemberBinding = '{Binding Path = Services}'> | |
<GridViewColumnHeader x:Name = 'ServicesColumnHeader' Content = 'NonRunningServices' /> | |
</GridViewColumn> | |
<GridViewColumn x:Name = 'NotesColumn' Width = '275' DisplayMemberBinding = '{Binding Path = Notes}'> | |
<GridViewColumnHeader x:Name = 'NotesColumnHeader' Content = 'Notes' /> | |
</GridViewColumn> | |
</GridView> | |
</ListView.View> | |
<ListView.ContextMenu> | |
<ContextMenu x:Name = 'ListViewContextMenu'> | |
<MenuItem x:Name = 'AddServerMenu' Header = 'Add Server' InputGestureText ='Ctrl+S'> </MenuItem> | |
<MenuItem x:Name = 'RemoveServerMenu' Header = 'Remove Server' InputGestureText ='Ctrl+D'> </MenuItem> | |
<Separator /> | |
<MenuItem x:Name = 'WindowsUpdateServiceMenu' Header = 'Windows Update Service' > | |
<MenuItem x:Name = 'WUStopServiceMenu' Header = 'Stop Service' > </MenuItem> | |
<MenuItem x:Name = 'WUStartServiceMenu' Header = 'Start Service' > </MenuItem> | |
<MenuItem x:Name = 'WURestartServiceMenu' Header = 'Restart Service' > </MenuItem> | |
</MenuItem> | |
<MenuItem x:Name = 'WindowsUpdateLogMenu' Header = 'WindowsUpdateLog' > | |
<MenuItem x:Name = 'EntireLogMenu' Header = 'View Entire Log' > </MenuItem> | |
<MenuItem x:Name = 'Last25LogMenu' Header = 'View Last 25' > </MenuItem> | |
<MenuItem x:Name = 'Last50LogMenu' Header = 'View Last 50' > </MenuItem> | |
<MenuItem x:Name = 'Last100LogMenu' Header = 'View Last 100' > </MenuItem> | |
</MenuItem> | |
<MenuItem x:Name = 'WUAUCLTMenu' Header = 'WUAUCLT' > | |
<MenuItem x:Name = 'DetectNowMenu' Header = 'Run Detect Now' > </MenuItem> | |
<MenuItem x:Name = 'ResetAuthorizationMenu' Header = 'Run Reset Authorization' > </MenuItem> | |
</MenuItem> | |
<MenuItem x:Name = 'InstalledUpdatesMenu' Header = 'Installed Updates' > | |
<MenuItem x:Name = 'GUIInstalledUpdatesMenu' Header = 'View Installed Updates' > </MenuItem> | |
</MenuItem> | |
</ContextMenu> | |
</ListView.ContextMenu> | |
</ListView> | |
</Grid> | |
</GroupBox> | |
</Grid> | |
<ProgressBar x:Name = 'ProgressBar' Grid.Row = '3' Height = '20' ToolTip = 'Displays progress of current action via a graphical progress bar.'> </ProgressBar> | |
<TextBox x:Name = 'StatusTextBox' Grid.Row = '4' ToolTip = 'Displays current status of operation'> Waiting for Action... </TextBox> | |
</Grid> | |
</Window> | |
"@ | |
$reader=(New-Object System.Xml.XmlNodeReader $xaml) | |
$Global:Window=[Windows.Markup.XamlReader]::Load( $reader ) | |
#Connect to all controls | |
$GenerateReportMenu = $Global:Window.FindName("GenerateReportMenu") | |
$ClearAuditReportMenu = $Global:Window.FindName("ClearAuditReportMenu") | |
$ClearInstallReportMenu = $Global:Window.FindName("ClearInstallReportMenu") | |
$SelectAllMenu = $Global:Window.FindName("SelectAllMenu") | |
$OptionMenu = $Global:Window.FindName("OptionMenu") | |
$WUStopServiceMenu = $Global:Window.FindName("WUStopServiceMenu") | |
$WUStartServiceMenu = $Global:Window.FindName("WUStartServiceMenu") | |
$WURestartServiceMenu = $Global:Window.FindName("WURestartServiceMenu") | |
$WindowsUpdateServiceMenu = $Global:Window.FindName("WindowsUpdateServiceMenu") | |
$GenerateReportButton = $Global:Window.FindName("GenerateReportButton") | |
$Global:ReportComboBox = $Global:Window.FindName("ReportComboBox") | |
$StartImage = $Global:Window.FindName("StartImage") | |
$CancelImage = $Global:Window.FindName("CancelImage") | |
$RunOptionComboBox = $Global:Window.FindName("RunOptionComboBox") | |
$ClearErrorMenu = $Global:Window.FindName("ClearErrorMenu") | |
$ViewErrorMenu = $Global:Window.FindName("ViewErrorMenu") | |
$EntireLogMenu = $Global:Window.FindName("EntireLogMenu") | |
$Last25LogMenu = $Global:Window.FindName("Last25LogMenu") | |
$Last50LogMenu = $Global:Window.FindName("Last50LogMenu") | |
$Last100LogMenu = $Global:Window.FindName("Last100LogMenu") | |
$ResetDataMenu = $Global:Window.FindName("ResetDataMenu") | |
$ResetAuthorizationMenu = $Global:Window.FindName("ResetAuthorizationMenu") | |
$ClearServerListNotesMenu = $Global:Window.FindName("ClearServerListNotesMenu") | |
$ServerListReportMenu = $Global:Window.FindName("ServerListReportMenu") | |
$OfflineHostsMenu = $Global:Window.FindName("OfflineHostsMenu") | |
$HostListMenu = $Global:Window.FindName("HostListMenu") | |
$InstalledUpdatesMenu = $Global:Window.FindName("InstalledUpdatesMenu") | |
$DetectNowMenu = $Global:Window.FindName("DetectNowMenu") | |
$WindowsUpdateLogMenu = $Global:Window.FindName("WindowsUpdateLogMenu") | |
$WUAUCLTMenu = $Global:Window.FindName("WUAUCLTMenu") | |
$GUIInstalledUpdatesMenu = $Global:Window.FindName("GUIInstalledUpdatesMenu") | |
$NotesColumnHeader = $Global:Window.FindName("NotesColumnHeader") | |
$InstallErrorsColumnHeader = $Global:Window.FindName("InstallErrorsColumnHeader") | |
$InstalledColumnHeader = $Global:Window.FindName("InstalledColumnHeader") | |
$AuditedColumnHeader = $Global:Window.FindName("AuditedColumnHeader") | |
$ComputerColumnHeader = $Global:Window.FindName("ComputerColumnHeader") | |
$AddServerMenu = $Global:Window.FindName("AddServerMenu") | |
$RemoveServerMenu = $Global:Window.FindName("RemoveServerMenu") | |
$Global:ListviewContextMenu = $Global:Window.FindName("ListViewContextMenu") | |
$ExitMenu = $Global:Window.FindName("ExitMenu") | |
$ClearInstalledUpdateMenu = $Global:Window.FindName("ClearInstalledUpdateMenu") | |
$RunMenu = $Window.FindName('RunMenu') | |
$ClearAllMenu = $Global:Window.FindName("ClearAllMenu") | |
$ClearServerListMenu = $Global:Window.FindName("ClearServerListMenu") | |
$AboutMenu = $Global:Window.FindName("AboutMenu") | |
$HelpFileMenu = $Global:Window.FindName("HelpFileMenu") | |
$Global:Listview = $Global:Window.FindName("Listview") | |
$LoadFileButton = $Global:Window.FindName("LoadFileButton") | |
$BrowseFileButton = $Global:Window.FindName("BrowseFileButton") | |
$LoadADButton = $Global:Window.FindName("LoadADButton") | |
$Global:StatusTextBox = $Global:Window.FindName("StatusTextBox") | |
$Global:ProgressBar = $Global:Window.FindName("ProgressBar") | |
$Global:RunButton = $Global:Window.FindName("RunButton") | |
$Global:CancelButton = $Global:Window.FindName("CancelButton") | |
$GridView = $Global:Window.FindName("GridView") | |
##Define Event Handlers | |
#Cancel Button Event | |
$CancelButton.Add_Click({ | |
Write-Verbose "Unregistering Events" | |
Get-EventSubscriber | Unregister-Event -Force -ErrorAction silentlycontinue | |
Write-Verbose "Cancelling all jobs" | |
Get-Job | Remove-Job -Force -ErrorAction silentlycontinue | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Action cancelled" | |
[Float]$Global:ProgressBar.Value = 0 | |
$runbutton.IsEnabled = $True | |
$StartImage.Source = "$pwd\Images\Start.jpg" | |
$Cancelbutton.IsEnabled = $False | |
$CancelImage.Source = "$pwd\Images\Stop_locked.jpg" | |
}) | |
#EntireUpdateLog Event | |
$EntireLogMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Retrieving Windows Update log from Server..." | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
GetUpdateLogFromQueue | |
} | |
} Else { | |
for( $i = 0; $i -lt $maxConcurrentJobs; $i++ ) { | |
GetUpdateLogFromQueue | |
} | |
} | |
} | |
}) | |
#Last100UpdateLog Event | |
$Last100LogMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Retrieving Windows Update log from Server..." | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
for( $i = 0; $i -le $queue.count; $i++ ) { | |
GetUpdateLogFromQueue -last 100 | |
} | |
} Else { | |
for( $i = 0; $i -lt $maxConcurrentJobs; $i++ ) { | |
GetUpdateLogFromQueue -last 100 | |
} | |
} | |
} | |
}) | |
#Last50UpdateLog Event | |
$Last50LogMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Retrieving Windows Update log from Server..." | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
for( $i = 0; $i -le $queue.count; $i++ ) { | |
GetUpdateLogFromQueue -last 50 | |
} | |
} Else { | |
for( $i = 0; $i -lt $maxConcurrentJobs; $i++ ) { | |
GetUpdateLogFromQueue -last 50 | |
} | |
} | |
} | |
}) | |
#Last25UpdateLog Event | |
$Last25LogMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Retrieving Windows Update log from Server..." | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
for( $i = 0; $i -le $queue.count; $i++ ) { | |
GetUpdateLogFromQueue -last 25 | |
} | |
} Else { | |
for( $i = 0; $i -lt $maxConcurrentJobs; $i++ ) { | |
GetUpdateLogFromQueue -last 25 | |
} | |
} | |
} | |
}) | |
#Offline server removal | |
$OfflineHostsMenu.Add_Click({ | |
Write-Verbose "Removing any server that is shown as offline" | |
$Offline = $Listview.DataContext.rows | Where {$_.Notes -eq "Offline"} | |
$Offline | ForEach { | |
Write-Verbose "Removing $($_.Computer)" | |
$_.Delete() | |
} | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
}) | |
#ResetAuthorization Event | |
$ResetAuthorizationMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Forcing Reset Authorization on Servers" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
#Set global variable for Starting service | |
$Global:ServiceAction = 'ResetAuthorization' | |
Write-Debug ("ServiceAction: {0}" -f $ServiceAction) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
for( $i = 0; $i -le $queue.count; $i++ ) { | |
Invoke-WuaucltAction -ServiceAction $ServiceAction | |
} | |
} Else { | |
for( $i = 0; $i -lt $maxConcurrentJobs; $i++ ) { | |
Invoke-WuaucltAction -ServiceAction $ServiceAction | |
} | |
} | |
} | |
}) | |
#DetectNow Event | |
$DetectNowMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Forcing Detection on Servers" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
#Set global variable for Starting service | |
$Global:ServiceAction = 'DetectNow' | |
Write-Debug ("ServiceAction: {0}" -f $ServiceAction) | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) | |
{ | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
for( $i = 0; $i -le $queue.count; $i++ ) { | |
Invoke-WuaucltAction -ServiceAction $ServiceAction | |
} | |
} Else { | |
for( $i = 0; $i -lt $maxConcurrentJobs; $i++ ) { | |
Invoke-WuaucltAction -ServiceAction $ServiceAction | |
} | |
} | |
} | |
}) | |
#Window Load Events | |
$Window.Add_Loaded({ | |
#Configure Options | |
Write-Verbose 'Updating configuration based on options' | |
Set-PoshPAIGOption | |
Write-Debug ("maxConcurrentJobs: {0}" -f $maxConcurrentJobs) | |
Write-Debug ("MaxRebootJobs: {0}" -f $MaxRebootJobs) | |
Write-Debug ("reportpath: {0}" -f $reportpath) | |
##Configure a timer to refresh window## | |
#Create Timer object | |
Write-Verbose "Creating timer object" | |
$Global:timer = new-object System.Windows.Threading.DispatcherTimer | |
#Fire off every 5 seconds | |
Write-Verbose "Adding 5 second interval to timer object" | |
$timer.Interval = [TimeSpan]"0:0:5.00" | |
#Add event per tick | |
Write-Verbose "Adding Tick Event to timer object" | |
$timer.Add_Tick({ | |
[Windows.Input.InputEventHandler]{ $Global:Window.UpdateLayout() } | |
#Write-Verbose "Updating Window" | |
}) | |
#Start timer | |
Write-Verbose "Starting Timer" | |
$timer.Start() | |
If (-NOT $timer.IsEnabled) { | |
$Window.Close() | |
} | |
###Configure Event Handlers### | |
##Sort Columns by Column Headers## | |
#Define hashtable of settings | |
$SortHash = @{} | |
Write-Verbose "Configuring Event handlers" | |
[System.Windows.RoutedEventHandler]$ColumnSortHandler = { | |
If ($_.OriginalSource -AND $_.OriginalSource.Role -ne 'Padding') { | |
$Column = $_.Originalsource.Column.DisplayMemberBinding.Path.Path | |
Write-Debug ("Sort: {0}" -f $Column) | |
If ($SortHash[$Column] -eq 'Ascending') { | |
Write-Debug "Descending" | |
$SortHash[$Column] = 'Descending' | |
} Else { | |
Write-Debug "Ascending" | |
$SortHash[$Column] = 'Ascending' | |
} | |
Write-Debug ("Direction: {0}" -f $SortHash[$Column]) | |
$lastColumnsort = $Column | |
#$view = [system.Windows.Data.CollectionViewSource]::GetDefaultView($listview.ItemsSource) | |
Write-Verbose "Clearing sort descriptions" | |
$Listview.Items.SortDescriptions.clear() | |
Write-Verbose ("Sorting {0} by {1}" -f $Column, $SortHash[$Column]) | |
$Listview.Items.SortDescriptions.Add((New-Object System.ComponentModel.SortDescription $Column, $SortHash[$Column])) | |
Write-Verbose "Refreshing View" | |
$Listview.Items.Refresh() | |
} | |
} | |
$ListView.AddHandler([System.Windows.Controls.GridViewColumnHeader]::ClickEvent, $ColumnSortHandler) | |
}) | |
#Window Events | |
$Global:Window.Add_Closed({ | |
#Stop and remove any jobs currently running | |
Write-Verbose "Removing PS jobs" | |
Get-Job | Remove-Job -Force -ea silentlycontinue | |
Remove-Variable AuditPatchReport -force -scope Global -ea 0 | |
Remove-Variable InstallPatchReport -force -scope Global -ea 0 | |
Remove-Variable content -force -scope Global -ea 0 | |
Remove-Variable StatusTextBox -Scope Global -ea 0 | |
Remove-Variable ProgressBar -Scope Global -ea 0 | |
Remove-Variable ListView -scope Global -ea 0 | |
Remove-Variable FileTextBox -ea 0 | |
Remove-Variable RunButton -scope Global -ea 0 | |
Remove-Variable ListViewContextMenu -scope Global -ea 0 | |
Remove-Variable Window -scope Global -ea 0 | |
Remove-Variable InstalledPatches -scope Global -force -ea 0 | |
Remove-Variable ServicesReport -scope Global -force -ea 0 | |
$timer.Stop() | |
}) | |
#Rightclick Event | |
$Global:Listview.Add_MouseRightButtonUp({ | |
Write-Debug "$($This.SelectedItem.Row.Computer)" | |
If ($Listview.SelectedItems.count -eq 0) { | |
$RemoveServerMenu.IsEnabled = $False | |
$InstalledUpdatesMenu.IsEnabled = $False | |
$WindowsUpdateLogMenu.IsEnabled = $False | |
$WindowsUpdateServiceMenu.IsEnabled = $False | |
$WUAUCLTMenu.IsEnabled = $False | |
} ElseIf ($Listview.SelectedItems.count -eq 1) { | |
$RemoveServerMenu.IsEnabled = $True | |
$InstalledUpdatesMenu.IsEnabled = $True | |
$WindowsUpdateLogMenu.IsEnabled = $True | |
$WindowsUpdateServiceMenu.IsEnabled = $True | |
$WUAUCLTMenu.IsEnabled = $True | |
} Else { | |
$RemoveServerMenu.IsEnabled = $True | |
$InstalledUpdatesMenu.IsEnabled = $True | |
$WindowsUpdateLogMenu.IsEnabled = $False | |
$WUAUCLTMenu.IsEnabled = $True | |
} | |
}) | |
#ListView drop file Event | |
$Global:Listview.add_Drop({ | |
$content = Get-Content $_.Data.GetFileDropList() | |
$content | ForEach { | |
$dr = $DataTable.NewRow() | |
#Add Data To Row | |
$dr.Computer = $_ | |
$dr.Audited = 0 | |
$dr.Installed = 0 | |
$dr.InstallErrors = 0 | |
$dr.Notes = $Null | |
#Add Row To Data Table | |
$DataTable.Rows.Add($dr) | |
} | |
$Global:Listview.DataContext = $DataTable | |
$b = new-object System.Windows.Data.Binding | |
$b.source = $DataTable | |
[void]$Global:Listview.SetBinding([System.Windows.Controls.ListView]::ItemsSourceProperty,$b) | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
Show-DebugState | |
}) | |
#FindFile Button | |
$BrowseFileButton.Add_Click({ | |
$File = Open-FileDialog | |
If (-Not ([system.string]::IsNullOrEmpty($File))) { | |
Get-Content $File | Where {$_ -ne ""} | ForEach { | |
$dr = $DataTable.NewRow() | |
#Add Data To Row | |
$dr.Computer = $_ | |
$dr.Audited = 0 | |
$dr.Installed = 0 | |
$dr.InstallErrors = 0 | |
$dr.Notes = $Null | |
Try { | |
#Add Row To Data Table | |
$DataTable.Rows.Add($dr) | |
} Catch { | |
Write-Warning "$($Error[0])" | |
} | |
} | |
$Global:Listview.DataContext = $DataTable | |
$b = new-object System.Windows.Data.Binding | |
$b.source = $DataTable | |
[void]$Global:Listview.SetBinding([System.Windows.Controls.ListView]::ItemsSourceProperty,$b) | |
$Global:ProgressBar.Maximum = $Global:Listview.ItemsSource.count | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Waiting for action..." | |
Show-DebugState | |
} | |
}) | |
#LoadADButton Events | |
$LoadADButton.Add_Click({ | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Querying Active Directory for Computers..." | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in (Open-DomainDialog)) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
ActiveDirectoryJobFromQueue | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
ActiveDirectoryJobFromQueue | |
} | |
} | |
}) | |
##RunButton Events | |
$RunButton.add_Click({ | |
Start-RunJob | |
}) | |
##Client WSUS Service Action | |
#Stop Service | |
$WUStopServiceMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Stopping WSUS Client service on selected servers" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
#Set global variable for Starting service | |
$Global:ServiceAction = 'Stop' | |
Write-Debug ("ServiceAction: {0}" -f $ServiceAction) | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
Invoke-WSUSServiceAction -ServiceAction $ServiceAction | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
Invoke-WSUSServiceAction -ServiceAction $ServiceAction | |
} | |
} | |
} | |
}) | |
#Start Service | |
$WUStartServiceMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Starting WSUS Client service on selected servers" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
#Set global variable for Starting service | |
$Global:ServiceAction = 'Start' | |
Write-Debug ("ServiceAction: {0}" -f $ServiceAction) | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
Invoke-WSUSServiceAction -ServiceAction $ServiceAction | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
Invoke-WSUSServiceAction -ServiceAction $ServiceAction | |
} | |
} | |
} | |
}) | |
#Restart Service | |
$WURestartServiceMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Restarting WSUS Client service on selected servers" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
#Set global variable for Starting service | |
$Global:ServiceAction = 'Restart' | |
Write-Debug ("ServiceAction: {0}" -f $ServiceAction) | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
Invoke-WSUSServiceAction -ServiceAction $ServiceAction | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
Invoke-WSUSServiceAction -ServiceAction $ServiceAction | |
} | |
} | |
} | |
}) | |
#View Installed Update Event | |
$GUIInstalledUpdatesMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Servers = $Listview.SelectedItems | Select -ExpandProperty Computer | |
[Float]$Global:ProgressBar.Maximum = $servers.count | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
$runbutton.IsEnabled = $False | |
$StartImage.Source = "$pwd\Images\Start_locked.jpg" | |
$Cancelbutton.IsEnabled = $True | |
$CancelImage.Source = "$pwd\Images\Stop.jpg" | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Gathering all installed patches on Servers" | |
$Global:updatelayout = [Windows.Input.InputEventHandler]{ $Global:ProgressBar.UpdateLayout() } | |
$Global:Start = Get-Date | |
[Float]$Global:ProgressBar.Value = 0 | |
# Read the input and queue it up | |
$Global:queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) ) | |
foreach($item in $Servers) { | |
$queue.Enqueue($item) | |
} | |
# Start up to the max number of concurrent jobs | |
# Each job will take care of running the rest | |
If ($queue.count -lt $maxConcurrentJobs) { | |
$queuecount = $queue.Count | |
for( $i = 0; $i -le $queuecount; $i++ ) { | |
ListInstalledUpdates | |
} | |
} Else { | |
for( $i = 0; $i -le $maxConcurrentJobs; $i++ ) { | |
ListInstalledUpdates | |
} | |
} | |
} | |
}) | |
#ClearAuditReportMenu Events | |
$ClearAuditReportMenu.Add_Click({ | |
Remove-Variable AuditPatchReport -scope Global -force -ea 'silentlycontinue' | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Audit Report Cleared!" | |
}) | |
#ClearInstallReportMenu Events | |
$ClearInstallReportMenu.Add_Click({ | |
Remove-Variable InstallPatchReport -scope Global -force -ea 'silentlycontinue' | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Install Report Cleared!" | |
}) | |
#ClearInstalledUpdateMenu | |
$ClearInstalledUpdateMenu.Add_Click({ | |
Remove-Variable InstalledPatches -scope Global -force -ea 'silentlycontinue' | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Installed Updates Report Cleared!" | |
}) | |
#ClearServerListMenu Events | |
$ClearServerListMenu.Add_Click({ | |
$Global:Listview.DataContext.Clear() | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:StatusTextBox.Text = "Server List Cleared!" | |
}) | |
#AboutMenu Event | |
$AboutMenu.Add_Click({ | |
Open-PoshPAIGAbout | |
}) | |
#Options Menu | |
$OptionMenu.Add_Click({ | |
#Launch options window | |
Write-Verbose "Launching Options Menu" | |
.\Options.ps1 | |
#Process Updates Options | |
Set-PoshPAIGOption | |
}) | |
#Select All | |
$SelectAllMenu.Add_Click({ | |
$ListView.SelectAll() | |
}) | |
#HelpFileMenu Event | |
$HelpFileMenu.Add_Click({ | |
Open-PoshPAIGHelp | |
}) | |
$Window.Add_KeyDown({ | |
$key = $_.Key | |
If ([System.Windows.Input.Keyboard]::IsKeyDown("RightCtrl") -OR [System.Windows.Input.Keyboard]::IsKeyDown("LeftCtrl")) { | |
Switch ($Key) { | |
"E" {$This.Close()} | |
"A" {$ListView.SelectAll()} | |
"O" { | |
.\Options.ps1 | |
#Process Updates Options | |
Set-PoshPAIGOption | |
} | |
"S" {Add-Server} | |
"D" {Remove-Server} | |
Default {$Null} | |
} | |
} ElseIf ([System.Windows.Input.Keyboard]::IsKeyDown("LeftShift") -OR [System.Windows.Input.Keyboard]::IsKeyDown("RightShift")) { | |
Switch ($Key) { | |
"RETURN" {Write-Host "Hit Shift+Return"} | |
} | |
} | |
}) | |
$Global:Window.Add_KeyUp({ | |
$Global:Test = $_ | |
Write-Debug ("Key Pressed: {0}" -f $_.Key) | |
Switch ($_.Key) { | |
"F1" {Open-PoshPAIGHelp} | |
"F5" {Start-RunJob} | |
"F8" {Start-Report} | |
Default {$Null} | |
} | |
}) | |
#AddServer Menu | |
$AddServerMenu.Add_Click({ | |
Add-Server | |
}) | |
#RemoveServer Menu | |
$RemoveServerMenu.Add_Click({ | |
Remove-Server | |
}) | |
#Run Menu | |
$RunMenu.Add_Click({ | |
Start-RunJob | |
}) | |
#Report Menu | |
$GenerateReportMenu.Add_Click({ | |
Start-Report | |
}) | |
#Exit Menu | |
$ExitMenu.Add_Click({ | |
$Global:Window.Close() | |
}) | |
#ClearAll Menu | |
$ClearAllMenu.Add_Click({ | |
Reset-DataTable | |
If ($Global:Listview.DataContext) { | |
$Global:Listview.DataContext.Clear() | |
} | |
$content = $Null | |
[Float]$Global:ProgressBar.value = 0 | |
$Global:StatusTextBox.Foreground = "Black" | |
$Global:patchreport = $Null | |
$Global:StatusTextBox.Text = "Waiting for action..." | |
}) | |
#Clear Server List notes | |
$ClearServerListNotesMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null} | |
} | |
}) | |
#Save Server List | |
$ServerListReportMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Global:StatusTextBox.Foreground = "Black" | |
$savedreport = Join-Path (Join-Path $home Desktop) "serverlist.csv" | |
$Listview.DataContext | Export-Csv -NoTypeInformation $savedreport | |
$Global:StatusTextBox.Text = "Report saved to $savedreport" | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
}) | |
#HostListMenu | |
$HostListMenu.Add_Click({ | |
If ($Global:Listview.Items.count -gt 0) { | |
$Global:StatusTextBox.Foreground = "Black" | |
$savedreport = Join-Path $reportpath "hosts.txt" | |
$Listview.DataContext | Select -Expand Computer | Out-File $savedreport | |
$Global:StatusTextBox.Text = "Report saved to $savedreport" | |
} Else { | |
$Global:StatusTextBox.Foreground = "Red" | |
$Global:StatusTextBox.Text = "No report to create!" | |
} | |
}) | |
#Report Generation | |
$GenerateReportButton.Add_Click({ | |
Start-Report | |
}) | |
#Clear Error log | |
$ClearErrorMenu.Add_Click({ | |
Write-Verbose "Clearing error log" | |
$Error.Clear() | |
}) | |
#View Error Event | |
$ViewErrorMenu.Add_Click({ | |
Get-Error | Out-GridView | |
}) | |
#ResetServerListData Event | |
$ResetDataMenu.Add_Click({ | |
Write-Verbose "Resetting Server List data" | |
$Listview.ItemsSource | ForEach {$_.Notes = $Null;$_.Audited = 0;$_.Installed = 0;$_.InstallErrors = 0;$_.Services = 0} | |
}) | |
Reset-DataTable | |
[void]$Global:Window.ShowDialog() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment