次の方法で共有


ネイティブ コードが Windows フォーム オブジェクトにアクセスできない

.NET 5 以降では、ネイティブ コードから Windows フォーム オブジェクトにアクセスできなくなります。

変更の説明

以前の .NET バージョンでは、一部の Windows フォームの種類は COM 相互運用機能から見えるように装飾されていたため、ネイティブ コードからアクセスできます。 .NET 5 以降では、WINDOWS フォーム API は COM 相互運用に対して表示されないか、ネイティブ コードからアクセスできません。 .NET ランタイムでは、すぐに使用するカスタム タイプ ライブラリの作成がサポートされなくなりました。 さらに、.NET ランタイムは.NET Framework のタイプ ライブラリに依存できません (.NET Framework の場合と同様に、クラスの形状を維持する必要があります)。

変更の理由

  • タイプ ライブラリ (TLB ファイル) の生成と参照に使用された列挙体からの ComVisible(true) の削除: .NET Core によって提供される WinForms TLB がないため、この属性を保持する値はありません。
  • ComVisible(true) クラスからのAccessibleObjectの削除: クラスは CoCreateable ではなく (パラメーターなしのコンストラクターがありません)、既に存在するインスタンスを COM に公開する必要はありません。
  • ComVisible(true)クラスとControl クラスからのComponentの削除: これは、OLE/ActiveX (VB6 や MFC など) を介した WinForms コントロールのホストを可能にするために使用されました。 ただし、これには、提供されなくなった WinForms 用の TLB と、レジストリ ベースのアクティブ化が必要です。これは、すぐには機能しません。 一般に、WinForms コントロールの COM ベースのホスティングのメンテナンスは行われなかったため、サポートされていない状態のままにするのではなく、サポートが削除されました。
  • コントロールからの ClassInterface 属性の削除: OLE/ActiveX によるホストがサポートされていない場合、これらの属性は不要になります。 これらは、オブジェクトがまだ COM に公開されている他の場所に保持され、属性が関連している可能性があります。
  • ComVisible(true)からのEventArgsの削除: OLE/ActiveX ホスティングで使用された可能性が最も高く、サポートされなくなりました。 これらは CoCreateable でもないので、属性には目的がありません。 また、TLB を提供せずに既存のインスタンスを公開しても意味がありません。
  • デリゲートからの ComVisible(true) の削除: 目的は不明ですが、WinForms コントロールの ActiveX ホスティングはサポートされなくなったため、有用性を持つ可能性はほとんどありません。
  • 一部の非パブリック コードからの ComVisible(true) の削除: 潜在的なコンシューマーは新しい Visual Studio デザイナーだけですが、GUID を指定しないと、まだ必要になることはほとんどありません。
  • 一部の任意のパブリック デザイナー クラスからの ComVisible(true) の削除: 古い Visual Studio デザイナーでは、COM 相互運用機能を使用してこれらのクラスと通信していた可能性があります。 ただし、古いデザイナーは .NET Core をサポートしていないため、 ComVisibleとして必要な人はほとんどいません。
  • IWin32Window では、.NET Framework で定義されたものと同じ GUID が定義されており、危険な結果が生じることがあります。 .NET Framework との相互運用が必要な場合は、 ComImportを使用します。
  • WinForms マネージド IDataObjectComVisible になりました。 これは必須ではありません。ComImport COM 相互運用のための個別のIDataObject インターフェイス宣言があります。 TLB が提供されておらず、マーシャリングが常に失敗するため、マネージド IDataObjectComVisibleすることは逆効果です。 また、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 以降のバージョンで動作させるには、次の 2 つの方法があります。

  • 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

すべての Windows フォーム API。