RAM usage continues to spiral up
hou8182 opened this issue · 2 comments
I am running PoshRSJob version 1.7.3.8 and I am having trouble with ever-increasing RAM usage when running my multithreaded jobs from my machine. The script that I am having an issue with is listed below. It's a patching script that compares patch files from my server repository against what has already been installed on the target machines. If the target machines don't have a specific patch, it is installed remotely.
Please let me know if you can think of the reason why my RAM usage continues to go up to the point where it freezes my machine. Thanks for your help and for the awesome module!
Here is the code for my patching script. It works pretty well for the most part, but like I said, I can watch the RAM usage on my machine continue to increase until I run out of memory and freeze my machine.
Please provide a code example showing the issue, if applicable:
#region - Load Prereqs
#Elevate if not running as Admin
Param([switch]$Elevated)
Function Check-Admin {
$currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)}
if ((Check-Admin) -eq $false){
if ($elevated)
{# could not elevate, quit
}
else {Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))}
exit}
Function Install-RSJob{
if (Get-Module -ListAvailable -Name PoshRSJob) {Write-Host "PoshRSJob module already installed" -ForegroundColor Green }
else {Write-Host "PoshRSJob Module was not found, installing now.... " -ForegroundColor Yellow
Copy-Item -Path "$PSScriptRoot\PoshRSJob" -Recurse -Destination "\$env:COMPUTERNAME\c$\Program Files\WindowsPowerShell\Modules\PoshRSJob" -Force
Import-Module –Name PoshRSJob
cls
if (Get-Module -ListAvailable -Name PoshRSJob) {Write-Host "PoshRSJob successfully installed." -ForegroundColor Green}
else {"ERROR, PoshRSJob unable to be installed...."}}
Get-ChildItem "C:\Program Files\WindowsPowerShell\Modules\PoshRSJob" -Recurse | Unblock-File}
Install-RSJob
#endregion - Prereqs Loaded
$Computers = Get-Content "$PSScriptRoot\computers.txt"
$ServerRepo = "\PatchServer\Patch Repository"
Param($computer)
#region ---------- Ping Check
$starttimer= Get-Date
$ConnCheck = Test-Connection $Computer -Count 1 -Quiet -ErrorAction SilentlyContinue
if ($ConnCheck -eq $false)
{Write-Verbose "$computer is offline" -Verbose
$stoptimer = Get-Date #------Collects end time
$ReportDate = Get-Date -Format ("yyyy-MM-dd")
$resultsarray = @()
$eachcomputer = [ordered]@{ "Computer" = $computer
"SysArch" = "offline"
"OS Version" = "offline"
"OS Build" = "offline"
"Start Time" = $starttimer
"Stop Time" = $stoptimer
"Elapsed Time in Hours" = [math]::round(($stoptimer - $starttimer).TotalHours , 2)
"New Patches Installed" = "offline"
"Previously Installed" = "offline"
"Skipped/Doesn't Apply" = "offline" }
$newobj = New-Object psobject -Property $eachcomputer
$resultsarray += $newobj
Write-Verbose "Attempting to grab mutex" -Verbose
$mtx = New-Object System.Threading.Mutex($false, "Global\TestMutex")
If ($mtx.WaitOne(500))
{
Write-Verbose "Recieved mutex!" -Verbose
$log = "$using:psscriptroot\Logs$ReportDate -PatchReport.csv"
Write-Verbose "Writing data to $log" -Verbose
$resultsarray | Export-Csv -Path $log -NoTypeInformation -Append
Write-Verbose "Releasing mutex" -Verbose
[void]$mtx.ReleaseMutex() }
Else { Write-Warning "Timed out acquiring mutex!" }
Return
}
#endregion - Ping Check
Else{
psexec 2> $null \$computer -s -d powershell Enable-PSRemoting -force
Start-Sleep -Seconds 5
$remotearray = @()
$InstalledPatches = @()
$SkippedCounter = 0
$SkippedArray = @()
$PrevInstallPatches = @()
$kbArticlearray = @()
Function mAdSwitch{
Param(
[String]$Switch,
[String]$InstallLine,
[String]$InstallPath,
[String]$File
)
#------Exit command for installation commands
$exitline = "exit"
#------Passed Switch parameter to remove files within Local Repository
if($Switch -eq "Cleanup"){
Remove-Item $InstallPath\mAd.cmd -Force -ErrorAction SilentlyContinue
Remove-Item $InstallPath\$File -ErrorAction SilentlyContinue
}
#------Passed Switch parameter to prepare Local Repository for an installation
if($Switch -eq "Install"){
#------Checks if mAd.cmd exists on target computer
$CMDchecker = Test-Path $InstallPath\mAd.cmd
if($CMDchecker -eq $True){
#------Clears computers Local Repository for installation
Clear-Content -Path $InstallPath\mAd.cmd -ea SilentlyContinue
}
else{
#------Creates cmd file if it does not exist
New-Item -Path "$InstallPath\mAd.cmd" -ItemType File
}
#------Populates cmd file with installation commands
Add-Content -Value $InstallLine -Path $InstallPath\mAd.cmd
Add-Content -Value $exitline -Path $InstallPath\mAd.cmd
}
}
Function Check-Mutex{
#check for existing Mutex file
$Mutex = "\\$computer\c$\Local_Repository\Mutex.csv"
if((Test-Path $Mutex) -eq $false){New-Item -ItemType File -Path $Mutex -ErrorAction SilentlyContinue}
#Attempt to grab Mutex
Write-Verbose "Attempting to grab mutex" -Verbose
$checkmutex = (Get-Content "\\$computer\c$\Local_Repository\Mutex.csv")
$timestart = Get-Date
if($checkmutex -eq "ON")
{Write-Verbose "Mutex currently ON, waiting 5 seconds..." -Verbose
do{ sleep -Seconds 5
$timecheck = Get-Date
$timealive = ($timecheck - $timestart).Minutes
$checkmutex = Get-Content "\\$computer\c$\Local_Repository\Mutex.csv"}
until(($checkmutex -eq "OFF") -or ($timealive -ge "15") -eq $true)
$timealive = ($timecheck - $timestart).seconds
if($timealive -ge "10" -eq $true){Write-Verbose "Timed out waiting on Mutex" -Verbose}}
else{
Write-Verbose "Turning Mutex ON" -Verbose
Set-Content -Path $Mutex -Value ON
Write-Verbose "Recieved mutex!" -Verbose}
}
Function Close-Mutex{
#Closing Mutex
$checkmutex = Get-Content "\\$computer\c$\Local_Repository\Mutex.csv"
$checkmutex | Set-Content -Value "OFF"
Write-Verbose "Turned Mutex OFF" -Verbose}
#region - KBCollector
Hotfix Collector
#===============================#
$KBArray = @()
$Hotfix = Get-Hotfix -ComputerName $Computer -ErrorAction SilentlyContinue | Select -expandProperty HotFixID
$KBArray += $HotFix
WMI Collector
#===============================#
function CheckWMI{
$Regex = 'KB\d+'
$WMIRecord = Get-WmiObject win32_reliabilityrecords -ComputerName $Computer
foreach($WMIArticle in $WMIRecord){
#------If WMI article contains a KB - Select only the KB name
if($WMIArticle.message -match "$Regex"){
$KBMatch = select-string -InputObject ($WMIArticle.message) -Pattern "$Regex" | select Matches
$WMIUser = $WMIArticle.User.Split("=")[0]
$KBMatch = $KBMatch.Matches
$KBMatch = $KBMatch | Select Value
$WMIKB = $KBMatch.Value
#------Checks for installed WMI KB not already found via Get-Hotfix
if($WMIKB -like $kbarticle){$kbarticle}}}}
Registry Collector
#===============================#
Try{
$RegQuery = Invoke-Command -ComputerName $Computer -ScriptBlock {
$OSArc = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
if($OSArc -eq "64-bit"){$KeyPath = "hklm:\SOFTWARE\Wow6432Node\Microsoft\Updates"}
else{$KeyPath = "hklm:\SOFTWARE\Microsoft\Updates"}
#------Regular expression to capture KB articles
$ResultArray = @()
$NDPregArray = @()
Get-ChildItem -path $KeyPath -Recurse | Select -Property Name | foreach{$NDPregArray += [string]$_.Name}
#------Collects KB articles from subkey names
foreach($Item in $NDPregArray){
if($Item -match "$KB7regex"){
$ResultArray += $Matches[0]
$Matches.Clear()}}
#------Returns results
Return $ResultArray }
#------Stores returned KB articles if $KBArray does not already contain them
foreach($Item in $RegQuery){
if(!($KBArray.Contains($Item))){$KBArray += $Item }}}
Catch{ "Unable to query $Computer registry for installed NDP patches. Installation will continue."}
function CheckRegistry{
$RegQuery = Invoke-Command -ComputerName $Computer -ScriptBlock {
$OSArc = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
if($OSArc -eq "64-bit"){$KeyPath = "hklm:\SOFTWARE\Wow6432Node\Microsoft\Updates"}
else{$KeyPath = "hklm:\SOFTWARE\Microsoft\Updates"}
#------Regular expression to capture KB articles
$ResultArray = @()
$NDPregArray = @()
Get-ChildItem -path $KeyPath -Recurse | Select -Property Name | foreach{$NDPregArray += [string]$_.Name}
#------Collects KB articles from subkey names
foreach($Item in $NDPregArray){
if($Item -match "$KB7regex"){
$ResultArray += $Matches[0]
$Matches.Clear()}}
#------Returns results
Return $ResultArray }
#------Stores returned KB articles if $KBArray does not already contain them
if($RegQuery -contains $kbarticle){$kbarticle}}
#endregion - KBCollector
#region - Gather SysInfo
Local Respository
#===============================#
#------Checks if Local Repository directory exists
$LPcheck = Test-Path $LocalRepositoryPath
$localrepo = "C:\Local_Repository"
if($LPcheck -eq $False){ New-Item -Path $LocalRepositoryPath -ItemType Directory }
Get-Item -Path "$LocalRepositoryPath*" | where {$_.Name -notmatch ".csv"} -ErrorAction SilentlyContinue | Remove-Item
Try{
$sysArch = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer).OSArchitecture
$sysversion = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer).Version
$OSversion = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer).Caption
}
Catch{ Continue }
#------Sets OS architecture variable for future search parameters
If($sysArch -eq "64-bit"){ $sysArch = "x64" }
If($sysarch -eq "32-bit"){ $sysArch = "x86" }
#------Determines computer's viable Cab and Office patches based of installed OS version (6.1 = Windows 7 ; 8.1 = Windows 8)
If($sysversion -like "6.1"){ $CabVer = "6.1" }
If($sysversion -like "6.3"){ $CabVer = "8.1" }
If($sysversion -like "10"){ $CabVer = "10.0" }
#endregion - Gather SysInfo
#Open remote session
$session = New-PSSession -ComputerName $computer -Name $computer
#region##################### MSU #########################
#------Collets all patch viable .msu files that match computer's architecture
$MSUPatchFiles = Get-Childitem -Path
Foreach ($MSU in $MSUPatchFiles){
[string]$kbArticle = $MSU.FullName -split '-' | Select-String -Pattern "KB"
If ($KBArray -contains $kbArticle){
$PrevInstallPatches += $kbArticle
$PrevInstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()
write-Host "$computer - $kbArticle previously installed on $PrevInstallDate" -ForegroundColor Green
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $PrevInstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
if (([bool](($remotearray | select -ExpandProperty "KB Article") -match $remoteobj.'KB Article')) -eq $false){
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
Else{
Check-Mutex
Copy-Item -LiteralPath $MSU.FullName -Destination "\\$computer\c$\Local_Repository"
#expand msu file to .cab
$SB = { Start-Process -filepath 'powershell.exe' -ArgumentList "expand -f:* c:\Local_Repository\*.msu c:\Local_Repository" -PassThru | Wait-Process -Timeout 2000 }
invoke-command -Session $session -ScriptBlock $SB
#install patch
$SB={ $patch = Get-Item -Path "C:\Local_Repository\*" | where {($_.name -like "*kb*") -and ($_.Name -like "*.cab")}
$patch = $patch.fullname
Start-Process -FilePath 'dism.exe' -ArgumentList "/online /add-package /PackagePath:$patch /quiet /norestart" -PassThru | Wait-Process -Timeout 2000 }
invoke-command -Session $session -ScriptBlock $SB
#delete non-csv folder items
Get-Item "$LocalRepositoryPath\*" | where {$_.name -notmatch ".csv"} | Remove-Item
Close-Mutex
#------Send installed KB# to log file and counts number of installed patches
if ((Get-HotFix -ComputerName $computer | select -expandProperty hotfixid) -contains $kbArticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckWMI -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckRegistry -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
else{Write-Host "$computer - $kbArticle skipped, possibly superseeded" -ForegroundColor Yellow; $SkippedArray+=$kbArticle}
$ReportDate = Get-Date -Format ("yyyy-MM-dd")
try{$InstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()}
catch{$InstallDate = $null}
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $InstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
#endregion-MSU
#region###################### CAB ########################
#------Collets all patch viable .cab files that match computer's architecture
$CABPatchFiles = Get-Childitem -Path "$using:ServerRepo" -Recurse | Where{($.Name -like "$sysArch") -and ($.Name -like "$CabVer") -and ($_.Name -match ".cab")}
Foreach ($CAB in $CABPatchFiles){
[string]$kbArticle = $CAB.FullName -split '-' | Select-String -Pattern "KB"
If ($KBArray -contains $kbArticle){
$PrevInstallPatches += $kbArticle
$PrevInstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()
write-Host "$computer - $kbArticle previously installed on $PrevInstallDate" -ForegroundColor Green
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $PrevInstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
if (([bool](($remotearray | select -ExpandProperty "KB Article") -match $remoteobj.'KB Article')) -eq $false){
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
Else{
Check-Mutex
Copy-Item -LiteralPath $CAB.FullName -Destination "\\$computer\c$\Local_Repository"
#install patch
$SB={ $patch = Get-Item -Path "C:\Local_Repository\*" | where {($_.name -like "*kb*") -and ($_.Name -like "*.cab")}
$patch = $patch.fullname
Start-Process -FilePath 'dism.exe' -ArgumentList "/online /add-package /PackagePath:$patch /quiet /norestart" -PassThru | Wait-Process -Timeout 2000 }
invoke-command -Session $session -ScriptBlock $SB
#delete non-csv folder items
Get-Item "$LocalRepositoryPath\*" | where {$_.name -notmatch ".csv"} | Remove-Item
Close-Mutex
#------Send installed KB# to log file and counts number of installed patches
if ((Get-HotFix -ComputerName $computer | select -expandProperty hotfixid) -contains $kbArticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckWMI -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckRegistry -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
else{Write-Host "$computer - $kbArticle skipped, possibly superseeded" -ForegroundColor Yellow; $SkippedArray+=$kbArticle}
$ReportDate = Get-Date -Format ("yyyy-MM-dd")
try{$InstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()}
catch{$InstallDate = $null}
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $PrevInstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
#endregion-CAB
#region##################### .NET ########################
#------Collets all patch viable .NET Framework files that match computer's architecture
$NDPPatchFiles = Get-Childitem -Path "$using:ServerRepo" -Recurse | Where{($.Name -like "$sysArch") -and ($.Name -like "$CabVer") -and ($_.Name -like "NDP")}
Foreach ($NDP in $NDPPatchFiles){
[string]$kbArticle = $NDP.FullName -split '-' | Select-String -Pattern "KB"
[string]$Name = $NDP.Name
If ($KBArray -contains $kbArticle){
$PrevInstallPatches += $kbArticle
$PrevInstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()
write-Host "$computer - $kbArticle previously installed on $PrevInstallDate" -ForegroundColor Green
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $PrevInstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
if (([bool](($remotearray | select -ExpandProperty "KB Article") -match $remoteobj.'KB Article')) -eq $false){
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
Else{
Check-Mutex
Copy-Item -LiteralPath $NDP.FullName -Destination "\\$computer\c$\Local_Repository"
#install patch
#------Installation Command
$EXEline = "$localrepo\$name /quiet /norestart"
#------Creates cmd for currently loaded patch to install on target computer
mAdSwitch -Switch "Install" -InstallLine $EXEline -InstallPath $LocalRepositoryPath
#------Launches created cmd
$install = (([WMICLASS]"\\$Computer\ROOT\CIMV2:win32_process").Create('c:\Local_Repository\mAd.cmd')).processid
$wait1 = get-process -cn $Computer -pid $install -ea SilentlyContinue
#------Script waits for the launched cmd process to complete
While($wait1 -ne $null){
start-sleep -seconds 5
$wait1 = get-process -cn $Computer -pid $install -ea SilentlyContinue
}
#------Deletes the cmd file
mAdSwitch -Switch "Cleanup" -File $name -InstallPath $LocalRepositoryPath
#delete non-csv folder items
Get-Item "$LocalRepositoryPath\*" | where {$_.name -notmatch ".csv"} | Remove-Item
Close-Mutex
#------Send installed KB# to log file and counts number of installed patches
if ((Get-HotFix -ComputerName $computer | select -expandProperty hotfixid) -contains $kbArticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckWMI -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckRegistry -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
else{Write-Host "$computer - $kbArticle skipped, possibly superseeded" -ForegroundColor Yellow; $SkippedArray+=$kbArticle}
$ReportDate = Get-Date -Format ("yyyy-MM-dd")
try{$InstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()}
catch{$InstallDate = $null}
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $PrevInstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
#endregion-.NET
#region#################### Office #######################
#------Registry location of Office version
$OfficeRegPath = "hklm:\SOFTWARE\Microsoft\Office"
$OfficeRegArray = @()
#------Collects all installed office version via registry key subnames
Get-ChildItem -path $OfficeRegPath | Select -Property PSChildName | Select-String -Pattern "\d+" | foreach{$OfficeRegArray += [string]$_.matches}
#------Determines computer's viable office patches via registry keys
if($OfficeRegArray -contains "14"){ $OfficeVer = '2010' }
if($OfficeRegArray -contains "15"){ $OfficeVer = '2013' }
#------Collets all patch viable office files that match computer's architecture
$OfficePatchFiles = Get-Childitem -Path "$using:ServerRepo" -Recurse | Where{($.Name -like "$sysArch") -and ($.Name -match $Officever)}
Foreach ($Office in $OfficePatchFiles){
[string]$kbArticle = $Office.FullName -split '-' | Select-String -Pattern "KB"
[string]$Name = $Office.Name
If ($KBArray -contains $kbArticle){
$PrevInstallPatches += $kbArticle
$PrevInstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()
write-Host "$computer - $kbArticle previously installed on $PrevInstallDate" -ForegroundColor Green
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $PrevInstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
if (([bool](($remotearray | select -ExpandProperty "KB Article") -match $remoteobj.'KB Article')) -eq $false){
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
Else{
Check-Mutex
Copy-Item -LiteralPath $Office.FullName -Destination "\\$computer\c$\Local_Repository"
#install patch
#------Installation Command
$EXEline = "$localrepo\$name /quiet /norestart"
#------Creates cmd for currently loaded patch to install on target computer
mAdSwitch -Switch "Install" -InstallLine $EXEline -InstallPath $LocalRepositoryPath
#------Launches created cmd
$install = (([WMICLASS]"\\$Computer\ROOT\CIMV2:win32_process").Create('c:\Local_Repository\mAd.cmd')).processid
$wait1 = get-process -cn $Computer -pid $install -ea SilentlyContinue
#------Script waits for the launched cmd process to complete
While($wait1 -ne $null){
start-sleep -seconds 5
$wait1 = get-process -cn $Computer -pid $install -ea SilentlyContinue
}
#------Deletes the cmd file
mAdSwitch -Switch "Cleanup" -File $name -InstallPath $LocalRepositoryPath
#delete non-csv folder items
Get-Item "$LocalRepositoryPath\*" | where {$_.name -notmatch ".csv"} | Remove-Item
Close-Mutex
#------Send installed KB# to log file and counts number of installed patches
if ((Get-HotFix -ComputerName $computer | select -expandProperty hotfixid) -contains $kbArticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckWMI -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
elseif(CheckRegistry -like $kbarticle){$InstalledPatches += $kbArticle
write-Host "$computer - $kbArticle successfully installed!" -ForegroundColor Green}
else{Write-Host "$computer - $kbArticle skipped, possibly superseeded" -ForegroundColor Yellow; $SkippedArray+=$kbArticle}
$ReportDate = Get-Date -Format ("yyyy-MM-dd")
try{$InstallDate = (Get-Hotfix -ComputerName $Computer | where {$_.hotfixid -eq $kbArticle} | select -ExpandProperty installedon).toshortdatestring()}
catch{$InstallDate = $null}
if($kbArticlearray -notcontains $kbarticle){
$kbArticlearray += $kbarticle
$remotecomputer = [ordered]@{ "KB Article" = $kbarticle
"Install Date" = $PrevInstallDate }
$remoteobj = New-Object psobject -Property $remotecomputer
$remotearray += $remoteobj
$remotearray | Export-Csv -Path "$LocalRepositoryPath\$ReportDate - LocalPatchReport.csv" -NoTypeInformation -Append}}}
#endregion-Office
Remove-PSSession -computerName $computer
Ending Tasks
#######################################
if($InstalledPatches -eq "offline"){$InstalledPatches = "offline"}
else{$InstalledPatches = ($InstalledPatches | sort -Unique).count}
if($PrevInstallPatches -eq "offline"){$PrevInstallPatches = "offline"}
else{$PrevInstallPatches = ($PrevInstallPatches | sort -Unique).count}
$stoptimer = Get-Date #------Collects end time
$ReportDate = Get-Date -Format ("yyyy-MM-dd")
$resultsarray = @()
$eachcomputer = [ordered]@{ "Computer" = $computer
"SysArch" = $sysArch
"OS Version" = $OSversion
"OS Build" = $sysversion
"Start Time" = $starttimer
"Stop Time" = $stoptimer
"Elapsed Time in Hours" = [math]::round(($stoptimer - $starttimer).TotalHours , 2)
"New Patches Installed" = $InstalledPatches
"Previously Installed" = $PrevInstallPatches
"Skipped/Doesn't Apply" = ($SkippedArray | sort -Unique).count }
$newobj = New-Object psobject -Property $eachcomputer
$resultsarray += $newobj
$resultsarray | Export-Csv -Path "$LocalRepositoryPath$ReportDate - PatchReport.csv" -NoTypeInformation -Force
Write-Verbose "Attempting to grab mutex" -Verbose
$mtx = New-Object System.Threading.Mutex($false, "Global\TestMutex")
If ($mtx.WaitOne(1000))
{
Write-Verbose "Recieved mutex!" -Verbose
$log = "$using:psscriptroot\Logs$ReportDate -PatchReport.csv"
Write-Verbose "Writing data to $log" -Verbose
$resultsarray | Export-Csv -Path $log -NoTypeInformation -Append
Write-Verbose "Releasing mutex" -Verbose
[void]$mtx.ReleaseMutex() }
Else { Write-Warning "Timed out acquiring mutex!" }
}}
Function Menu{
Function Show-Menu
{
param (
[string]$Title = 'Choose an Option Below:'
)
cls
Write-Host ""
Write-Host " SCOO PATCHER -beta-"
Write-Host ""
Write-Host "================ $Title ================="
Write-Host ""
Write-Host "1: Status - All Jobs"
Write-Host "2: Status - Running Jobs"
Write-Host "3: Status - Completed Jobs"
Write-Host "4: Count - Running jobs"
Write-Host "5: Count - Completed jobs"
Write-Host "Q: Press 'Q' to quit."
}
Do
{
Show-Menu
$input = Read-Host "Please make a selection"
switch ($input)
{
'1' {
cls
""
Write-Host 'Status - All Jobs' -ForegroundColor Darkcyan
""
Write-Host "Id Name State HasMoreData HasErrors Command
-- ---- ----- ----------- --------- -------"
Get-RSJob
write-host ""
} '2' {
cls
""
Write-Host 'Status - Running Jobs' -ForegroundColor Darkcyan
""
Write-Host "Id Name State HasMoreData HasErrors Command
-- ---- ----- ----------- --------- -------"
Get-RSJob -state running
write-host ""
} '3' {
cls
""
Write-Host 'Status - Completed Jobs' -ForegroundColor Darkcyan
""
Write-Host "Id Name State HasMoreData HasErrors Command
-- ---- ----- ----------- --------- -------"
Get-RSJob -state Completed
write-host ""
} '4' {
cls
$continue = $true
while($continue){
if ([console]::KeyAvailable){
echo "Press Q to Exit to Main Menu";
$x = [System.Console]::ReadKey()
switch ( $x.key)
{ q { $continue = $false } } }
else{cls
""
Write-Host 'Count - Running Jobs' -ForegroundColor Darkcyan
Write-Host 'Refreshing every 10 seconds....Press Q to Exit to Main Menu' -ForegroundColor Darkcyan
""
$a = (Get-RSJob -State Running).count
$b = (Get-RSJob).count
write-host "$a/$b Jobs Running"
""
Start-Sleep -seconds 10}}
} '5' {
cls
$continue = $true
while($continue){
if ([console]::KeyAvailable){
echo "Press Q to Exit to Main Menu";
$x = [System.Console]::ReadKey()
switch ( $x.key)
{ q { $continue = $false } } }
else{cls
""
Write-Host 'Count - Completed Jobs' -ForegroundColor Darkcyan
Write-Host 'Refreshing every 10 seconds....Press Q to Exit to Main Menu' -ForegroundColor Darkcyan
""
$a = (Get-RSJob -State Completed).count
$b = (Get-RSJob).count
write-host "$a/$b Jobs Completed"
""
Start-Sleep -seconds 10}}
} 'q' {return}
}
pause
}
Until ($input -eq 'q')
}
Menu
Do you try to use latest build?