dotnet/winforms

AssemblyLoadedContext for custom winforms designer serializer

Opened this issue · 10 comments

Environment

MSVS 17.11.6

.NET version

net8

Did this work in a previous version of Visual Studio and/or previous .NET release?

no

Issue description

I'm trying to port netframework's custom designer serializer into net8.
I've created separate project, using Microsoft.WinForms.Designer.SDK, and put serializer there, so it's instantiated by WinFormsDesigner code, but assembly is loaded into UserAssemblyLoadContext, whereas types, returned by IDesignerSerializerManager - are from Default context.
As the result, it's impossible to mix them together, due to even type cast would give an exception:

[18:10:21.375488] fail: [WinFormsCustomSerializer]: Ex: System.InvalidCastException: [A]System.CodeDom.CodeStatementCollection cannot be cast to [B]System.CodeDom.CodeStatementCollection. Type A originates from 'System.CodeDom, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context 'Default' at location 'C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.11\System.CodeDom.dll'. Type B originates from 'System.CodeDom, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context '"UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0' at location 'c:\views!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll'.

winforms-designerServerContext.zip

Steps to reproduce

1. Create separate project for custom serializer, using Microsoft.WinForms.Designer.SDK:

Image

2. Add some dummy serializer there:

Image

3. Create winforms project and add some user control there, with customer serializer:

Image

Image

4. Use that control on winforms:

Image

5. Try to change control (say, size), and save it.
It will give an exception in log (due to mismatched types)

Image

Image

Here is how serializer is created (by WinFormsServer):

Image

[18:10:21.363486] fail: [WinFormsCustomSerializer]: Creating from at System.Environment.get_StackTrace()
[18:10:21.364486] fail: [WinFormsCustomSerializer]: at MyDesignServer.MySerializer..ctor()
[18:10:21.364486] fail: [WinFormsCustomSerializer]: at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
[18:10:21.364486] fail: [WinFormsCustomSerializer]: at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.DesignerSerializationManager.GetSerializer(Type objectType, Type serializerType)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.DesignerSerializationManager.System.ComponentModel.Design.Serialization.IDesignerSerializationManager.GetSerializer(Type objectType, Type serializerType)
[18:10:21.365486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializationStore.ComponentListCodeDomSerializer.Serialize(IDesignerSerializationManager manager, IDictionary objectData, IDictionary objectState, IList shimObjectNames)
[18:10:21.366487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializationStore.Close()
[18:10:21.366487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ChangeUndoEvent.Serialize(UndoEngine engine, Object component, MemberDescriptor member)
[18:10:21.366487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ChangeUndoEvent..ctor(UndoEngine engine, ComponentChangingEventArgs e, Boolean serializeBeforeState)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ComponentChanging(ComponentChangingEventArgs e)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Undo.UndoEngine.OnComponentChanging(Object sender, ComponentChangingEventArgs e)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Host.RemoteDesignerHost.System.ComponentModel.Design.IComponentChangeService.OnComponentChanging(Object component, MemberDescriptor member)
[18:10:21.367487] fail: [WinFormsCustomSerializer]: at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Designers.Behaviors.ResizeBehavior.OnMouseMove(Glyph glyph, MouseButtons button, Point adornerCoordinates)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Designers.Behaviors.BehaviorService.OnMouseMove(InputDispatchEventArgs e)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Designers.Behaviors.BehaviorService.Dispatcher.OnMouseMove(InputDispatchEventArgs e)
[18:10:21.368487] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Protocol.Endpoints.Input.InputMessageHandler.HandleRequest(InputMessageRequest request)
[18:10:21.369486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Protocol.Endpoints.RequestHandler2.Microsoft.DotNet.DesignTools.Protocol.Endpoints.IRequestHandler.HandleRequest(Request request) [18:10:21.369486] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Protocol.Endpoints.RequestManager.HandleRequestAsync(String name, Request request) [18:10:21.369486] fail: [WinFormsCustomSerializer]: at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1.AsyncStateMachineBox1.ExecutionContextCallback(Object s) [18:10:21.369486] fail: [WinFormsCustomSerializer]: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1.AsyncStateMachineBox1.MoveNext(Thread threadPoolThread) [18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Runtime.CompilerServices.AsyncTaskMethodBuilder1.AsyncStateMachineBox`1.MoveNext()
[18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
[18:10:21.370487] fail: [WinFormsCustomSerializer]: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[18:10:21.371488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
[18:10:21.371488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.WndProc(Message& m)
[18:10:21.371488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Server.Window.ServerWindow.WndProc(Message& m)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)
[18:10:21.372488] fail: [WinFormsCustomSerializer]: at Windows.Win32.PInvoke.DispatchMessage(MSG* lpMsg)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Application.ComponentManager.Microsoft.Office.IMsoComponentManager.FPushMessageLoop(UIntPtr dwComponentID, msoloop uReason, Void* pvLoopData)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(msoloop reason, ApplicationContext context)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(msoloop reason, ApplicationContext context)
[18:10:21.373488] fail: [WinFormsCustomSerializer]: at Microsoft.DotNet.DesignTools.Server.DesignToolsServer.<>c__DisplayClass55_0.b__1()
[18:10:21.374487] fail: [WinFormsCustomSerializer]: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[18:10:21.374487] fail: [WinFormsCustomSerializer]: Serializer constructor: c:\views!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll.
[18:10:21.374487] fail: [WinFormsCustomSerializer]: Context: "UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0

Diagnostics

[19:42:14.170246] info: [WinFormsCustomSerializer]: TypeResolution: type = MyDesignServer.MySerializer, TimeTaken = 0 ms.
[19:42:14.171247] fail: [WinFormsCustomSerializer]: Creating from    at System.Environment.get_StackTrace()
[19:42:14.171247] fail: [WinFormsCustomSerializer]:    at MyDesignServer.MySerializer..ctor()
[19:42:14.171247] fail: [WinFormsCustomSerializer]:    at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
[19:42:14.171247] fail: [WinFormsCustomSerializer]:    at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
[19:42:14.172250] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Serialization.DesignerSerializationManager.GetSerializer(Type objectType, Type serializerType)
[19:42:14.172250] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializationStore.ComponentListCodeDomSerializer.Serialize(IDesignerSerializationManager manager, IDictionary objectData, IDictionary objectState, IList shimObjectNames)
[19:42:14.172250] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializationStore.Close()
[19:42:14.172250] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ChangeUndoEvent.Serialize(UndoEngine engine, Object component, MemberDescriptor member)
[19:42:14.173249] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ChangeUndoEvent..ctor(UndoEngine engine, ComponentChangingEventArgs e, Boolean serializeBeforeState)
[19:42:14.173249] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Undo.UndoEngine.UndoUnit.ComponentChanging(ComponentChangingEventArgs e)
[19:42:14.173249] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Undo.UndoEngine.OnComponentChanging(Object sender, ComponentChangingEventArgs e)
[19:42:14.173249] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Host.RemoteDesignerHost.System.ComponentModel.Design.IComponentChangeService.OnComponentChanging(Object component, MemberDescriptor member)
[19:42:14.174251] fail: [WinFormsCustomSerializer]:    at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
[19:42:14.174251] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Designers.Behaviors.ResizeBehavior.OnMouseMove(Glyph glyph, MouseButtons button, Point adornerCoordinates)
[19:42:14.174251] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Designers.Behaviors.BehaviorService.OnMouseMove(InputDispatchEventArgs e)
[19:42:14.174251] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Protocol.Endpoints.Input.InputMessageHandler.HandleRequest(InputMessageRequest request)
[19:42:14.175250] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Protocol.Endpoints.RequestHandler`2.Microsoft.DotNet.DesignTools.Protocol.Endpoints.IRequestHandler.HandleRequest(Request request)
[19:42:14.175250] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Protocol.Endpoints.RequestManager.HandleRequestAsync(String name, Request request)
[19:42:14.175250] fail: [WinFormsCustomSerializer]:    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[19:42:14.175250] fail: [WinFormsCustomSerializer]:    at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread)
[19:42:14.176251] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
[19:42:14.176251] fail: [WinFormsCustomSerializer]:    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[19:42:14.176251] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
[19:42:14.176251] fail: Request failures: Input/InputMessage.
                        Microsoft.DotNet.DesignTools.Client.DesignToolsServerException: [A]System.CodeDom.CodeStatementCollection cannot be cast to [B]System.CodeDom.CodeStatementCollection. Type A originates from 'System.CodeDom, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context 'Default' at location 'C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.11\System.CodeDom.dll'. Type B originates from 'System.CodeDom, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context '"UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0' at location 'c:\views\!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll'.

                        For information on how to troubleshoot the designer refer to the guide at https://aka.ms/winforms/designer/troubleshooting.
[19:42:14.176251] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.Control.WndProc(Message& m)
[19:42:14.177251] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.Form.WndProc(Message& m)
[19:42:14.177251] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Server.Window.ServerWindow.WndProc(Message& m)
[19:42:14.177251] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.NativeWindow.Callback(HWND hWnd, MessageId msg, WPARAM wparam, LPARAM lparam)
[19:42:14.178250] fail: [WinFormsCustomSerializer]:    at Windows.Win32.PInvoke.DispatchMessage(MSG* lpMsg)
[19:42:14.178250] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.Application.ComponentManager.Microsoft.Office.IMsoComponentManager.FPushMessageLoop(UIntPtr dwComponentID, msoloop uReason, Void* pvLoopData)
[19:42:14.178250] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(msoloop reason, ApplicationContext context)
[19:42:14.178250] fail: [WinFormsCustomSerializer]:    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(msoloop reason, ApplicationContext context)
[19:42:14.179250] fail: [WinFormsCustomSerializer]:    at Microsoft.DotNet.DesignTools.Server.DesignToolsServer.<>c__DisplayClass55_0.<StartUIThreadAsync>b__1()
[19:42:14.179250] fail: [WinFormsCustomSerializer]:    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
[19:42:14.179250] fail: [WinFormsCustomSerializer]: Serializer constructor: c:\views\!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll.
[19:42:14.179250] fail: [WinFormsCustomSerializer]: Context: "UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0
[19:42:14.179250] info: [WinFormsCustomSerializer]: TypeResolution: type = Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializationProvider, TimeTaken = 0 ms.
[19:42:14.179250] info: [WinFormsCustomSerializer]: TypeResolution: type = Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializer, TimeTaken = 0 ms.
[19:42:14.180251] info: [WinFormsCustomSerializer]: TypeResolution: type = Microsoft.DotNet.DesignTools.Designers.ControlDesigner+DesignerControlCollectionCodeDomSerializer, TimeTaken = 0 ms.
[19:42:14.180251] fail: [WinFormsCustomSerializer]: obj type: System.CodeDom.CodeStatementCollection (C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.11\System.CodeDom.dll). Context: "Default" System.Runtime.Loader.DefaultAssemblyLoadContext #1
[19:42:14.180251] fail: [WinFormsCustomSerializer]: serializer type: System.CodeDom.CodeStatementCollection (c:\views\!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll). Context: "UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0
[19:42:14.180251] fail: [WinFormsCustomSerializer]: Ex: System.InvalidCastException: [A]System.CodeDom.CodeStatementCollection cannot be cast to [B]System.CodeDom.CodeStatementCollection. Type A originates from 'System.CodeDom, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context 'Default' at location 'C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.11\System.CodeDom.dll'. Type B originates from 'System.CodeDom, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' in the context '"UserAssemblyLoadContext" Microsoft.DotNet.DesignTools.Services.TypeResolutionService+UserAssemblyLoadContext #0' at location 'c:\views\!nuget\PackagesCache\system.codedom\4.6.0\lib\netstandard2.0\System.CodeDom.dll'.
[19:42:14.181252] fail: [WinFormsCustomSerializer]:    at MyDesignServer.MySerializer.Serialize(IDesignerSerializationManager manager, Object value)

@LeafShi1 can your team take a look to let us know if it is something missing in our SDK or if this is something that @svg2003 can do on their end?

@LeafShi1 can your team take a look to let us know if it is something missing in our SDK or if this is something that @svg2003 can do on their end?

This should be a problem in the Winform Designer repo. When we package WinForms.Designer.SDK, the referenced package System.CodeDom is a hard-coded value (currently SystemCodeDomVersion=5.0)

If WinForms.Designer.SDK removes the reference to the package System.CodeDom, then everything works fine here.

At design time, System.CodeDom under Microsoft.WindowsDesktop.App.WindowsForms can be used, and At Runtime, System.CodeDom under .Net SDK can be used. So can we consider removing System.CodeDom from the Microsoft.Winforms.Designer.SDK package?

@merriemcgaw @Tanya-Solyanik What do you think?

@LeafShi1 - we need to know if System.CodeDOM.dll is included in PlatformManifest.txt for SDK for NET5, I don't know where this file is located in the GH, NET8 is here - https://github.com/dotnet/windowsdesktop/blob/release/8.0/src/windowsdesktop/src/sfx/PlatformManifest.txt before we remove it from the designer SDK package. And we need to confirm that all supported versions of .NET, starting with .NET5 work correctly with System.CodeDOM from the windowsdesktop SDK.

NET5 is no longer supported since 2022, and the Release/5.0 branch has been deleted, so it is not certain whether System.CodeDOM.dll is included in the PlatformManifest.txt file of Net5

But from the created .Net5.0 project, it can be seen that System.CodeDOM.dll points to the correct version
Image

I verified with the customer's project CustomControl_Tab (2) 1.zip in diference .NET version, everything works fine (the package WinForms.Designer.SDK used in the project removed System.CodeDom)
SDKWithoutCodeDom.zip

@LeafShi1 - we need to know if System.CodeDOM.dll is included in PlatformManifest.txt for SDK for NET5, I don't know where this file is located in the GH, NET8 is here - https://github.com/dotnet/windowsdesktop/blob/release/8.0/src/windowsdesktop/src/sfx/PlatformManifest.txt before we remove it from the designer SDK package. And we need to confirm that all supported versions of .NET, starting with .NET5 work correctly with System.CodeDOM from the windowsdesktop SDK.

It can be found in Net6 and Net7:

In NET6: https://github.com/dotnet/windowsdesktop/blob/7a6bfe6311159ed7f186dc670bb34dbb3d92a48f/pkg/windowsdesktop/sfx/PlatformManifest.txt#L31
In NET7: https://github.com/dotnet/windowsdesktop/blob/8a5915b0acdec36b60fcd5a82890a2d87da3a6ff/pkg/windowsdesktop/sfx/PlatformManifest.txt#L32

This issue is tracked using issue #6200 in the WinForm Designer repo

Thank you for checking.
Is it feasible to provide ETA when fix would be available for public? Do you have any release plan?

@merriemcgaw, @Tanya-Solyanik ,

Could you please comment when fix would be available for public? Do you have any release plan?

We are still investigating in our internal repo. We do not have a solution just yet but will update once we do.

@merriemcgaw ,
Thank you for status update