【问题标题】:NullReferenceException during ChartInvalidate when customizing LegendItem自定义 LegendItem 时 ChartInvalidate 期间出现 NullReferenceException
【发布时间】:2018-10-12 22:13:11
【问题描述】:

我在 IIS 日志的 powershell 中构建了一个图形引擎,点的大小由绘制的点数(50-50k)缩放。当尺寸很小时,图例会同时调整,所以我正在尝试调整图例中的标记。

我已经创建了一个事件函数:

$chart1_CustomizeLegend = { 
        Param([Object]$sender , [System.Windows.Forms.DataVisualization.Charting.CustomizeLegendEventArgs]$e ) 
        try
        {
        if ($e.LegendItems.Count -gt 0)
        {
            Write-Host found $e.LegendItems.Count legend items

            for ($i = 0 ; $i -lt $e.LegendItems.Count ; $i++)
            {
                write-host processing $i

                if ($e.LegendItems[$i] -eq $null)
                {
                    write-host item is null
                }
                else
                {
                    write-host item is not null
                }
                #update marker size
                $e.LegendItems[$i].MarkerSize=10
            }
         }
         } catch [System.Exception] {
            Write-Error "failed to customize legend-item" 
            $_ | Format-List -Force | Out-String | Write-Error
         }
        }#CustomizeLegend

并注册:

$custjob = Register-ObjectEvent -InputObject $chart1 -EventName CustomizeLegend -Action $chart1_CustomizeLegend

我可以看到它被调用了,但是它碰到了 catch 块:

自定义图例项失败

异常:System.NullReferenceException:对象 引用未设置为对象的实例。 在 System.Windows.Forms.DataVisualization.Charting.Chart.Invalidate() 在 System.Windows.Forms.DataVisualization.Charting.ChartPicture.Invalidate() 在 System.Windows.Forms.DataVisualization.Charting.ChartElementCollection`1.Invalidate() 在 System.Windows.Forms.DataVisualization.Charting.ChartElement.Invalidate() 在 System.Windows.Forms.DataVisualization.Charting.Legend.Invalidate(布尔 无效LegendOnly) 在 CallSite.Target(Closure , CallSite , Object , Int32 ) TargetObject : CategoryInfo : 未指定:(:) [],NullReferenceException FullyQualifiedErrorId : ExceptionWhenSetting ErrorDetails : InvocationInfo : System.Management.Automation.InvocationInfo ScriptStackTrace:在 , : 第 763 行 在 Write-IISResponseCharts,:第 906 行 在 , : 第 1373 行 PipelineIterationInfo : {} PSMessageDetails :

但在此之前它写出该项目不为空,所以我知道我没有做任何空引用异常。这似乎是一个 .NET 问题,但很难确定。

它似乎在图表的 SaveImage 期间发生。

 $ChartName = "IIS Response Time {0}-{1}, Series By Call Type, time-response scatter" -f $data.Folder,$data.File
        Write-progress -status "Preparing $ChartName containing $($data.data.count) points" -activity "Preparing $ChartName, getting data"
        $DataArray  = $data.data  |where {$_["time"]}| where $FilterSB | where $CoreFilterSB

    $chart1 = New-object System.Windows.Forms.DataVisualization.Charting.Chart
    $chart1.Width = 1200*$GraphScale
    $chart1.Height = 800*$GraphScale
    $chart1.BackColor = [System.Drawing.Color]::White

    # title
       $chart1.Titles.Add(("{0} ({1} of {2} points) " -f $ChartName, @($DataArray).Count, $data.data.count)) > $null
       $chart1.Titles[0].Font = "Arial,{0}pt" -f (8*$GraphScale)
       $chart1.Titles[0].Alignment = "topLeft"

    # chart area
       $chartarea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
       $chartarea.Name = "ChartArea1"
       $chartarea.AxisY.Title = "Response time (MS)"
       $chartarea.AxisX.Title = "Time"
         $chartarea.AxisY.LogarithmBase = 2
       #$chartarea.axisy.IntervalAutoMode = [System.Windows.Forms.DataVisualization.Charting.IntervalAutoMode]::FixedCount
       $chartarea.AxisX.Interval = 60
       $chartarea.AxisX.IntervalType = [System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType]::Minutes
       $chartarea.AxisX.LabelStyle.Font = "Arial,24pt"
       $chartarea.AxisX.LabelStyle.Format="HH:mm"
       #$chartarea.AxisX.Minimum = $StartTime.TotalMinutes
       #$chartarea.AxisX.Maximum = $EndTime.TotalMinutes
       #$chartarea.AxisX.Minimum = 0*60 #17:30
       #$chartarea.AxisX.Maximum = 24.0*60 #20:00
       $chartarea.AxisY.LabelStyle.Font = "Arial,24pt"
       $chartarea.AxisY.Minimum = 256
        if ($SetExceedingToMaxCallTime)
        {
            $chartarea.AxisY.Maximum = [Math]::Pow([Math]::Round([Math]::Sqrt($MaxCallTimeToChart)+0.5,0),2)*1024

        }
        else
        {
            $chartarea.AxisY.Maximum = 131072
        }
       $chartarea.AxisY.Interval = 1
       $chartarea.AxisY.MinorGrid.Enabled = $true
       $chartarea.AxisY.IsLogarithmic=$true
       $chartarea.AxisY.MinorGrid.LineColor = [System.drawing.color]::LightGray

       $chart1.ChartAreas.Add($chartarea)

        # legend
        if ($ShowLegend)
        {
write-host add event to scatter chart
       $custjob = Register-ObjectEvent -InputObject $chart1 -EventName CustomizeLegend -Action $chart1_CustomizeLegend
       write-host 'create legend scatter chart'
       $legend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend
       $legend.name = "Legend1"
       $chart1.Legends.Add($legend)
        write-host 'format legend scatter chart'
       $chart1.Legends["Legend1"].Font = "Arial,{0}pt" -f (6 * $GraphScale)

       $chart1.Legends["Legend1"].Docking =[System.Windows.Forms.DataVisualization.Charting.Docking]::Right
       #$chart1.Legends["Legend1"].LegendItems
       }
    # data series
       #$chart1.Series["wGLN"].Legend = "Legend1"
       #$chart1.Series["wGLN"].color = "#62B5CC"



       #dev
       $labelNum = 0


       $series = @()
       $pointsadded = 0
       $DataArray | ForEach-Object {
            if ($pointsadded % 100 -eq 0) {  write-host ("Adding data Series [{0}] Points [{1}]" -f $series.Count,$pointsadded)       Write-progress -status ("Adding data Series [{0}] Points [{1}]" -f $series.Count,$pointsadded) -activity "Preparing $ChartName" }

            $seriesname = Invoke-Command $seriesSB -ArgumentList $_
            if (!($series -contains $seriesname))
            {
                write-host 'create a series'
              $theSeries = $chart1.Series.Add($seriesname)
               $theSeries.ChartType = "Point"
               $theSeries.BorderWidth  = 2
               $theSeries.IsVisibleInLegend = $true
               $theSeries.chartarea = "ChartArea1"
               $theSeries.MarkerSize = 6/[Math]::Sqrt([Math]::Sqrt([Math]::Max($DataArray.Count/1000,1)))*$GraphScale
               $theSeries.BorderColor=$theSeries.Color
               $theSeries.BorderWidth = 2
               write-host 'add series'
               $series += $seriesname

               $theSeries.IsVisibleInLegend=$true
               $theseries.Legend = "Legend1"
           }
           else
           {
                #series dictionary is case sensitive however IIS logs are not, 
                #use whereclause instead of dictionary lookup to ensure case insensitive match!
                $theSeries = $chart1.Series | where {$_.Name -eq $seriesname}
           }

           if ($_['time-taken'] -gt 0)
           {
               if ($SetExceedingToMaxCallTime)
               {
                     $theSeries.Points.addxy( [DateTime]($_["time"]) , [Math]::Min($MaxCallTimeToChart*1000,($_['time-taken']))) > $null; 
               }
               else
               {
                   $theSeries.Points.addxy( [DateTime]($_["time"]) , (($_['time-taken']))) > $null; 
               }
           }
           $pointsadded++
        }#each dataarray

        foreach ($item in $chart1.Legends["Legend1"].CustomItems) {$item.MarkerSize = 8}
       #$chart1.Show()
       write-host "save charte $chartname"
       $filename = "$DestinationPath\$ChartName.png"
       $chart1.SaveImage($filename,"png")

【问题讨论】:

    标签: .net powershell exception charts nullreferenceexception


    【解决方案1】:

    我最初的想法是以下是不正确的:

    $e.LegendItems[$i].MarkerSize=10

    根据我使用 Google-foo 阅读的内容,您不能直接更改 markersize。您必须更改SeriesSymbolSize。我可能错了(我之前从未与Datavisualization.Charting 合作过)

    尝试替换:

    for ($i = 0 ; $i -lt $e.LegendItems.Count ; $i++)
    {
        write-host processing $i
    
        if ($e.LegendItems[$i] -eq $null)
        {
            write-host item is null
        }
        else
        {
            write-host item is not null
        }
        #update marker size
        $e.LegendItems[$i].MarkerSize=10
    }
    

    与:

    foreach($item in $e.LegendItems)
    {
        item.Cells(0).SeriesSymbolSize = 10
    }
    

    【讨论】:

    • 不幸的是,这不起作用。 [System.Windows.Forms.DataVisualization.Charting.LegendItem] 不包含名为“Cells”的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-19
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多