two background jobs colision
Posted: Wed Jan 13, 2016 1:30 am
So I have a GUI script for station management with multiple function and for many functions I use the powershell studio JobTracker framework with no problems. Until yesterday, when I decided to convert a test-connection function to run as a job with the prebuilt job framework aswell.
It looks like this:
The pingtimer will create a new job every 10 seconds and then return an online/offline value in the completedscript block which then updates the form. Works like charm.
Problems start to appear when I run a different job function that I use to scan a remote computer for specific changes (software metering), to be specific, the problem occurs when this job finishes its "scriptblock" part and jumps to "completedscript" part. This part looks like this:
When this script block gets to the part where I save the output to a file it gets thrown away and jumps to the beginning of the "completedscript" (????) and starts doing this scriptblock again. I spent many hours debugging this and was able to figure out that the culprit is the pingtimer job, that kicks in every 10 seconds and just happens to kick in during the execution of this scriptblock. For some reason which I am unable to figure out it keeps trying to remove this job before it gets to execute the whole completedscript block.
If I remove the pingtimer job, other jobs works just fine.
The Output console is showing this:
Can you please help me figure out why is this happening and how to prevent the pingtimer job to interrupt other jobs?
Thanks a lot,
Thomas
It looks like this:
- $script:pingtimer = New-Object System.Windows.Forms.Timer
- $script:pingtimer.Enabled = $true
- $pingtimer.Interval = 10000
- $pingtimer.Add_Tick({
- if ($pc -eq $env:COMPUTERNAME)
- {
- $panel_online.BackColor = 'GreenYellow'
- $labelStatusPCOnOff.Text = "LOCALHOST"
- $script:statusTargetPc = $true
- }
- elseif (!($pc))
- {
- $panel_online.BackColor = 'Red'
- $labelStatusPCOnOff.Text = "NO TARGET"
- $script:statusTargetPc = $false
- }
- else
- {
- Add-JobTracker -Name "ping" -JobScript { `
- param ($pc)
- $a = Test-Connection -ComputerName $pc -Quiet -Count 1
- return $a
- } -CompletedScript { `
- $ping = Receive-Job -Name "ping"
- if ($ping)
- {
- $panel_online.BackColor = 'GreenYellow'
- $labelStatusPCOnOff.Text = "ONLINE"
- $script:statusTargetPc = $true
- }
- else
- {
- $panel_online.BackColor = 'Red'
- $labelStatusPCOnOff.Text = "OFFLINE"
- $script:statusTargetPc = $false
- }
- } -ArgumentList $pc
- }
- })
- $script:pingtimer.Start()
Problems start to appear when I run a different job function that I use to scan a remote computer for specific changes (software metering), to be specific, the problem occurs when this job finishes its "scriptblock" part and jumps to "completedscript" part. This part looks like this:
- -CompletedScript {
- #get job results
- Param ($Job)
- $script:scanafter = Receive-Job -Job $Job -Keep
- Add-Log -Color 'Red' -Value "COMPARE SCAN COMPLETE, GENERATING RESULTS..." -NewLine
- Show-NotifyIcon -BalloonTipTitle "PCT" -BalloonTipText "COMPARE SCAN COMPLETE" -BalloonTipIcon 'Info' -NotifyIcon $notifyicon_PCT
- #compare scans and show differences
- $script:compareafter = [ordered]@{ }
- $compareafter.apps = compare $scanbefore.apps $scanafter.apps -Property ProgramName, DisplayVersion -PassThru | ? { $_.Sideindicator -eq "=>" }
- $compareafter.appfolders = compare $scanbefore.appfolders $scanafter.appfolders -Property FullName -PassThru | ? { $_.Sideindicator -eq "=>" }
- $compareafter.filteredappfolders = @()
- $previous = $null
- $compareafter.appfolders.fullname | foreach {
- if (($previous -eq $null) -or ($_ -notlike "$previous*"))
- {
- $previous = $_
- $compareafter.filteredappfolders += "$_"
- }
- }
- Clear-Variable previous
- $compareafter.exefiles = compare $scanbefore.exefiles $scanafter.exefiles -Property FullName -PassThru | ? { $_.Sideindicator -eq "=>" }
- $compareafter.registry = compare $scanbefore.registry $scanafter.registry | ? { $_.Sideindicator -eq "=>" }
- $compareafter.drivers = compare $scanbefore.drivers $scanafter.drivers -Property OriginalFileName, Version -PassThru | ? { $_.Sideindicator -eq "=>" }
- $compareafter.services = compare $scanbefore.services $scanafter.services -Property Name, DisplayName -PassThru | ? { $_.Sideindicator -eq "=>" }
- $compareafter.tasks = compare $scanbefore.tasks $scanafter.tasks -Property TaskName, TaskPath, Description | ? { $_.Sideindicator -eq "=>" }
- $compareafter.envvar = compare $scanbefore.envvar $scanafter.envvar -Property Name, Value | ? { $_.Sideindicator -eq "=>" }
- $compareafter.startmenu = compare $scanbefore.startmenu $scanafter.startmenu -Property FullName | ? { $_.Sideindicator -eq "=>" }
- <#
- #save dialog
- $SaveCompareDialog = New-Object System.Windows.Forms.SaveFileDialog
- $SaveCompareDialog.Title = "Save Compare Results"
- $SaveCompareDialog.initialDirectory = "$env:LOCALAPPDATA\PCT"
- $SaveCompareDialog.FileName = $PackageFullName + "_AppScan"
- $SaveCompareDialog.filter = “Text files (*.txt)|*.txt”
- $DialogResult = $SaveCompareDialog.ShowDialog()
- if ($DialogResult -eq [System.Windows.Forms.DialogResult]::OK)
- { }
- #>
- #format data and output to a file
- $savefilepath = "$env:LOCALAPPDATA\PCT\AppScan.txt" #$SaveCompareDialog.FileName
- Remove-Item -Path $savefilepath -Force -ea 'SilentlyContinue'
- New-Item $savefilepath -ItemType File -Force | Add-Content -value "METERING DIFFERENCES:`r`r" -Encoding Unicode
- $compareafter.apps | select ProgramName, DisplayVersion, Publisher, InstallDate, UninstallString | ft | Out-String | Out-File $savefilepath -Append -Force
- #$compareafter.appfolders | select @{ Name = "AppFolders"; Expression = "FullName" } | Out-String | Out-File $SaveCompareDialog.filename -Append -Force
- if ($compareafter.filteredappfolders) { Add-Content $savefilepath -Value "Application Folders:`n--------------------`r" }
- $compareafter.filteredappfolders | Out-File $savefilepath -Append -Force
- $compareafter.exefiles | select @{ Name = "ExeFiles"; Expression = "FullName" } | Out-String | Out-File $savefilepath -Append -Force
- $compareafter.registry | select @{ Name = "Registry"; Expression = "InputObject" } | Out-String | Out-File $savefilepath -Append -Force
- $compareafter.drivers | select @{ Name = "Driver"; Expression = "OriginalFileName" }, @{ Name = "Description"; Expression = "ClassDescription" }, Version, ProviderName | ft -Wrap | Out-String | Out-File $savefilepath -Append -Force
- $compareafter.services | select @{ Name = "Service"; Expression = "Name" }, @{ Name = "Service Display Name"; Expression = "DisplayName" }, Status | ? { $_.Service -ne "PSEXESVC" } | ft -Wrap | Out-String | Out-File $savefilepath -Append -Force
- $compareafter.tasks | select TaskName, TaskPath, Description | ft -Wrap | Out-String | Out-File $savefilepath -Append -Force
- $compareafter.envvar | select @{ Name = "Environment Variables"; Expression = "Name" }, Value | ft -Wrap | Out-String | Out-File $savefilepath -Append -Force
- $compareafter.startmenu | select @{ Name = "Start Menu"; Expression = "FullName" } | Out-String | Out-File $savefilepath -Append -Force
- ii $savefilepath
- $exportcompare = show-messagebox -YesNo -M "Do you want to export compare results to Exchange?" -TM -Q -T "Export Compare Results"
- if ($exportcompare -eq "Yes")
- {
- if (!(Test-Path "$exchange\MeteringFiles\$PackageFullName")) { New-Item -ItemType directory -Path "$exchange\MeteringFiles" -Name $PackageFullName }
- Copy-Item $savefilepath "$exchange\MeteringFiles\$PackageFullName" -Force
- $exeprops = foreach ($i in $compareafter.exefiles.fullname) { icm -cn $pc -ScriptBlock { param ($exe) Get-ItemProperty $exe } -ArgumentList $i }
- $exeprops | ConvertTo-Csv | Out-File "$exchange\MeteringFiles\$PackageFullName\$PackageFullName.$PackageVersion EXE.csv" -Force
- }
- $toolstrip_Progressbar2.Style = 'Blocks'
- $toolstrip_Progressbar2.Value = 0
- $toolstrip_Status.Text = "Idle"
- } -ArgumentList ($pc)
If I remove the pingtimer job, other jobs works just fine.
The Output console is showing this:
- ERROR: Exception calling "RemoveAt" with "1" argument(s): "Index je mimo rozsah. Index musí být nezáporný a musí být menší než velikost kolekce.
- ERROR: Název parametru: index"
- Globals.ps1 (448): ERROR: At Line: 448 char: 6
- ERROR: + $JobTrackerList.RemoveAt($index)
- ERROR: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ERROR: + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
- ERROR: + FullyQualifiedErrorId : ArgumentOutOfRangeException
- ERROR:
- ERROR: Remove-Job : The command cannot remove the job because it does not exist or because it is a child job. Child jobs can be removed only by removing the parent jo
- ERROR: b.
- Globals.ps1 (449): ERROR: At Line: 449 char: 6
- ERROR: + Remove-Job -Job $psObject.Job
- ERROR: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ERROR: + CategoryInfo : InvalidOperation: (System.Manageme...n.PSRemotingJob:PSRemotingJob) [Remove-Job], ArgumentException
- ERROR: + FullyQualifiedErrorId : CannotRemoveJob,Microsoft.PowerShell.Commands.RemoveJobCommand
- ERROR:
Thanks a lot,
Thomas