Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AssemblyLoadedContext for custom winforms designer serializer #12545

Open
svg2003 opened this issue Nov 26, 2024 · 16 comments
Open

AssemblyLoadedContext for custom winforms designer serializer #12545

svg2003 opened this issue Nov 26, 2024 · 16 comments
Assignees
Labels
area-VSDesigner Windows Forms out-of-proc designer related issues

Comments

@svg2003
Copy link

svg2003 commented Nov 26, 2024

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)
@svg2003 svg2003 added the untriaged The team needs to look at this issue in the next triage label Nov 26, 2024
@merriemcgaw
Copy link
Member

@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?

@merriemcgaw merriemcgaw added area-VSDesigner-32Bit Issues related to 32bit references in VS 64bit and removed untriaged The team needs to look at this issue in the next triage labels Nov 26, 2024
@Tanya-Solyanik Tanya-Solyanik added area-VSDesigner Windows Forms out-of-proc designer related issues and removed area-VSDesigner-32Bit Issues related to 32bit references in VS 64bit labels Nov 26, 2024
@LeafShi1
Copy link
Member

LeafShi1 commented Dec 2, 2024

@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?

@Tanya-Solyanik
Copy link
Member

@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.

@LeafShi1
Copy link
Member

LeafShi1 commented Dec 3, 2024

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
Copy link
Member

LeafShi1 commented Dec 4, 2024

@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

@LeafShi1
Copy link
Member

LeafShi1 commented Dec 4, 2024

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

@svg2003
Copy link
Author

svg2003 commented Dec 4, 2024

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

@svg2003
Copy link
Author

svg2003 commented Dec 12, 2024

@merriemcgaw, @Tanya-Solyanik ,

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

@merriemcgaw
Copy link
Member

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

@svg2003
Copy link
Author

svg2003 commented Dec 19, 2024

@merriemcgaw ,
Thank you for status update

@Shyam-Gupta
Copy link
Member

@svg2003 From the repro project, I found that the assembly containing the custom serializer was getting loaded in UserAssemblyLoadContext which generally loads the user code required at runtime. I am not sure if serializer is required at runtime. So I think, it will be better to use custom serializer using reflection by following syntax on the UserControl:

[DesignerSerializer("MyDesignServer.MySerializer", "Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializer")]
public partial class UserControl1 : UserControl
{
   ...
}

And include the custom serializer assembly as a server-side design time assembly as explained in scenario 2 in this document. The updated NuGet package structure will look like:

Image

This way, the serializer assembly will be loaded at design time only and the serializer will bind to the UserControl using reflection.

@svg2003
Copy link
Author

svg2003 commented Jan 3, 2025

@Shyam-Gupta , thank you for suggestion. Can you please elaborate, because right now it sounds a bit awkward and leads to errors.

Correct me if I wrong, but seems instead of using strong types, you're suggesting to use hardcoded strings, to define link between 2 assemblies, which is for me looks very, very bad design and easy way to make a mistake.
Also, it's not clear how DesignServer would realize, that it needs to copy MyDesignServer.dll when someone is using WinFormsCustomSerializer.dll.

And I tried to change test project, to replace DesignerSerializer(typeof(MySerializer) with your suggested string, and found that inside Cache folder is copied only WinFormsCustomSerializer.dll, so custom serializer type just cannot be found.

[19:01:10.389432] info: TypeResolution: type = System.Drawing.Design.UITypeEditor, TimeTaken = 0 ms.
[19:01:10.389432] info: [WinFormsCustomSerializer]: TypeResolution: type = System.String, TimeTaken = 0 ms.
[19:01:10.390432] info: [WinFormsCustomSerializer]: TypeResolution: type = System.Windows.Forms.ControlBindingsCollection, TimeTaken = 0 ms.
[19:01:20.012941] info: [WinFormsCustomSerializer]: TypeResolution: type = Microsoft.DotNet.DesignTools.Serialization.CodeDomSerializer, TimeTaken = 0 ms.
[19:01:20.012941] info: [WinFormsCustomSerializer]: TypeResolution: type = MyDesignServer.MySerializer not found, TimeTaken = 0 ms.
[19:01:20.012941] info: [WinFormsCustomSerializer]: TypeResolution: type = MyDesignServer.MySerializer not found, TimeTaken = 0 ms.

@Shyam-Gupta
Copy link
Member

Strong type will require a project or assembly reference of MyDesignServer in WinFormsCustomSerializer, and hence MyDesignServer.dll will be required at runtime to load WinFormsCustomSerializer, which can be avoided. By using strings, we don't need a project/assembly reference.
By creating the NuGet package structure I shared, MyDesignServer will be present in the package as a loose assembly and it will not participate in NuGet restore. Designer has an inbuilt logic to walk through the referenced NuGet package structure and copy the assemblies present in lib\<TFM>\Design\WinForms\Server directory to appropriate location in ShadowCache directory. These design time assemblies will get loaded in default AssemblyLoadContext by the designer.

From the error you are seeing, it appears that MyDesignServer.dll is not getting copied to the shadow cache directory. Could you please confirm if you are using the NuGet package in the format I shared?

@svg2003
Copy link
Author

svg2003 commented Jan 3, 2025

No, it is not the package. And I would prefer don't use packages, nor be enforced to select very bad design trade offs (strings instead of strong types; strange, hardcoded paths logic which seems is not documented and may be changed at any moment. packages, where there are non needed, etc, etc) .
Moreover, if using strings for type are mandatory condition and I cannot use Type, why attribute with Type in constructor exist at all?

Let's start with very simple task - I have solution with 2 projects - custom control and custom serializer, which I somehow want to debug, i.e. want serializer logic is called, when I open custom control in the same solution. How solution structure should looks like at this case?

@Shyam-Gupta
Copy link
Member

I am sorry about this complexity. But it stems from the two-process architecture which we have to create in order to support .NET designer and it required a nearly complete rewrite of the designer logic. I would encourage you to refer to this document in which @KlausLoeffelmann has explained this complexity nicely. He has also documented the recommended project structure.

The NuGet package path logic has been documented here and it cannot be changed easily.

@KlausLoeffelmann Please let us know if there is any better way to support the scenario mentioned in the repro steps of this issue.

@svg2003
Copy link
Author

svg2003 commented Jan 4, 2025

Seems Server is using DesignDependecies element from DesignToolsServerManifest.json.
Is there a way beside nuget pass there my own dlls? Or is it possible somehow extend existing functionality to make it working without packages, say as special msbuild items?
Packages are very inconvenient for local development and debugging. Even your test repo examples as they provided are not compilable. And change anything there is the really pain. Designer would just continue use old dlls from cache.

"DesignDependencies": [
"c:\!nuget\PackagesCache\tilerepeater.package\1.251.31529\lib\net6.0\design\winforms\server\TileRepeater.ClientServerProtocol.dll",
"c:\!nuget\PackagesCache\tilerepeater.package\1.251.31529\lib\net6.0\design\winforms\server\TileRepeater.Designer.Server.dll"
],

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-VSDesigner Windows Forms out-of-proc designer related issues
Projects
None yet
Development

No branches or pull requests

5 participants