PS & Winforms in PS Studio looping through DataGridView

Hi all,

I’m creating background jobs to perform a task.
I get certain values from a DataGridView
I’m adding the results in to another DGV and removing them from the source DGV.
I’m controlling the flow to limit the amount of background jobs running at one time.
everything works as expected but in the source i’m left with some items still in the source DGV after the loop that goes through each item in the source DGV.

The code for the button that executes the command is below:

$ScanButton_Click = {
	
	$ScanButton.Enabled = $false
	foreach ($a in $ItemsToScanDGV.Rows)
	{
		$AddJobs = $true
		while ($AddJobs -eq $true)
		{
			if ($JobTrackerList.Count -ge ($concurrentjobstb.Text -as [int]))
			{
				$AddJobs = $true
				[System.Windows.Forms.Application]::DoEvents()
			}
			else {
			$ComputerName = (($a.Cells[$ItemsToScanDGV.Columns["HostName"].Index]).Value)
			$ComputerName = $ComputerName.ToString().Trim()
			if ($ComputerName -gt "")
			{
				$SourceCellIndex = $a.Cells[$ItemsToScanDGV.Columns["HostName"].Index]
				Add-JobTracker -Name ("$ComputerName" + (Get-Random -Minimum 1000 -Maximum 9999)) -ArgumentList $ComputerName -JobScript {
					param ($Computer)
					
					$ObjectProps = @{
						"HostName" = "";
						"IPAddress" = "";
						"LastRestarted" = "Could Not Query";
						"RestartedRecently" = "N/A";
						"RDP" = "N/A";
						"TryAgain" = "TryAgain"
					}
					
					
					$NetworkTest = Test-NetConnection -CommonTCPPort RDP -ComputerName $Computer -ErrorAction SilentlyContinue
					
					if ($NetworkTest.PingSucceeded)
					{
						try
						{
							$WMI = Get-WmiObject -Class win32_operatingsystem -ComputerName $Computer -ErrorAction 'Stop'
							if ($WMI.LastBootUpTime -lt (Get-Date).AddHours(-1)) { $LastHour = "Yes" }
							Else { $LastHour = "No" }
							
							$obj = New-Object System.Management.Automation.PSObject -Property $ObjectProps
							$obj.HostName = $Computer
							$obj.IPAddress = $NetworkTest.RemoteAddress
							$obj.LastRestarted = $WMI.ConvertToDateTime($WMI.LastBootUpTime)
							$obj.RestartedRecently = $LastHour
							$obj.RDP = $NetworkTest.TCPTestSucceeded
							
							Write-Output $obj
						}
						catch
						{
							
							
							$obj = New-Object System.Management.Automation.PSObject -Property $ObjectProps
							$obj.HostName = $Computer
							$obj.IPAddress = $NetworkTest.RemoteAddress
							
							Write-Output $obj
						}
					}
					Else
					{
						$obj = New-Object System.Management.Automation.PSObject -Property $ObjectProps
						$obj.HostName = $Computer
						$obj.IPAddress = $NetworkTest.RemoteAddress
						
						Write-Output $obj
					}
				} -CompletedScript {
					param ($job)
					
					$hashReturn = Receive-Job -Job $Job
					ForEach ($Job in $hashReturn)
					{
						$OutputDGV.Rows.Add($Job.HostName, $Job.IPAddress, $Job.LastRestarted, $Job.RestartedRecently, $Job.RDP, $Job.TryAgain)
						foreach ($row in $ItemsToScanDGV.Rows)
						{
							if ($row.Cells["HostName"].Value -ne $null)
							{
								if ($row.Cells["HostName"].Value.ToString().Equals($Job.HostName))
								{
									$ItemsToScanDGV.Rows.Remove($Row)
									break
								}
							}
						}
					}
					If ($JobTrackerList.Count -le 1) { $ScanButton.Enabled = $true }
				}
			}
			$AddJobs = $false
			[System.Windows.Forms.Application]::DoEvents()
		}
	}
}
}

Anyone know what i’m going wrong?

I’m happy to upload the project files somewhere is needed.
Edit: in fact, here’s the link anyway Dropbox - File Deleted

I’d probably begin by putting a lot of Write-Verbose statements. Have it tell you what it’s pulling from the source grid, what it’s trying to delete, and so on. I’d probably also put some debug breakpoints in there - when it tells me it removed something, I’d also let it break so I could manually confirm the contents of the grid at that point.

I’m not going to be able to run your code, and it’s impossible to debug something like this statically. But the first debug step, in any situation, is to get the code to give you some information about what it’s doing. Analyze that output to make sure it’s what you expected it to be. If it isn’t, then you have some evidence of your bug.

I’m not great at debugging none console scripts/applications, I’ve been using things like [System.Windows.Forms.MessageBox]::Show($Error[0], “ERROR”) to give me details replacing the variable with want I want to view.

When I add the Write-Debug or Write-Verbose to the application i’m assuming the output will appear in the console portion of the PS Studios editor?

Many Thanks,

Nigel

No offense but I’d start over with another form. Use one datagrid and update the cells based on the results. Your scannow button should execute for each row selected in the dgv. Use the job tracker function properly.

Here’s a stripped down example of how the jobtracker works. btw, sapien has forums as well.

foreach ($row in $datagridview1.SelectedRows) {
				
				$server = $row.Cells[0].Value
				
				if (test-connection $server -count 1 -erroraction "silentlycontinue") {

					$JobScript = {
						
						param ($server,
							$credential)
						
						
						###get a bunch of server info
						
						[pscustomobject]@{
							
							Server = $server
							Timestamp = $timestamp
							KBList = $kblist
							EventListCount = $eventlist.count
							ServiceList = $servicelist
							UPtime = $uptime
							CSpace = $cconv
							
						}
						
						
					}

					
					$UpdateScript = {
						Param ($Job)
						$statusbarpanel1.Text = 'Working...'
					}

					
					$CompletedScript = {
						
						Param ($Job)
						$results = Receive-Job -Job $Job
						
						$row = $datagridview1.Rows | ? { $_.Cells[0].Value -eq $results.server }
						
						$row.Cells[1].Value = $results.timestamp
						$row.Cells[2].Value = $results.kblist
						$row.Cells[3].Value = $results.eventlistcount
						$row.Cells[4].Value = $results.servicelist
						$row.Cells[5].Value = $results.uptime
						$row.Cells[6].Value = $results.cspace
						
						
						$statusbarpanel1.Text = $results.server + " Complete."
						

						
					}
					
					Add-JobTracker -Name $server -JobScript $JobScript -UpdateScript $UpdateScript -CompletedScript $CompletedScript -ArgumentList $server, $credential
					
					###ENDJOB####*************************************************************************************
					
					
				} else {
					
					$row.Cells[1].Value = 'Offline'
					$row.Cells[2].Value = 'Offline'
					$row.Cells[3].Value = 'Offline'
					$row.Cells[4].Value = 'Offline'
					$row.Cells[5].Value = 'Offline'
					$row.Cells[6].Value = 'Offline'
					
				}
				
			}

write-host is the most efficient way of troubleshooting in the studio. Practice manipulating Cells and rows in the dgv, returning info etc. Get in the habit of building or binding datatables so you can use all the methods available.

https://msdn.microsoft.com/en-us/library/system.data.datatable_methods(v=vs.110).aspx

To see what the form looks like in the example go here.

https://www.sapien.com/forums/viewtopic.php?f=21&t=10239

Hi Dan, thanks for the reply,

Liking the look of that, that’s what I was hoping this could mature into, just getting to grips with is all now.

i’ll start again with the DGVs and go from there.

Thank you.