Bagikan melalui


Kode asli tidak dapat mengakses objek Formulir Windows

Mulai dari .NET 5, Anda tidak dapat lagi mengakses objek Formulir Windows dari kode asli.

Deskripsi perubahan

Dalam versi .NET sebelumnya, beberapa jenis Formulir Windows didekorasi sebagai terlihat oleh interop COM, dan dengan demikian dapat diakses oleh kode asli. Mulai dari .NET 5, tidak ada FORMULIR WINDOWS API yang terlihat oleh interop COM atau dapat diakses oleh kode asli. Runtime .NET tidak lagi mendukung pembuatan pustaka jenis kustom di luar kotak. Selain itu, runtime .NET tidak dapat bergantung pada pustaka jenis untuk .NET Framework (yang akan memerlukan pemeliharaan bentuk kelas seperti yang ada di .NET Framework).

Alasan untuk berubah

  • ComVisible(true) Penghapusan dari enumerasi yang digunakan untuk pembuatan dan pencarian pustaka jenis (file TLB): Karena tidak ada WinForms TLB yang disediakan oleh .NET Core, tidak ada nilai dalam menyimpan atribut ini.
  • ComVisible(true) Penghapusan dari AccessibleObject kelas: Kelas tidak Dapat Dibuat Bersama (tidak memiliki konstruktor tanpa parameter), dan mengekspos instans yang sudah ada ke COM tidak memerlukan atribut tersebut.
  • ComVisible(true) Penghapusan dari Control kelas dan Component : Ini digunakan untuk memungkinkan hosting kontrol WinForms melalui OLE/ActiveX, misalnya di VB6 atau MFC. Namun, ini membutuhkan TLB untuk WinForms, yang tidak lagi disediakan, serta aktivasi berbasis registri, yang juga tidak akan berfungsi di luar kotak. Umumnya, tidak ada pemeliharaan hosting berbasis COM kontrol WinForms, sehingga dukungan dihapus alih-alih membiarkannya dalam keadaan tidak didukung.
  • ClassInterface Penghapusan atribut dari kontrol: Jika hosting melalui OLE/ActiveX tidak didukung, atribut ini tidak diperlukan lagi. Mereka disimpan di tempat lain di mana objek masih terekspos ke COM dan atribut mungkin relevan.
  • ComVisible(true) Penghapusan dari EventArgs: Kemungkinan besar digunakan dengan hosting OLE/ActiveX, yang tidak lagi didukung. Mereka juga tidak Dapat Dibuat Bersama, sehingga atribut tidak memiliki tujuan. Selain itu, mengekspos instans yang ada tanpa menyediakan TLB tidak masuk akal.
  • ComVisible(true) Penghapusan dari delegasi: Tujuan tidak diketahui, tetapi karena hosting ActiveX Kontrol WinForms tidak lagi didukung, tidak mungkin memiliki kegunaan apa pun.
  • ComVisible(true) Penghapusan dari beberapa kode non-publik: Satu-satunya konsumen potensial adalah desainer Visual Studio baru, tetapi tanpa GUID yang ditentukan, tidak mungkin masih diperlukan.
  • ComVisible(true) Penghapusan dari beberapa kelas desainer publik arbitrer: Desainer Visual Studio lama mungkin telah menggunakan interop COM untuk berbicara dengan kelas-kelas ini. Namun, desainer lama tidak mendukung .NET Core, sehingga hanya sedikit orang yang membutuhkannya sebagai ComVisible.
  • IWin32Window mendefinisikan GUID yang sama yang didefinisikan dalam .NET Framework, yang memiliki konsekuensi berbahaya. Jika Anda memerlukan interop dengan .NET Framework, gunakan ComImport.
  • WinForms yang dikelola IDataObject dibuat ComVisible. Ini tidak diperlukan, ada deklarasi antarmuka terpisah ComImport untuk IDataObject interop COM. Kontraproduktif untuk memiliki dikelola IDataObject menjadi ComVisible, karena tidak ada TLB yang disediakan dan marshalling akan selalu gagal. Selain itu, GUID tidak ditentukan dan berbeda dari .NET Framework, sehingga tidak mungkin menghapus IID yang tidak terdokumentasi akan memengaruhi pelanggan secara negatif.
  • ComVisible(false)Penghapusan : Mereka ditempatkan di tempat yang tampaknya segan-segan dan berlebihan ketika defaultnya adalah untuk tidak mengekspos kelas ke interop COM.

Versi yang diperkenalkan

.NET 5.0

Contoh berikut berfungsi pada .NET Framework dan .NET Core 3.1. Contoh ini bergantung pada pustaka jenis .NET Framework, yang memungkinkan JavaScript untuk memanggil kembali ke subkelas formulir melalui pantulan.

[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");
    }
}

Ada dua cara yang mungkin untuk membuat contoh berfungsi pada .NET 5 dan versi yang lebih baru:

  • Perkenalkan objek yang dideklarasikan ObjectForScripting pengguna yang mendukung IDispatch (yang diterapkan secara default, kecuali diubah secara eksplisit di tingkat proyek).

    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);
    
            ...
        }
    }
    
  • Deklarasikan antarmuka dengan metode untuk diekspos.

    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 yang Terpengaruh

Semua API Formulir Windows.