PowerShell script exchange
Post Reply
drewdavis
Lurker
Posts: 1
Liked: never
Joined: Apr 15, 2024 9:14 am
Full Name: drewdavis
Contact:

Datagridview locks up loading an object

Post by drewdavis »

I have 2 datagridviews, 1 loading some replication stats from zerto and the other loading stats from veeam.

On form load they both load with no issues, but I have a timer set for 30 seconds to refresh the data. Datagridview1 (containing zerto stats) loads just fine, Datagridview2 (loading veeam stats) locks the application.

Both datagridviews are populated using the build in 'Update-datagridview' functions on page load (which works), and then again on a timer (which doesnt work).

Here is the function I'm using to grab my veeam stats

Code: Select all

function get-VeeamStats
{
	
	$jobs = get-vbrjob | ?{ $_.JobType -eq "Backup" }
	
	$JobsOutput = @()
	foreach ($job in $jobs)
	{
		$LastSession = $Job.FindLastSession()
		
		$JobOutput = New-Object -TypeName PSObject
		$JobOutput | Add-Member -Name "Jobname" -MemberType Noteproperty -Value $LastSession.Name
		$JobOutput | Add-Member -Name "State" -MemberType Noteproperty -Value $LastSession.state
		$JobOutput | Add-Member -Name "StartTime" -MemberType Noteproperty -Value $LastSession.CreationTime
		$JobOutput | Add-Member -Name "Endtime" -MemberType Noteproperty -Value $LastSession.endtime
		$JobOutput | Add-Member -Name "TotalUsedSize" -MemberType Noteproperty -Value ($LastSession.Info.Progress.TotalUsedSize)
		$JobOutput | Add-Member -Name "ReadSize" -MemberType Noteproperty -Value ($LastSession.Info.Progress.ReadSize)
		$JobOutput | Add-Member -Name "TransferedSize" -MemberType Noteproperty -Value ($LastSession.Info.Progress.TransferedSize)
		$JobsOutput += $JobOutput
	}
	return $JobsOutput
}
This will return data like...

Code: Select all

Jobname        : Jobname1 - Daily (Reverse Incremental)
State          : Stopped
StartTime      : 14/3/2024 8:00:22 PM
Endtime        : 14/3/2024 8:18:01 PM
TotalUsedSize  : 297580625920
ReadSize       : 3931111424
TransferedSize : 1787831840

Jobname        : Jobname2  (Reverse Incremental)
State          : Stopped
StartTime      : 14/3/2024 11:59:16 PM
Endtime        : 14/4/2024 12:36:46 AM
TotalUsedSize  : 208479977471
ReadSize       : 75517394944
TransferedSize : 16996112096

Jobname        : Jobname3 (Reverse Incremental)
State          : Stopped
StartTime      : 14/3/2024 10:00:02 PM
Endtime        : 14/3/2024 10:15:34 PM
TotalUsedSize  : 730433847295
ReadSize       : 7075790848
TransferedSize : 1662320288

Jobname        : Jobname4 (Reverse Incremental)
State          : Stopped
StartTime      : 14/4/2024 12:00:01 PM
Endtime        : 14/4/2024 12:16:55 PM
TotalUsedSize  : 1090948956159
ReadSize       : 6180306944
TransferedSize : 2234701552
Below is a snippet of the form load and trigger code

Code: Select all

$form1_Load = {
	
	$zertoStats = get-ZertoStats
	$VeeamStats = get-VeeamStats
	
	
	Update-DataGridView $datagridview1 $zertoStats
	Update-DataGridView $datagridview2 $VeeamStats

	# timer1
	#
	$timer1.Enabled = $True
	$timer1.Interval = 30000
	$timer1.add_Tick($timer1_Tick)
}

#region Control Helper Functions
function Update-DataGridView
{
	<#
	.SYNOPSIS
		This functions helps you load items into a DataGridView.

	.DESCRIPTION
		Use this function to dynamically load items into the DataGridView control.

	.PARAMETER  DataGridView
		The DataGridView control you want to add items to.

	.PARAMETER  Item
		The object or objects you wish to load into the DataGridView's items collection.
	
	.PARAMETER  DataMember
		Sets the name of the list or table in the data source for which the DataGridView is displaying data.

	.PARAMETER AutoSizeColumns
	    Resizes DataGridView control's columns after loading the items.
	#>
	Param (
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		[System.Windows.Forms.DataGridView]$DataGridView,
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		$Item,
	    [Parameter(Mandatory=$false)]
		[string]$DataMember,
		[System.Windows.Forms.DataGridViewAutoSizeColumnMode]$AutoSizeColumns = 'None'
	)
	$DataGridView.SuspendLayout()
	$DataGridView.DataMember = $DataMember
	
	if ($Item -is [System.Data.DataSet] -and $Item.Tables.Count -gt 0)
	{
		$DataGridView.DataSource = $Item.Tables[0]
	}
	elseif ($Item -is [System.ComponentModel.IListSource]`
	-or $Item -is [System.ComponentModel.IBindingList] -or $Item -is [System.ComponentModel.IBindingListView] )
	{
		$DataGridView.DataSource = $Item
	}
	else
	{
		$array = New-Object System.Collections.ArrayList
		
		if ($Item -is [System.Collections.IList])
		{
			$array.AddRange($Item)
		}
		else
		{
			$array.Add($Item)
		}
		$DataGridView.DataSource = $array
	}
	
	if ($AutoSizeColumns -ne 'None')
	{
		$DataGridView.AutoResizeColumns($AutoSizeColumns)
	}
	
	$DataGridView.ResumeLayout()
}

function ConvertTo-DataTable
{
	<#
		.SYNOPSIS
			Converts objects into a DataTable.
	
		.DESCRIPTION
			Converts objects into a DataTable, which are used for DataBinding.
	
		.PARAMETER  InputObject
			The input to convert into a DataTable.
	
		.PARAMETER  Table
			The DataTable you wish to load the input into.
	
		.PARAMETER RetainColumns
			This switch tells the function to keep the DataTable's existing columns.
		
		.PARAMETER FilterWMIProperties
			This switch removes WMI properties that start with an underline.
	
		.EXAMPLE
			$DataTable = ConvertTo-DataTable -InputObject (Get-Process)
	#>
	[OutputType([System.Data.DataTable])]
	param(
	[ValidateNotNull()]
	$InputObject, 
	[ValidateNotNull()]
	[System.Data.DataTable]$Table,
	[switch]$RetainColumns,
	[switch]$FilterWMIProperties)
	
	if($null -eq $Table)
	{
		$Table = New-Object System.Data.DataTable
	}
	
	if ($InputObject -is [System.Data.DataTable])
	{
		$Table = $InputObject
	}
	elseif ($InputObject -is [System.Data.DataSet] -and $InputObject.Tables.Count -gt 0)
	{
		$Table = $InputObject.Tables[0]
	}
	else
	{
		if (-not $RetainColumns -or $Table.Columns.Count -eq 0)
		{
			#Clear out the Table Contents
			$Table.Clear()
			
			if ($null -eq $InputObject) { return } #Empty Data
			
			$object = $null
			#find the first non null value
			foreach ($item in $InputObject)
			{
				if ($null -ne $item)
				{
					$object = $item
					break
				}
			}
			
			if ($null -eq $object) { return } #All null then empty
			
			#Get all the properties in order to create the columns
			foreach ($prop in $object.PSObject.Get_Properties())
			{
				if (-not $FilterWMIProperties -or -not $prop.Name.StartsWith('__')) #filter out WMI properties
				{
					#Get the type from the Definition string
					$type = $null
					
					if ($null -ne $prop.Value)
					{
						try { $type = $prop.Value.GetType() }
						catch { Out-Null }
					}
					
					if ($null -ne $type) # -and [System.Type]::GetTypeCode($type) -ne 'Object')
					{
						[void]$table.Columns.Add($prop.Name, $type)
					}
					else #Type info not found
					{
						[void]$table.Columns.Add($prop.Name)
					}
				}
			}
			
			if ($object -is [System.Data.DataRow])
			{
				foreach ($item in $InputObject)
				{
					$Table.Rows.Add($item)
				}
				return @( ,$Table)
			}
		}
		else
		{
			$Table.Rows.Clear()
		}
		
		foreach ($item in $InputObject)
		{
			$row = $table.NewRow()
			
			if ($item)
			{
				foreach ($prop in $item.PSObject.Get_Properties())
				{
					if ($table.Columns.Contains($prop.Name))
					{
						$row.Item($prop.Name) = $prop.Value
					}
				}
			}
			[void]$table.Rows.Add($row)
		}
	}
	
	return @(,$Table)	
}
#endregion

$timer1_Tick = {
	
	$ZertoStats = get-ZertoStats
	$veeamstats = get-VeeamStats
	
	Update-DataGridView $datagridview1 $ZertoStats
	Update-DataGridView $datagridview2 $VeeamStats
}
any help understanding why my it's locking my form would be greatly appreciated.
david.domask
Veeam Software
Posts: 1925
Liked: 463 times
Joined: Jun 28, 2016 12:12 pm
Contact:

Re: Datagridview locks up loading an object

Post by david.domask »

Hi drewdavis,

I'm afraid we likely won't be able to assist on why the DataGridView starts to hang during your scheduled refresh as it's not one of our cmdlets.

I would advise set up some logging on the script temporarily and maybe just print each part of your workflow to see if you can catch where it's hanging, then add some additional debugging lines to try to catch it. Since it loads initially the first time, I have doubts its about the content of what you're sending, but it'd be best to start with some debugging and see where it's actually hanging; if the actual Veeam cmdlets turn out to be hanging, we can advise, but if it's the .NET Reflection for the DataGrid, it would be best to check one of Microsoft's Powershell communities.
David Domask | Product Management: Principal Analyst
Post Reply

Who is online

Users browsing this forum: No registered users and 8 guests