Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Начиная с .NET 5, вы больше не сможете получить доступ к объектам Windows Forms из машинного кода.
Описание изменения
В предыдущих версиях .NET некоторые типы Windows Forms были помечены как доступные для COM-взаимодействия и, таким образом, были доступны для родного кода. Начиная с .NET 5, API Windows Forms не видны для COM-взаимодействия и недоступны для родного кода. Среда выполнения .NET больше не поддерживает создание пользовательских библиотек типов по умолчанию. Кроме того, среда выполнения .NET не может зависеть от библиотеки типов для .NET Framework (которая требует поддержания формы классов в .NET Framework).
Причина изменения
- Удаление
ComVisible(true)из перечислений, которые использовались для генерации и поиска библиотеки типов (TLB-файла): поскольку .NET Core не предоставляет TLB-файл для WinForms, нет смысла сохранять этот атрибут. - Удаление
ComVisible(true)из классовAccessibleObject: классы не являются CoCreateable (у них нет конструктора без параметров), и доступ к уже существующему экземпляру COM не требует этого атрибута. - Удаление
ComVisible(true)из классовControlиComponent: это использовалось для размещения элементов управления WinForms через OLE/ActiveX, например, в VB6 или MFC. Однако для этого требуется библиотека типов TLB для WinForms, которая больше не предоставляется, а также активация на основе реестра, которая тоже не будет работать сразу. Как правило, не было обслуживания размещения элементов управления WinForms на основе COM, поэтому поддержка была удалена вместо того, чтобы оставить ее в неподдерживаемом состоянии. - Удаление атрибутов
ClassInterfaceиз элементов управления: если размещение через OLE/ActiveX не поддерживается, эти атрибуты больше не требуются. Они хранятся в других местах, где объекты по-прежнему подвергаются воздействию COM, и атрибут может быть релевантен. - Удаление
ComVisible(true)изEventArgs: они, скорее всего, использовались для хостинга OLE/ActiveX, который больше не поддерживается. Они также не являются совместно создаваемыми, поэтому атрибут не имеет назначения. Кроме того, предоставление существующих экземпляров без предоставления TLB не имеет смысла. - Удаление
ComVisible(true)из делегатов: назначение неизвестно. Однако, поскольку размещение элементов управления WinForms с поддержкой ActiveX больше не поддерживается, вряд ли это будет полезным. - Удаление
ComVisible(true)из какого-то не публичного кода: единственным потенциальным потребителем будет новый конструктор Visual Studio, но без GUID, маловероятно, что он по-прежнему необходим. - Удаление
ComVisible(true)из некоторых произвольных классов дизайнера: устаревший дизайнер Visual Studio, возможно, использовал взаимодействие через COM для работы с этими классами. Тем не менее, старый конструктор не поддерживает .NET Core, поэтому немногим людям нужны они в качествеComVisible. -
IWin32Windowопределяет тот же GUID, который был определен в .NET Framework, который имеет опасные последствия. Если требуется взаимодействие с .NET Framework, используйтеComImport. - Управляемая форма
IDataObjectWinForms была созданаComVisible. Это не обязательно, существует отдельноеComImportобъявление интерфейса дляIDataObjectвзаимодействия COM. Это контрпродуктивно, еслиIDataObjectдолжно бытьComVisible, так как таблица сопоставления страниц (TLB) не предоставляется, и маршаллинг всегда завершается ошибкой. Кроме того, GUID не был указан и отличается от .NET Framework, поэтому маловероятно, что удаление незадокументированного IID повлияет на клиентов отрицательно. - Удаление
ComVisible(false): они размещаются в, казалось бы, произвольных местах и избыточны, если значение по умолчанию — это не показывать классы для взаимодействия с COM.
Представленная версия
.NET 5.0
Рекомендуемое действие
Следующий пример работает на платформах .NET Framework и .NET Core 3.1. В этом примере используется библиотека типов .NET Framework, которая позволяет JavaScript вернуться в подкласс формы с помощью отражения.
[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class Form1 : Form
{
private WebBrowser webBrowser1 = new WebBrowser();
protected override void OnLoad(EventArgs e)
{
webBrowser1.AllowWebBrowserDrop = false;
webBrowser1.IsWebBrowserContextMenuEnabled = false;
webBrowser1.WebBrowserShortcutsEnabled = false;
webBrowser1.ObjectForScripting = this;
webBrowser1.DocumentText =
"<html><body><button " +
"onclick=\"window.external.Test('called from script code')\">" +
"call client code from script code</button>" +
"</body></html>";
}
public void Test(String message)
{
MessageBox.Show(message, "client code");
}
}
Есть два возможных способа заставить пример работать на .NET 5 и более поздних версиях.
Введите объявленный пользователем
ObjectForScriptingобъект, который поддерживаетIDispatch(который применяется по умолчанию, если не изменен явным образом на уровне проекта).public class MyScriptObject { private Form1 _form; public MyScriptObject(Form1 form) { _form = form; } public void Test(string message) { MessageBox.Show(message, "client code"); } } public partial class Form1 : Form { protected override void OnLoad(EventArgs e) { ... // Works correctly. webBrowser1.ObjectForScripting = new MyScriptObject(this); ... } }Объявите интерфейс с методами, которые следует предоставить.
public interface IForm1 { void Test(string message); } [ComDefaultInterface(typeof(IForm1))] public partial class Form1 : Form, IForm1 { protected override void OnLoad(EventArgs e) { ... // Works correctly. webBrowser1.ObjectForScripting = this; ... } }
Затронутые API
Все API Windows Forms.