Hi,
in our application we dynamically add/remove ribbon tabs based on the selected tab of a tab control. This causes the application to crash when changing DPI of the screen or when (re)connecting to the machine via RDP while the application is running.
I've managed to create a minimal working example that exhibits the crash immediately on startup, without the need for RDP sessions and DPI changes. You can find it on Github. Simply starting the application causes a crash with the following stacktrace:
Unhandled Exception: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at ActiproSoftware.Windows.Controls.Ribbon.Ribbon.P3(Object , RoutedEventArgs )
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.UIElement.RaiseEvent(RoutedEventArgs e)
at System.Windows.BroadcastEventHelper.BroadcastEvent(DependencyObject root, RoutedEvent routedEvent)
at System.Windows.BroadcastEventHelper.BroadcastLoadedEvent(Object root)
at MS.Internal.LoadedOrUnloadedOperation.DoWork()
at System.Windows.Media.MediaContext.FireLoadedPendingCallbacks()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.Resize(ICompositionTarget resizedCompositionTarget)
at System.Windows.Interop.HwndTarget.OnResize()
at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(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.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.HwndSubclass.DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
The modification of the collection happens in DetailView.TabControlOnSelectionChanged() which is called by WPF in a Stacktrace with Ribbon.OnLoaded() (obfuscated Ribbon.P3()) below it:
WpfApp31.exe!WpfApp31.DetailView.TabControlOnSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) Line 28
PresentationFramework.dll!System.Windows.Controls.SelectionChangedEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget)
PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target)
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs)
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args)
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e)
PresentationFramework.dll!System.Windows.Controls.TabControl.OnSelectionChanged(System.Windows.Controls.SelectionChangedEventArgs e)
PresentationFramework.dll!System.Windows.Controls.Primitives.Selector.InvokeSelectionChanged(System.Collections.Generic.List<System.Windows.Controls.ItemsControl.ItemInfo> unselectedInfos, System.Collections.Generic.List<System.Windows.Controls.ItemsControl.ItemInfo> selectedInfos)
PresentationFramework.dll!System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
PresentationFramework.dll!System.Windows.Controls.Primitives.Selector.SelectionChanger.SelectJustThisItem(System.Windows.Controls.ItemsControl.ItemInfo info, bool assumeInItemsCollection)
PresentationFramework.dll!System.Windows.Controls.Primitives.Selector.OnSelectedIndexChanged(System.Windows.DependencyObject d, System.Windows.DependencyPropertyChangedEventArgs e)
WindowsBase.dll!System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e)
PresentationFramework.dll!System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs e)
WindowsBase.dll!System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs args)
WindowsBase.dll!System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex entryIndex, System.Windows.DependencyProperty dp, System.Windows.PropertyMetadata metadata, System.Windows.EffectiveValueEntry oldEntry, ref System.Windows.EffectiveValueEntry newEntry, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType)
WindowsBase.dll!System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty dp, object value, System.Windows.PropertyMetadata metadata, bool coerceWithDeferredReference, bool coerceWithCurrentValue, System.Windows.OperationType operationType, bool isInternal)
WindowsBase.dll!System.Windows.DependencyObject.SetCurrentValueInternal(System.Windows.DependencyProperty dp, object value)
PresentationFramework.dll!System.Windows.Controls.TabControl.OnGeneratorStatusChanged(object sender, System.EventArgs e)
PresentationFramework.dll!System.Windows.Controls.ItemContainerGenerator.SetStatus(System.Windows.Controls.Primitives.GeneratorStatus value)
PresentationFramework.dll!System.Windows.Controls.ItemContainerGenerator.Generator.System.IDisposable.Dispose()
PresentationFramework.dll!System.Windows.Controls.Panel.GenerateChildren()
PresentationFramework.dll!System.Windows.Controls.Panel.EnsureGenerator()
PresentationFramework.dll!System.Windows.Controls.Panel.InternalChildren.get()
PresentationFramework.dll!System.Windows.Controls.Primitives.TabPanel.MeasureOverride(System.Windows.Size constraint)
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize)
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureCell(int cell, bool forceInfinityV)
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureCellsGroup(int cellsHead, System.Windows.Size referenceSize, bool ignoreDesiredSizeU, bool forceInfinityV, out bool hasDesiredSizeUChanged)
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureCellsGroup(int cellsHead, System.Windows.Size referenceSize, bool ignoreDesiredSizeU, bool forceInfinityV)
PresentationFramework.dll!System.Windows.Controls.Grid.MeasureOverride(System.Windows.Size constraint)
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize)
PresentationFramework.dll!System.Windows.Controls.Control.MeasureOverride(System.Windows.Size constraint)
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize)
PresentationFramework.dll!MS.Internal.Helper.MeasureElementWithSingleChild(System.Windows.UIElement element, System.Windows.Size constraint)
PresentationFramework.dll!System.Windows.Controls.ContentPresenter.MeasureOverride(System.Windows.Size constraint)
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayout()
PresentationCore.dll!System.Windows.UIElement.UpdateLayout()
ActiproSoftware.Ribbon.Wpf.dll!ActiproSoftware.Windows.Controls.Ribbon.Controls.Group.axe(bool ) Line 405
ActiproSoftware.Ribbon.Wpf.dll!ActiproSoftware.Windows.Controls.Ribbon.Ribbon.P3(object , System.Windows.RoutedEventArgs ) Line 1038
PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs)
PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source, System.Windows.RoutedEventArgs args, bool reRaised)
PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender, System.Windows.RoutedEventArgs args)
PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs e)
PresentationFramework.dll!System.Windows.BroadcastEventHelper.BroadcastEvent(System.Windows.DependencyObject root, System.Windows.RoutedEvent routedEvent)
PresentationFramework.dll!System.Windows.BroadcastEventHelper.BroadcastLoadedEvent(object root)
PresentationCore.dll!MS.Internal.LoadedOrUnloadedOperation.DoWork()
PresentationCore.dll!System.Windows.Media.MediaContext.FireLoadedPendingCallbacks()
PresentationCore.dll!System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandlerCore(object resizedCompositionTarget)
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandler(object resizedCompositionTarget)
PresentationCore.dll!System.Windows.Media.MediaContext.Resize(System.Windows.Media.ICompositionTarget resizedCompositionTarget)
PresentationCore.dll!System.Windows.Interop.HwndTarget.OnResize()
PresentationCore.dll!System.Windows.Interop.HwndTarget.HandleMessage(MS.Internal.Interop.WindowMessage msg, System.IntPtr wparam, System.IntPtr lparam)
PresentationCore.dll!System.Windows.Interop.HwndSource.HwndTargetFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler)
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs)
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!MS.Win32.HwndSubclass.DefWndProcWrapper(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)
[Native to Managed Transition]
[Managed to Native Transition]
ActiproSoftware.Shared.Wpf.dll!ActiproSoftware.Windows.Interop.NativeMethods.ConfigureNonClientArea(System.Windows.Window window, bool isIconVisible, bool isTitleVisible) Line 310
ActiproSoftware.Shared.Wpf.dll!ActiproSoftware.Windows.Themes.WindowChromeManager.Hko() Line 607
ActiproSoftware.Shared.Wpf.dll!ActiproSoftware.Windows.Themes.WindowChromeManager.rkN() Line 625
ActiproSoftware.Shared.Wpf.dll!ActiproSoftware.Windows.Themes.WindowChromeManager.OkP(object , System.EventArgs ) Line 738
PresentationFramework.dll!System.Windows.Window.OnSourceInitialized(System.EventArgs e)
PresentationFramework.dll!System.Windows.Window.CreateSourceWindow(bool duringShow)
PresentationFramework.dll!System.Windows.Window.CreateSourceWindowDuringShow()
PresentationFramework.dll!System.Windows.Window.SafeCreateWindowDuringShow()
PresentationFramework.dll!System.Windows.Window.ShowHelper(object booleanBox)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl()
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state)
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(object obj)
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext executionContext, System.Threading.ContextCallback callback, object state)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke()
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue()
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler)
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs)
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame)
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame)
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore)
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window)
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window)
PresentationFramework.dll!System.Windows.Application.Run()
WpfApp31.exe!WpfApp31.App.Main()
We are not quiet sure what to do here. Would this be a bug in Actipro? Is there something we can do in our application to force the tab selection event to happen earlier or later so it doesn't interfere with Ribbon.OnLoaded()?
[Modified 4 years ago]