I have a WPF application that does some integration with legacy Infragistics/winforms.
On a fairly regular basis we get fatal exceptions that are sent out from the depths of an Infragistics call stack. They are "ArgumentExceptions" from System.Drawing.Graphics.GetHdc() - which is typically called from some Infragistics component, eg (Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureTextGDIOrThemed(String text, Font font, TextFormatFlags textFormatFlags).
My recollection is that IG does some internal caching of win32 Device Context information and it misbehaves in certain circumstances. Are there any tips you can give us for making this stuff work in a more reliable way? I have already tried including this magical method call in a number of places: Infragistics.Win.DrawUtility.BeginGraphicsCaching() ...
... but that doesn't seem to fully fix the problem. It would be nice if the exception had more information for us to use in our troubleshooting, or if these winforms controls could do a better job at recovering from their own internal problems with their own cached data.
Below is an example of a full stack trace.
Application: UFP.LumberTrack.Production.Mill.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ArgumentException
at System.Drawing.Graphics.GetHdc()
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureTextGDIOrThemed(String text, Font font, TextFormatFlags textFormatFlags)
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureCharacterRangesGDI(String text, Font font, TextFormatFlags textFormatFlags, CharacterRange[] ranges)
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.ReMeasureParts(String text, Int32[] parts, Single[] widths, Int32 partStartIndex, Int32 partEndIndex, Font font, Single& lineHeight)
at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureParts(String text, Int32[] parts, Font font, Single& lineHeight)
at Infragistics.Win.FormattedLinkLabel.NodeText.TextLayoutInfo.Measure(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeText.PositionSelf(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBase.PositionHelper(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBase.PositionChildNodes(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBlock.PositionChildNodes(PositionElementsInfo& info)
at Infragistics.Win.FormattedLinkLabel.NodeBase.CalcSize(IFormattedLinkLabelOwner owner, Graphics graphics, Int32 maxWidth)
at Infragistics.Win.UltraWinToolbars.Ribbon.RibbonMetrics.CalculateCaptionAreaHeight()
at Infragistics.Win.UltraWinToolbars.Ribbon.RibbonMetrics.GetRibbonHeight(Boolean isAutoHideRibbonPopup)
at Infragistics.Win.UltraWinToolbars.UltraToolbarsDockArea.RefreshDockAreaSize(Size& currentSize)
at Infragistics.Win.UltraWinToolbars.UltraToolbarsDockArea.SetBoundsCore(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
at System.Windows.Forms.Control.System.Windows.Forms.Layout.IArrangedElement.SetBounds(Rectangle bounds, BoundsSpecified specified)
at System.Windows.Forms.Layout.DefaultLayout.xLayoutDockedControl(IArrangedElement element, Rectangle newElementBounds, Boolean measureOnly, Size& preferredSize, Rectangle& remainingBounds)
at System.Windows.Forms.Layout.DefaultLayout.LayoutDockedControls(IArrangedElement container, Boolean measureOnly)
at System.Windows.Forms.Layout.DefaultLayout.xLayout(IArrangedElement container, Boolean measureOnly, Size& preferredSize)
at System.Windows.Forms.Layout.DefaultLayout.LayoutCore(IArrangedElement container, LayoutEventArgs args)
at System.Windows.Forms.Layout.LayoutEngine.Layout(Object container, LayoutEventArgs layoutEventArgs)
at System.Windows.Forms.Control.OnLayout(LayoutEventArgs levent)
at System.Windows.Forms.ScrollableControl.OnLayout(LayoutEventArgs levent)
at System.Windows.Forms.Form.OnLayout(LayoutEventArgs levent)
at System.Windows.Forms.Control.PerformLayout(LayoutEventArgs args)
at System.Windows.Forms.Control.PerformLayout()
at System.Windows.Forms.Control.ResumeLayout(Boolean performLayout)
at UFP.LumberTrack.Shared.Windows.Forms.UfpBaseForm.Show(Form p_Parent)
at UFP.LumberTrack.Production.Presentation.AppLaunchers.InventoryControlLauncher.LaunchInventoryControl(IProvideParentForWindow ParentForWindow, String p_ActiveBranchCode, String p_AppServerProUserName, String p_ProductType, String p_ProductCode, Boolean p_UseSpecificLengthCode, String p_LengthCode)
at UFP.LumberTrack.Production.Kiln.Workspace.Sources.Viewers.InventoryLevelItemSelection.ExecuteShowInventoryControl(IInventoryManagementItem p_Item)
at UFP.LumberTrack.Production.Kiln.Workspace.Sources.Viewers.InventoryLevelItemSelection.DataRecordPresenter_MouseDoubleClick(Object p_Sender, MouseButtonEventArgs p_Args)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.Controls.Control.HandleDoubleClick(Object sender, MouseButtonEventArgs e)
at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
at System.Windows.UIElement.OnMouseDownThunk(Object sender, MouseButtonEventArgs e)
at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at UFP.LumberTrack.Production.Mill.MfgManagement.MfgProgram.Main()
We are still facing the "Parameter is not valid." from time-to-time
... at System.Drawing.Graphics.GetHdc()
Just as I described above. The real annoyance is that if you google this error outside the context of Infragistics, there are often some "legitimate" reasons for the error. It can happen, for example, if you run out of GDI objects in certain extreme situations.
... but in the context of the Infragistics winforms code, the meaning of the error becomes a lot less certain. It has nothing to do with GDI resources, nor does it have a legitimate root cause. It seems to be an Infragistics logic bug rather than a GDI bug. for example here is a callstack:
Stack trace: at System.Drawing.Graphics.GetHdc() at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureTextGDIOrThemed(String text, Font font, TextFormatFlags textFormatFlags) at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureCharacterRangesGDI(String text, Font font, TextFormatFlags textFormatFlags, CharacterRange[] ranges) at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.ReMeasureParts(String text, Int32[] parts, Single[] widths, Int32 partStartIndex, Int32 partEndIndex, Font font, Single& lineHeight) at Infragistics.Win.FormattedLinkLabel.PositionElementsCache.MeasureParts(String text, Int32[] parts, Font font, Single& lineHeight) at Infragistics.Win.FormattedLinkLabel.NodeText.TextLayoutInfo.Measure(PositionElementsInfo& info) at Infragistics.Win.FormattedLinkLabel.NodeText.PositionSelf(PositionElementsInfo& info) at Infragistics.Win.FormattedLinkLabel.NodeBase.PositionHelper(PositionElementsInfo& info) at Infragistics.Win.FormattedLinkLabel.NodeBase.PositionChildNodes(PositionElementsInfo& info) at Infragistics.Win.FormattedLinkLabel.NodeBlock.PositionChildNodes(PositionElementsInfo& info) at Infragistics.Win.FormattedLinkLabel.NodeBase.CalcSize(IFormattedLinkLabelOwner owner, Graphics graphics, Int32 maxWidth) at Infragistics.Win.UltraWinToolbars.Ribbon.RibbonMetrics.CalculateCaptionAreaHeight()
That stack is telling me that the bug is relate to the ribbon, on a UltraWinToolbar, and that the ribbon cannot calculate it's area.
While calculating the area, it is trying to measure the size of a "FormattedLinkLabel", and that is making use of a "PositionElementsCache". I suspect failures are a result of a poor caching strategy within the Infragistics winforms controls.
Another thing that makes the bug frustrating is that it isn't consistent. I can have twenty users who never see it, and one who gets it all the time. Even though they are doing the exact same things.
I did some research and found a couple other anecdotes about people having the same problem:
After much teeth-gnashing I found somewhere (can't remember where) that setting the IsGlassSupported property on the UltraToolbarsManager to False solved the problem. It certainly worked for me.
We put the change to remove the IsGlassSupported for the ribbon and have no reported crashes in over a week of customer use.
So to make a long story short, it seems that the problem is not unique to me, and others have struggled as well. The workaround is extremely obscure (IsGlassSupported to false) and I don't understand why Infragistics doesn't improve this situation in one of their winforms releases. It would take far less time to do something on your end than to leave customers to fend for themselves and try discovering the workaround. Here are my suggestions:
Hope one of these things sounds reasonable.
Hello,
I am not aware of any current known issues related to GetHdc(). Have you had the opportunity to test this with the latest version? Please let me know whether updating helps to resolve this.
We use 16.1.20161.2141 (for both winforms and wpf).
It appears that there may be a history behind this error and it was "fixed" in a service release several years ago. Are there any outstanding/known issues that would produce the same exception?