Hm.NetCOMの頻繁なアップデートへの対応方No.00669
fzok4234 さん 22/09/05 17:24
 
こんばんは、fzok4234 です。


現在の時点では、秀丸エディタのマクロから呼び出す外部 DLL は主に、Hm.NET.dll
参照する
.NET Framework 4.8 依存のアセンブリとして作成しております。しかし、この .NET
 Framework 4.8 の
開発 / 実行環境が近年急速に陳腐化してきたこともあって、これからまもなく当方
の主な
開発 / 実行環境を C# 10 以降と .NET 6 以降に全面移行することを検討しています。

それに合わせて .NET Framework 4.8 専用の Hm.NET.dll から .NET 6 で使える Hm.
NetCOM に
乗り換える必要が出てきたのですが、Hm.NetCOM 自体を常に最新版にアップデートす
る方法で
分からないことがあります。

Hm.NET.dll は
 https://秀丸マクロ.net/?page=nobu_tool_hm_dotnet_update
で、Hm.NetCOM は
 https://秀丸マクロ.net/?page=nobu_tool_hm_dotnet_pinvoke_update
で見るように共にほぼ 1 ヵ月に 1 回のペースで頻繁にアップデートが行われており
ます。

そこで、この頻繁なアップデートへの対応方法ですが、従来の Hm.NET.dll の場合で
は秀丸エディタの
インストールディレクトリの Hm.NET.dll を上書きするだけで済んでいました。とこ
ろが Hm.NetCOM の
方は、実体がコンパイル済みアセンブリではなく T4 テンプレートの HmNetCOM.tt
ファイルの形をとっているため、
アップデートの度に HmNetCOM.tt から HmNetCOM.cs に T4 テンプレート変換して、
所有する全ての
外部 DLL をこの HmNetCOM.cs をインクルードしてコンパイルし直さなければならな
いみたいです。
しかも  HmNetCOM.tt を T4 テンプレート変換した時点で再コンパイルする DLL の
GUID が再決定されて
しまうため、アップデートの度に DLL の GUID がコロコロ変わってしまいます。

このため、Hm.NetCOM に移行後に従来の Hm.NET.dll のときのようなアップデートへ
の迅速な対応を行う
方法が分からず、以降への大きな不安材料となっています。

現状において、作成した DLL を再コンパイルすることなく Hm.NetCOM だけを常に最
新版に維持し続ける
具体的な手順のご教示お願い申し上げます。



[ ]
RE:00669 Hm.NetCOMの頻繁なアップデートNo.00670
こみやんま さん 22/09/07 04:17
 
fzok4234 さん、こんばんわ。
こみやんまです。

■GUID
>しまうため、アップデートの度に DLL の GUID がコロコロ変わってしま

DLLの(COMインターフェイスの)IDがコロコロ変わるというよりは、
ユーザーが直接呼び出さないCOMクラスの1つのGUIDが変化します。
(よってNET6などでマクロから呼び出すcreateobject( ..., "{GUID}"は変化しません。)

しかしながら、気持ち悪いといったこともあるでしょう。
(例え内部的なGUIDだとしても)一度定めたGUIDを変化させたくない場合には、
1つ前の HmNetCom.cs 内の HmMacroCOMVarInterface = "****" の値をコピーしてお
き、
改めて新しいHmNetCom.ttからT4テンプレートで作成した HmNetCom.cs の同じ箇所に
 値を貼り付けておけばよいかと思います。

ここについてはT4テンプレート自体を改良できるかと思います。
(初めての時にGUIDをファイルとして保持し、2回目以降GUIDを変えないようにする)

■hm.NETと異なり、なぜインターナルなライブラリなのか
>現状において、作成した DLL を再コンパイルすることなく Hm.NetCOM だけを常に
>最新版に維持し続ける
>具体的な手順のご教示お願い申し上げます。

その手段は現状ありません。

最新のHmNetCOMに差し替えたいならば、それを利用したdllを再コンパイルするしか
ないかと思います。
nugetから最新を取ってくる⇒(おそらく勝手にT4コンパイルが走る)⇒再コンパイル
というパターンになるかと思っています。

HmNetCOMをこのようにせざるをえないのには理由があります。

.NET Frameworkとは異なり、.NET Core系列は、.NET5以降は、
1年単位で新バージョンが1つずつ出てくる予定となっており
2020/11月に.NET5が来て、.NET 6がリリースされ、もうすぐ.NET 7が来ます
.NET Frameworkとは異なる、.NET Core系列は異バージョンに対する融通がほとんど
効きませんので
 (特に下のバージョンから上のバージョンへの融通が全く効かない)

毎年1つずつ増えていく各.NET系のものを別々のdllとして提供する必要が出てしまい、
これは、現実的な有り様ではないと考えています。

又、.NETのネイティブコンパイラなども近々入ってくるため、
hm.NETのような形にすると、大破綻する可能性が高いのではないかと推察した側面も
あります。

現状では、今の形=「1つのdllに対して、Hm.NETCOM.ttを1つあてがい、しかも、イ
ンターナルなライブラリとして持つ」というのが
一番将来への耐久力が高く、かつ、.NETCore3.1/4/5/6/7 それ以降も結構長期に渡って
動作することが期待できる唯一の有り様だろうと考えています。



[ ]
RE:00670 Hm.NetCOMの頻繁なアップデートNo.00671
こみやんま さん 22/09/07 10:45
 
最新の ver 2.0.7.5 では、一度T4テンプレートを実行すると、
該当のプロジェクトではGUIDが維持されるようにしました。

(GUID生成時に、HmNetCom.guidというファイルにGUIDを書き込み、
 このファイルがプロジェクトのディレクトリに存在している間は、
 そのGUIDを再利用します)

[ ]
RE:00670 Hm.NetCOMの頻繁なアップデートNo.00672
fzok4234 さん 22/09/07 20:46
 
回答ありがとうございます。


とりあえず当方で新たな形態として、HmNetCOM.cs をインクルードしてその中の int
ernal な API を
丸ごとか、或いは当方で使いやすいようにカスタマイズした public な API から呼
び出す「ラッパー DLL」を
1 つだけ作って、秀丸エディタから呼び出す自作 COM アセンブリからはこのラッ
パー DLL を
参照アセンブリとして呼び出す体制に改めようと考えています。

こうすることで、HmNetCOM.tt が最新版にアップデートされたらこのラッパー DLL
だけを再コンパイル
すればよくなりますし、各自作 COM アセンブリごとに同じ HmNetCOM.cs のコードを
重複して埋め込む
必要もなくなって、あるアセンブリと別のアセンブリとで埋め込まれた HmNetCOM.cs
 のバージョンが
異なって思わぬバグが出る心配もなくなると思われます。

全ての各アセンブリとラッパー DLL の一斉再コンパイルは、.NET 6 が .NET 7 に変
わるような
.NET ランタイム自体のメジャーアップデートのときだけに限定して行うことができ
ればと思っています。



[ ]
RE:00672 Hm.NetCOMの頻繁なアップデートNo.00673
こみやんま さん 22/09/08 14:00
 
>とりあえず当方で新たな形態として、HmNetCOM.cs をインクルードしてその中の in
>ternal な API を
>丸ごとか、或いは当方で使いやすいようにカスタマイズした public な API から呼
>び出す「ラッパー DLL」を
>1 つだけ作って、秀丸エディタから呼び出す自作 COM アセンブリからはこのラッ
>パー DLL を
>参照アセンブリとして呼び出す体制に改めようと考えています。

HmNetCOMは、出発地点では外部dll参照型でしたので、
少量の修正で 外部dllとして使えるようになるかと思います。

@まず、HmNetCom.cs を生成して、ソースを確保

「internal」という単語を「public」と全て置き換えてしまう。

A新規ソリューション&プロジェクトを「.NET6」で作成し、
 名前はHmNetCOM6Lib など適当に名称を付ける。
 HmNetCom.cs のソースを貼り付けて、コンパイル。
 HmNetCOM6Lib.dllが出来上がる。

 これで、おそらくは、「Hm.Macro.Exec.Method」以外はいきなり全部使えるんじゃ
ないかな? と思います。
 Hm.Macro.Exec.Method もメソッドの状態の判定を緩めて、
 アセンブリとメソッドを引数に取るようなのにすればいけるかな。


B使う時は、HmNetCom.csと同様インターナルであるかのようにしておいた方が安全

---------------------------------------------------------
using System;
using System.Runtime.InteropServices;


namespace ClassLibrary14
{
    // 自身が使う「Hm」は、HmNetCOM.Hmではなく、このアセンブリ自身のHmである
かのようにするため、継承してしまう。
    public class Hm : HmNetCOM.Hm
    {

    }

    [ComVisible(true)]
    [Guid("310AE8DC-86AA-4871-8A65-780107983929")]
    public class Class1
    {
        public int abcd()
        {
            Hm.Edit.TotalText = "あいうえお";
            return 1000;
        }
    }
}

---------------------------------------------------------

[ ]
RE:00673 Hm.NetCOMの頻繁なアップデートNo.00674
こみやんま さん 22/09/08 14:21
 
あ、いや継承しちゃうと、HmNetCOM6Lib.dllのメソッドや引数が変化すると、不正な
状態になるので、
継承はしちゃだめですかね。う〜む。

[ ]
RE:00673 Hm.NetCOMの頻繁なアップデートNo.00675
fzok4234 さん 22/09/08 17:12
 
> @まず、HmNetCom.cs を生成して、ソースを確保
> 「internal」という単語を「public」と全て置き換えてしまう。
> A新規ソリューション&プロジェクトを「.NET6」で作成し、
>  名前はHmNetCOM6Lib など適当に名称を付ける。
>  HmNetCom.cs のソースを貼り付けて、コンパイル。
>  HmNetCOM6Lib.dllが出来上がる。

最初に当方で思いついた方法がまさにそれです。試験的に HmNetCOM.tt を T4 テン
プレート変換して
生成された HmNetCOM.cs を眺めていて、internal 扱いの Hm クラスを public で公
開すれば
そのまま参照アセンブリとして使えそうな感じがしました。

ただ、実際に使用する段階で、例えば
 https://help.maruo.co.jp/hidemac/html/240_PaneDll.html
に載っているアウトプット枠のコマンド値を素の System.Int32 値ではなく
public enum OutputPaneCommand : Int32 {
    ClosePane       = 1001  ,
    Suspend         = 1002  ,
    Search          = 1005  ,
    NextResult      = 1006  ,
    .....
}
というようにちゃんと名前を付けた enum 値として定義する場合に、引数のコマンド
値を
System.Int32 として受ける Hm.OutputPane.SendMessage() を一段ラップした自作メ
ソッドを
用意する必要があるときなど、最終的に自作ラッパーを介して HmNetCOM.cs の各 AP
I を
操作することとなる見込みです。

よって、このラッパー DLL には HmNetCOM.cs を GUID 以外は手を付けずに埋め込ん
で、
その中の各 API を使いやすいようにラップした public なクラスを実装する形とな
ります。



[ ]