Closed SteffenSchwaiger closed 2 months ago
As you said, Debug.Fail(...)
crashes the out-of-process designer, and the VS client is unable to communicate with the crashed process... What are your expectations?
I would expect one of the following:
DesignToolsServer
behaves similarly as before (in-process designer), i.e. an "Assertion failed..." dialog is displayed, which can be closed by the user.Debug.Assert(...)
or Debug.Fail(...)
calls are caught inside the DesignToolsServer
and are only logged to the "Windows Forms" output in Visual Studio. The Visual Designer itself works as if these assertions were not present.Thanks for sharing the ideas.
The first won't work, as it'd block the remote process and, thus, block the VS, which is a big no-no. The second is likely achievable with something like NoAssertContext
.
Though, what would you expect to happen on the designer surface?
The first won't work, as it'd block the remote process and, thus, block the VS, which is a big no-no.
I can understand this. Is it not possible to inform Visual Studio via RPC that the designer is in an assertion state and Visual Studio could display the same assertion dialog as in the old designer?
The second is likely achievable with something like NoAssertContext.
Sounds promising to me.
Though, what would you expect to happen on the designer surface?
Since the assertion in our case is only relevant when the application is running, the designer surface could simply ignore it. In this case, the designer surface would at least not get stuck at the "Loading designer..." stage like it currently is.
We work around this problem by only calling Debug.Fail(...)
when the control is not instanciated by the DesignToolsServer
process. Sample pseudocode:
private static bool _designMode => Assembly.GetEntryAssembly()?.GetName()?.Name?.Contains("DesignToolsServer") ?? false;
protected virtual void ResizeControl()
{
if (!_designMode)
Debug.Fail("this method has to be implemented from the derived class");
}
Another more elegant way would be to display the assertion and let the user decide whether to still load the control/dialog/... or close the current designer tab.
Sample:
I think we can probably implement a custom TraceListener in server process which will route the Debug.Fail messages to output window or send them as notification for display in a MessageBox.
@Olina-Zhang can you copy this issue to the designer repo?
@merriemcgaw Filed a DT issue: https://github.com/microsoft/winforms-designer/issues/5926 for this issue
Fix for this bug has been implemented and should be available in an upcoming VS 17.11 preview release. Thanks.
A message box is shown in Visual Studio 17.11.0 Preview 4.0 which displays the assertion. After confirming the dialog with OK, the Designer is loaded. :tada:
Environment
17.10.0 Preview 2.0
.NET version
.NET 8
Did this work in a previous version of Visual Studio and/or previous .NET release?
It worked in .NET Framework / In-Process Designer.
Issue description
When using a common form base class for multiple other form classes, it is not yet possible to mark that class as abstract, or the designer won't load. The team seems to be aware of this and is tracking this feature under the following issue: https://github.com/dotnet/winforms-designer/issues/3142.
We work around this limitation of the WinForms Designer (In-Process & Out-Of-Process) by not marking the base class as abstract and calling Debug.Fail(...) in each of the "abstract" methods to "ensure" that the class is not directly used by developers:
In the old designer, this meant that an assertion was displayed when the design view was opened, but after that the designer could be used as normal.
In the new designer, dialog instantiation fails and the user interface gets stuck on the current screen:
Steps to reproduce
Create two
UserControl
s:Open the designer for the derived user control.
Diagnostics