dotnet / winforms

Windows Forms is a .NET UI framework for building Windows desktop applications.
MIT License
4.42k stars 984 forks source link

The designer does not work for a custom language and .Net Framework #8381

Closed RobertvanderHulst closed 1 year ago

RobertvanderHulst commented 1 year ago

Environment

VS 2022 17.5.0 Preview 2 X# 2.14

.NET version

.Net Framework 4.7.2 (but same problem for all other versions of .Net Framework)

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

Did not try this before

Issue description

We have a custom .Net language X#. We support the in process Windows Forms Designer. To do so, our language has is own CodeDomProvider. Whenever VS asks the project system for the codedomprovider we give it an instance of our own provider. We have also registered this provider inside machine.config, so the code generator gets called when necessary (for example to generate the code for WPF projects):

 <system.codedom>
    <compilers>
      <compiler language="XSharp" extension=".prg" type="XSharp.CodeDom.XSharpCodeDomProvider,XSharpCodeDomProvider, Version=2.14.0.4, Culture=neutral, PublicKeyToken=ed555a0467764586, ProcessorArchitecture=MSIL" />
    </compilers>
  </system.codedom>

With the new out of process designer the forms do not load.

Steps to reproduce

Diagnostics

[12:25:08.396101] info: Creating VsDesignerLoader
[12:25:08.545943] info: [Thread 1] Creating design-time ITypeResolutionService.
[12:25:08.634083] info: Start processing enqueued assemblies
[12:25:08.634083] trce: Loaded Microsoft.WinForms.DesignTools.Protocol in 00:00:00.0000296 [thread 78]
[12:25:08.647595] trce: Processed 'Microsoft.WinForms.DesignTools.Protocol' in 00:00:00.0134897
[12:25:08.650594] info: Added 'Microsoft.WinForms.DesignTools.Protocol'
[12:25:08.651594] trce: Loaded Microsoft.WinForms.DesignTools.Client in 00:00:00.0000094 [thread 77]
[12:25:08.680089] trce: Processed 'Microsoft.WinForms.DesignTools.Client' in 00:00:00.0289660
[12:25:08.683089] info: Added 'Microsoft.WinForms.DesignTools.Client'
[12:25:08.835303] info: Visual Studio culture: en-US (0x0409)
[12:25:08.835303] info: [Thread 97] Launching server...
[12:25:08.841304] info: Is processor architecture ARM64: False
[12:25:09.495021] info: Added 'mscorlib'
[12:25:09.495021] trce: Loaded System.Windows.Forms in 00:00:00.0000178 [thread 94]
[12:25:09.499032] trce: Processed 'System.Windows.Forms' in 00:00:00.0033508
[12:25:09.517557] info: Added 'System.Windows.Forms'
[12:25:09.517557] trce: Loaded System in 00:00:00.0000135 [thread 6]
[12:25:09.518556] trce: Processed 'System' in 00:00:00.0007920
[12:25:09.536070] info: Added 'System'
[12:25:09.537070] trce: Loaded System.Drawing in 00:00:00.0000162 [thread 95]
[12:25:09.537070] trce: Processed 'System.Drawing' in 00:00:00.0001036
[12:25:09.539071] info: Added 'System.Drawing'
[12:25:09.539071] trce: Loaded System.Design in 00:00:00.0000096 [thread 11]
[12:25:09.648223] trce: Processed 'System.Design' in 00:00:00.1097627
[12:25:09.653224] info: Prefer32Bit: True
[12:25:09.663747] info: Added 'System.Design'
[12:25:09.663747] trce: Loaded System.Drawing.Design in 00:00:00.0000159 [thread 11]
[12:25:09.663747] trce: Processed 'System.Drawing.Design' in 00:00:00.0000874
[12:25:09.664747] info: Added 'System.Drawing.Design'
[12:25:09.978613] info: Shadow cache base directory: C:\Users\robert\AppData\Local\Microsoft\VisualStudio\17.0_be851373\WinFormsDesigner
[12:25:09.987622] info: [WindowsFormsApplication1]: Preparing shadow cache folder
[12:25:09.988625] info: [WindowsFormsApplication1]: NetFrameworkServerLayout - Platform: AnyCPU, Prefer32Bit: True, Normalized PlatformName: x86
[12:25:09.990625] info: [WindowsFormsApplication1]: Copying design tools server common files from: 'c:\program files\microsoft visual studio\2022\preview\common7\ide\commonextensions\microsoft\windows.forms\FxDesignToolsServer\Common'
[12:25:10.062421] info: [WindowsFormsApplication1]: Copying design tool server platform-specific files from: 'c:\program files\microsoft visual studio\2022\preview\common7\ide\commonextensions\microsoft\windows.forms\FxDesignToolsServer\x86'
[12:25:15.827348] info: [WindowsFormsApplication1]: Launching design tools server process...
[12:25:17.074658] info: [WindowsFormsApplication1]: Connected to named pipe: FxDesignToolsServer.13b15d47-5e31-4e8b-82f9-4df184815141
[12:25:17.097222] info: [WindowsFormsApplication1]: Connecting to pipe: FxDesignToolsServer.13b15d47-5e31-4e8b-82f9-4df184815141... 
[12:25:17.098261] info: [WindowsFormsApplication1]: Successfully connected to pipe: FxDesignToolsServer.13b15d47-5e31-4e8b-82f9-4df184815141
[12:25:17.153780] info: [WindowsFormsApplication1]: Creating DesignToolsServer [thread 6]
[12:25:17.158779] info: [WindowsFormsApplication1]: Starting UI thread [thread 6]
[12:25:17.167300] info: [WindowsFormsApplication1]: UI thread started
[12:25:17.194361] info: [WindowsFormsApplication1]: Performing start up tasks [thread 5]
[12:25:17.299228] info: [WindowsFormsApplication1]: Loaded server manifest [thread 13]
[12:25:17.299228] info: [WindowsFormsApplication1]: Loading design-time assemblies [thread 13]
[12:25:17.387328] info: [WindowsFormsApplication1]: Wait for start up tasks to complete... [thread 6]
[12:25:17.462916] info: [WindowsFormsApplication1]: Building MEF composition
[12:25:17.985334] info: [WindowsFormsApplication1]: Start up tasks completed [thread 13]
[12:25:17.986334] info: [WindowsFormsApplication1]: Initialize JsonRpc [thread 13]
[12:25:18.180713] info: [WindowsFormsApplication1]: Start processing enqueued assemblies
[12:25:18.180713] info: [WindowsFormsApplication1]: Listening for JSON RPC messages
[12:25:18.180713] info: [WindowsFormsApplication1]: Design tools server process is running
[12:25:18.180713] info: [WindowsFormsApplication1]: Design tools server process launch completed successfully.
[12:25:18.180713] trce: [WindowsFormsApplication1]: Launching and connecting to the design tools server process took 00:00:02.3548425
[12:25:18.182711] info: [Thread 5] DesignToolsServer launch time = 9346 ms.
[12:25:18.182711] info: [Thread 5] Initializing client...
[12:25:18.192712] info: [Thread 5] DesignToolsClient init time = 10 ms.
[12:25:18.192712] info: [Thread 5] Initializing server...
[12:25:18.209231] trce: [WindowsFormsApplication1]: Loaded mscorlib in 00:00:00.0000441 [thread 7]
[12:25:18.209231] trce: [WindowsFormsApplication1]: Processed 'mscorlib' in 00:00:00.0011256
[12:25:18.214753] info: [WindowsFormsApplication1]: Added 'mscorlib'
[12:25:18.214753] trce: [WindowsFormsApplication1]: Loaded System.Windows.Forms in 00:00:00.0000109 [thread 5]
[12:25:18.216754] trce: [WindowsFormsApplication1]: Processed 'System.Windows.Forms' in 00:00:00.0019562
[12:25:18.231275] info: [WindowsFormsApplication1]: Added 'System.Windows.Forms'
[12:25:18.231275] trce: [WindowsFormsApplication1]: Loaded System.Drawing in 00:00:00.0000087 [thread 5]
[12:25:18.231275] trce: [WindowsFormsApplication1]: Processed 'System.Drawing' in 00:00:00.0001046
[12:25:18.233273] info: [WindowsFormsApplication1]: Added 'System.Drawing'
[12:25:18.233273] trce: [WindowsFormsApplication1]: Loaded System.Drawing in 00:00:00.0000054 [thread 5]
[12:25:18.233273] trce: [WindowsFormsApplication1]: Loaded System in 00:00:00.0000116 [thread 5]
[12:25:18.234275] trce: [WindowsFormsApplication1]: Processed 'System' in 00:00:00.0008778
[12:25:18.247791] info: [WindowsFormsApplication1]: Added 'System'
[12:25:18.247791] trce: [WindowsFormsApplication1]: Loaded System in 00:00:00.0000094 [thread 11]
[12:25:18.247791] trce: [WindowsFormsApplication1]: Loaded System in 00:00:00.0000058 [thread 5]
[12:25:18.247791] trce: [WindowsFormsApplication1]: Loaded System in 00:00:00.0000017 [thread 5]
[12:25:18.247791] trce: [WindowsFormsApplication1]: Loaded System in 00:00:00.0000015 [thread 5]
[12:25:18.332186] info: [Thread 10] DesignToolsServer init time = 139 ms.
[12:25:18.332186] info: [Thread 10] Populating server with style data...
[12:25:18.487946] trce: Sending request: Styles/Populate
[12:25:18.602072] trce: Styles/Populate took 00:00:00.1140387.
[12:25:18.627625] trce: Sending request: Sessions/Create
[12:25:18.646979] trce: Sessions/Create took 00:00:00.0189944.
[12:25:18.659976] trce: Sending request: Options/SetOptions
[12:25:18.686525] trce: Options/SetOptions took 00:00:00.0271682.
[12:25:18.688525] trce: Sending request: Sessions/BeginLoad
[12:25:18.696045] trce: Sessions/BeginLoad took 00:00:00.0073216.

After that nothing happens. When I close the document the following error is displayed. I see several references to CodeDom in there, so I suspect that the designer cannot find or load our codedom provider

[12:25:59.430351] fail: Exception occurred while disposing VSDesignSurface
                        System.InvalidOperationException: The service 'Microsoft.VisualStudio.Shell.Design.Serialization.DesignerDocDataService' must be installed for this feature to work.  Ensure that this service is available.
                           at System.ServiceExtensions.GetRequiredService[TService,TInterface](IServiceProvider provider)
                           at Microsoft.DotNet.DesignTools.Client.CodeDom.VsDesignerInfo.<CreateAsync>d__22.MoveNext()
                        --- End of stack trace from previous location where exception was thrown ---
                           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                           at Microsoft.DotNet.DesignTools.Client.CodeDom.CodeModel.MergedCodeDomProvider.<CreateAsync>d__23.MoveNext()
                        --- End of stack trace from previous location where exception was thrown ---
                           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                           at Microsoft.DotNet.DesignTools.Client.CodeDom.CodeDomSource.<CreateAsync>d__9.MoveNext()
                        --- End of stack trace from previous location where exception was thrown ---
                           at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
                           at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                           at Microsoft.VisualStudio.Threading.JoinableTask.CompleteOnCurrentThread()
                           at Microsoft.VisualStudio.Threading.JoinableTask`1.CompleteOnCurrentThread()
                           at Microsoft.DotNet.DesignTools.Client.Loader.VsDesignerLoader.<get_CodeDomSource>g__Create|36_0()
                           at Microsoft.DotNet.DesignTools.Client.Loader.VsDesignerLoader.get_CodeDomSource()
                           at Microsoft.DotNet.DesignTools.Client.Loader.VsDesignerLoader.get_CodeDomManager()
                           at Microsoft.DotNet.DesignTools.Client.Loader.VsDesignerLoader.OnBeginUnload()
                           at Microsoft.DotNet.DesignTools.Client.Loader.BasicDesignerLoader.Dispose()
                           at Microsoft.DotNet.DesignTools.Client.Loader.VsDesignerLoader.Dispose()
                           at System.ComponentModel.Design.DesignerHost.DisposeHost()
                           at System.ComponentModel.Design.DesignSurface.Dispose(Boolean disposing)
                           at Microsoft.VisualStudio.WinForms.VSDesignSurface.Dispose(Boolean disposing)

                        For information on how to troubleshoot the designer refer to the guide at https://aka.ms/winforms/designer/troubleshooting.
RobertvanderHulst commented 1 year ago

I do not understand why for 'Non Microsoft' languages you do not call the CodeDomProvider like you did before, call the Parse() method and then serialize the generated CodeCompileUnit and pass it to the External designer. And when the form was designed, you can do the reverse thing: send the revised CodeCompileUnit back and call GenerateCodeFromCompileUnit() to generate the code. This should not be too hard to implement, I think.

elachlan commented 1 year ago

Do you think you could put together a PR?

RobertvanderHulst commented 1 year ago

@elachlan I would if I understood how the designer works. But that may take a while. To start with: where do I find the source for the external designer and the client part that is running inside VS?

elachlan commented 1 year ago

It might not be something you can handle if its in the out of process designer. Since that is closed source.

RobertvanderHulst commented 1 year ago

Well, if you want to change something like this, then you will most likely have to change things on both the sender and the receiver side. If one side is closed source, then what can I do? But can you at least tell me where the open source part can be found. Not in this repo, at least I could not find it.

elachlan commented 1 year ago

Sorry to give you the run around. Hopefully we can find a solution.

merriemcgaw commented 1 year ago

We haven't yet implemented anything with custom languages in the out of process designer, in part because we haven't had any requests for it. We can put this on the backlog and prioritize it with our other projects, but I will be transparent and say that the priority wouldn't be terribly high given lack of other requests. If we have enough requests then of course we could add support for the out of process designer.

elachlan commented 1 year ago

I also recieved this error:

Exception occurred while disposing VSDesignSurface
System.InvalidOperationException: The service 'Microsoft.VisualStudio.Shell.Design.Serialization.DesignerDocDataService' must be installed for this feature to work.  Ensure that this service is available.

For this error message, maybe there is an issue in that the code isn't checking to see if there is a connected design surface?

Maybe for this specific issue, an NotSupportedException (https://learn.microsoft.com/en-us/dotnet/api/system.notsupportedexception?view=net-7.0) for languages that are not supported?

merriemcgaw commented 1 year ago

@elachlan - I think you're right. We're only initializing the designer for languages that are known to VS ahead of time. I don't think this is something the WinForms team is prepared to change with our current priorities.

RobertvanderHulst commented 1 year ago

@merriemcgaw Are you serious? You are creating a replacement for a language agnostic Windows Forms editor, that uses a code model to communicate with the development language (C#, VB or any third party language that feeds the editor), and you replace it with a new editor that only understands C# and VB and you are not prepared to change that? Come on! You must be kidding. This is clearly a wrong design decision that needs to be corrected.

merriemcgaw commented 1 year ago

At this point there are no plans to disable the inproc designer, is there a reason that doesn't support your needs? The out of process support for Framework will be a workaround for Framework projects with 32bit references. Until your request, we've not received any customer feedback that we need to support all languages in the out of process designer. It's something that could be put on the backlog for some future date, but it's not on our current roadmap and we would likely need significant business justification to enable it, and it will likely not be for a while as we round out the support for other parts of .NET/.NET Framework in the out of process designer.

elachlan commented 1 year ago

@merriemcgaw Isn't the new designer is Roslyn based? Would that make the change easier because of the abstraction? I have no feelings either way at this stage, but it would be quite cool if it supported additional languages with ease.

RobertvanderHulst commented 1 year ago

The inproc designer works for Framework projects, but our language (X#) also supports .Net 5/6/7/Core and to design forms for these versions of .Net our customers would need to use the external designer. And I am not asking for support for "all languages", I am asking that you keep the "old" method alive and let the project system provide a codedom for the Form and Form.Designer, and then serialize the codedom between the client and the designer. That should work with all languages, including C# and VB. Why invent a new system at all?