最終更新日 2024-09-25

.NET4.x から .NET5 以降(.NET6, .NET7, ...) の.dllを呼び出す

秀丸エディタ v8.97 以降かどうかで判断が変化します。

秀丸エディタ v8.97 では.NET5の.dllを、COM経由で普通に読むことができます。
そちらも参照してください。

参照先を見れば、それをhm.NET上で行うことで、.NET Framwork4.xから.NET5のCOMライブラリも普通に読めることがわかります。

秀丸エディタ v8.97 以降 なのであれば、

などを利用して記述すれば、
秀丸マクロ上で、createobject関数 や メソッドを呼び出すことと同じですので、
.NET4.xから.NET5.xの呼び出しや値のやり取りが実現できることがわかるかと思います。

以下は、秀丸からは.NET5以降のCOMを扱えないバージョンとなる、
秀丸エディタ v8.96以下のバージョンを対象とした説明となります。

概要

「.NET4.x」のアセンブリから直接、「.NET5のアセンブリ」を「参照」することは出来ません。
「.NET5」はアセンブリとしては「.NET Core3.1」の後継であり、「.NET Framework 4.x」とは原則、互換性がありません。
(とはいえ、.NET Framework4.xを対象に制作したライブラリは、.NET5からも結構な高確率で参照して利用することが出来ます。)

「.NET4.x」のルーズな互換性と、「.NET5」以降の厳しい非互換性が生み出す問題 .NET4.xでは、ルーズに互換性があり、例えば、.NET4.5から.NET4.8の.dllをロードすることが出来ました。
Visual Studio上で直接参照として加えることはできずとも、よほどのことが無い限り、Assembly.Loadは出来たため、
古いNET4.5のdllから新しいNET4.8のdllを同一のAppDomainへと読み込むことが出来たのです。
hm.NET自体は.NET4.5で制作されていますが、そこから呼び出されるあなたが自作する.dllについては「.NET4.5のdll」でも「.NET4.8のdll」でもほとんどのシーンにおいて問題なく実行できるのは、この相互に高い互換性があればこそです。

しかし、.NET5以降はこれは当てはまりません。

「新しい.NET6」から、古い「.NET5や.NET Core3.1(そして、多くの.NET Framework ライブラリも)」を読み込むことはできても、
その逆「.NET5」から「.NET6」の.dllを読み込んだり、「.NET Core3.1」から「.NET5」を読み込むことは一切できなくなりました。

これにより、C#のオブジェクト指向のあり方を考慮すれば、今後は、基本的にはかなり強く「同一バージョンの.NETを使うことを意識する必要が出た」と言えます。
2021年以降は、.NET5→.NET6→.NET7と毎年のようにバージョンアップしていくわけですが、
「呼び出し元」と「呼び出し先」が互いのクラスやメソッドをロードしているならば、「どちらも.NETのバージョンを上げたくとも上げくい状況」となったと言えます。

2021年現在の段階では、nugetライブラリ上に公開されている「.NET系ライブラリ」は、ほとんどのライブラリが.NET 4.8で使えます。

しかし、長い目でみれば、今後制作される新しいライブラリ、あるいは既存ライブラリの新バージョンは、
.NET5以降のものへと徐々に移ってゆき、.NET4.xはサポート対象から外れてくることが予想されます。

それはちょうど、アクティブな活動をしているライブラリの多くが、最新版では、すでに.NET 3.5を動作対象から外していることからも明らかです。

このような将来像を見据え、「.NET4.x」から「.NET5」のライブラリを呼び出す使い方を知っておくと良いでしょう。

ここで解説する方法は、COM経由で「.NET Core 3.1以降で作ったdll」「.NET5 以降で作ったdll」を「.NET4.x」から呼び出す方法です。
COM経由で制作した場合の、パッキングの仕方(インストーラーを使って簡単にレジストリへの登録や解除も含めてパックしてしまう)方法も解説します。

今回の解説の基礎となる情報は「COM への .NET Core コンポーネントの公開」のものとなります。
そちらも合わせて参照することをオススメします。

ダウンロード

以降の解説内容のソリューションやプロジェクト、そしてC#ソース群となります。
ダウンロードした後、プロパティで「許可する(or ブロック解除)」にチェックを入れて、適用してください。

更新日 2021/02/22
MyTestCoreServer.zip

動作環境

COMサーバー側 (.NET5 側)

まずは「COMサーバー側」のプロジェクトファイルから見ていきましょう。

MyTestComServer.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <EnableComHosting>true</EnableComHosting>
    <EnableRegFreeCom>true</EnableRegFreeCom>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
    <PlatformTarget>x86</PlatformTarget>
    <DebugType>none</DebugType>
    <DebugSymbols>false</DebugSymbols>
  </PropertyGroup>

</Project>
    

COMサーバーをレジストする

.NET Framework では「RegAsm」が利用されていたが、.NET5では再び、ネイティブCOM同様、「Regsvr32.exe」 へと戻っている。
「管理者」権限でプロンプトを開き、対象の「MyTestComServer.comhost.dll」を登録する。

Cmdコンソール もしくはPowerShell の管理者権限
regsvr32 .\MyTestComServer.comhost.dll
    

登録を解除するには、

  regsvr32 /u .\MyTestComServer.comhost.dll
      

通常は実装することはありませんが、もしもこの「レジスト登録」や「レジスト解除」時に、何か特別なことをC#側から実行したいのであれば、以下のようなメソッドを定義すれば、
呼び出されます。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace MyTestCOMServer
{
    [ComVisible(true)]
    [Guid("A7500A08-B63F-49DB-9EC2-1CE2CDBEC319")]
    public class MyTestCOMServer
    {

        public string AddString(string str1, string str2, string[] list)
        {
            return str1 + str2 + list.Length.ToString(); ;
        }

        [ComRegisterFunction]
        private static void RegisterFunction(Type type)
        {
            System.Diagnostics.Trace.WriteLine("★RegisterFunction" + type.ToString());
        }
        [ComUnregisterFunction]
        private static void UnregisterFunction(Type type)
        {
            System.Diagnostics.Trace.WriteLine("★UnRegisterFunction" + type.ToString());
        }
    }
}
  

COMクライアント側 (.NET4.x 側)

「COMクライアント側」のプロジェクトファイルは普通に作ればよく、変わったオプションは必要ありません。

hm.NETを使い、秀丸マクロから呼び出し

最後に一応秀丸マクロから呼び出せることを確認してみましょう。

MyTestComInterface.mac
#DLL = loaddll( hidemarudir + @"\hm.NET.dll");

$_ = dllfuncstrw(#DLL, "CallMethod", currentmacrodirectory + @"\MyTestComClient.dll", "MyTestCOMClient.Program", "abc", "あいうえお");

message($_);
  

ここまで登場した.NET5 COM関連ファイル群の詳細

一番詳細な資料は以下のものだと思われます。

https://github.com/dotnet/runtime/blob/master/docs/design/features/COM-activation.md

レジストやアンレジストをインストーラーで行うには

上述していた「Regsvr32」によるレジスト登録や解除は、個人で利用する分には「バッチファイル」か何かで行えば良いでしょう。
幸いにもdll名には「****.comhost.dll」といった名前や、見慣れない.jsonファイルなどが付随しているため、
少し慣れればそれが「ただの.dllではなく、COM用の.NET 5(or .NET Core)用の.dllだとすぐにわかります。

一方で配布する際にはどのようにすればよいのでしょう。
1つはReadmeやバッチファイルを作り、登録や解除を使用者本人にやってもらう方法です。

もうひとつがインストーラー(アンインストーラー兼ねる)を制作し、
インストール時にレジストリへの登録、アンインストール時にレジストリからの解除を行うというものです。

EnableRegFreeCom

秀丸マクロから呼び出す分には、全く役立ちませんが、
一般的な.NET5系のCOM利用をレジスト登録せずに利用することができる方法に関係しており、
知識としては役立つ部分も多いため、触れておきます。

このMyTestCOMClient.exe をコンパイルし、
「MyTestCOMClient.exe」と「MyTestCOMServer.comhost.dll」、「MyTestCOMServer.X.manifest」、「他のdllや.json」が同じディレクトリにあれば、
Regsvr32をせずとも、MyTestCOMServer.comhost.dllを自動的にCOMサーバーとして認識してくれます。