One of our MacroView Studio customers sent a strange stack trace from an application crash yesterday. It's strange in that the standard Windows Forms ImageListStreamer class is where the exception occurs. The exception being thrown is a TargetInvocationException wrapping an InvalidOperationException and occurs as a result of very basic form constructor code which is run many times in the application and hence many users will run that code during normal operation. As is typical with tough to resolve faults, I can't reproduce it in the office and will wait for more information from the customer if it occurs again. Regardless the symptoms and some results of web research into the problem has been posted here for any other poor souls that encounter it and also for my own benefit as a record. Here's the stack trace:
Exception Details:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Loading of the ImageList did not succeed.
at System.Windows.Forms.ImageListStreamer..ctor(SerializationInfo info, StreamingContext context)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle._SerializationInvoke(Object target, SignatureStruct& declaringTypeSig, SerializationInfo info, StreamingContext context)
at System.RuntimeMethodHandle.SerializationInvoke(Object target, SignatureStruct declaringTypeSig, SerializationInfo info, StreamingContext context)
at System.Reflection.RuntimeConstructorInfo.SerializationInvoke(Object target, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Resources.ResourceReader.DeserializeObject(Int32 typeIndex)
at System.Resources.ResourceReader.LoadObjectV2(Int32 pos, ResourceTypeCode& typeCode)
at System.Resources.ResourceReader.LoadObject(Int32 pos, ResourceTypeCode& typeCode)
at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase, Boolean isString)
at System.Resources.RuntimeResourceSet.GetObject(String key, Boolean ignoreCase)
at System.Resources.ResourceManager.GetObject(String name, CultureInfo culture, Boolean wrapUnmanagedMemStream)
at System.Resources.ResourceManager.GetObject(String name)
at Syncfusion.Windows.Forms.Edit.FindReplaceDlg.InitializeComponent()
at Syncfusion.Windows.Forms.Edit.FindReplaceDlg..ctor()
at Syncfusion.Windows.Forms.Edit.EditControl..ctor()
at MacroView.Script.MetascriptEditControl.InitializeComponent()
at MacroView.Script.MetascriptEditControl..ctor()
at MacroView.Script.MetascriptEditor.InitializeComponent()
at MacroView.Script.MetascriptEditor..ctor()
Some links that are relevant:
It appears from web searches on the problem is that it is likely to be caused by accessing winform controls from other than the GUI thread and/or the visual styles functionality. This theory is re-enforced by looking at the code for the System.Windows.Forms.ImageListStreamer class serialization constructor using Reflector. The constructor includes native platform theming calls and synchronization support. I don't what goes on to cause the fault but it's very subtle and is rare. At first I suspected the Syncfusion (legacy) edit control of perform winform control actions across threads but the debugger showed that although the thread code was there, it shouldn't ever be called in the MacroView Studio application scenario.
IntPtr ptr1 = UnsafeNativeMethods.ThemingScope.Activate();
try
{
MemoryStream stream1 = new MemoryStream(this.Decompress(buffer1));
lock (ImageListStreamer.internalSyncObject)
{
SafeNativeMethods.InitCommonControls();
this.nativeImageList = new ImageList.NativeImageList(SafeNativeMethods.ImageList_Read(
new UnsafeNativeMethods.ComStreamFromDataStream(stream1)));
}
}
finally
{
UnsafeNativeMethods.ThemingScope.Deactivate(ptr1);
}
if (this.nativeImageList.Handle == IntPtr.Zero)
{
throw new InvalidOperationException(SR.GetString("ImageListStreamerLoadFailed"));
}