NuGetでAutoCAD .NET API用クラスライブラリを作成する

# はじめに

- AutoCAD .NET APIの開発で新規プロジェクト作成する際の簡単な方法は
  - ObjectARXのインストールとAutoCAD .NET API Wizardsをインストール
  - 新規プロジェクトから選ぶ

  ですが

- 現状ではNuGetから必要なファイルを入手できるようになっています
- 以下はその方法を記したものです

# 前提

- Visual Studioがインストールされている
- AutoCADがインストールされている
- NuGetが問題なく利用できる
- AutoCADバージョンと.NET Frameworkの関係は以下参照のこと

|AutoCADバージョン|.NET Frameworkバージョン|
|---|---|
|2017|4.6|
|2018|4.6|
|2019|4.7|
|2020|4.7|
|2021|4.8|
|2022|4.8|
|2023|4.8|
|2024|4.8|

- AutoCADのサポートされるバージョンは現行版から3世代前まで。（現状であれば2021まで）

# 作成手順

## プロジェクト作成手順

1. Visual Studioを起動し、[ファイル（F）]-[新規作成（N）]-[プロジェクト（P）]を選択します。
   ![新規プロジェクト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/f21a8929-787b-3ef2-92d7-7f7e20b63c57.png)

2. 「新しいプロジェクトの作成」画面が表示されたら、クラスライブラリ（.NET Framework）を選択します。
   ![新しいプロジェクトの作成画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/1b1165f3-329f-4018-618c-09d71e75c9be.png)

3. 「新しいプロジェクトを構成します」画面でプロジェクト名、保存先を設定します。
   ![新しいプロジェクトを構成します](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/14614e14-6fbf-8a19-9dcb-347d6467f94f.png)

## NuGet

4. [ツール（T）]-[NuGetパッケージマネージャー（N）]-[ソリューションのNuGetパッケージの管理（N）...]を選択しNuGetを起動します
   ![NuGet起動](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/67bad104-c53e-9627-170c-6ae9a1471a4b.png)

5. [参照]のページで「AutoCAD」を検索し、AutoCAD.NETを選択
   ![AutoCAD.NET](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/c22b3893-a64f-fa71-9ccd-da864c4e85c5.png)

6. 画面右のプロジェクト名をチェックし、[インストール]ボタンを押します
   ![プロジェクトにインストール](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/b46abf0c-e26d-3a16-1be0-01950317f9fe.png)

7. [変更のプレビュー]画面を確認し、[OK]ボタンを押します
   ![変更のプレビュー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/b175bdbf-6ae4-c754-d61e-8746c2a2b0df.png)
   画像のバージョンは2019時点ぐらい

8. [ライセンスへの同意]画面を確認し、[同意する]ボタンを押します
   ![ライセンスへの同意](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/c6c84652-54db-94e3-8657-02b3ca43099b.png)

9. [ソリューションエクスプローラー]の[参照]に「Ac」で始まる参照が追加されます
    ![参照](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/1f2e9dbe-103b-7308-f1f8-a79210de6f95.png)

## コードの追加

### ロード時・開放時用のクラス

- 「MyPlugin.cs」クラスファイルを作成し、以下のコードを入力します。

```cs
using Autodesk.AutoCAD.Runtime;

[assembly: ExtensionApplication(typeof(nugetTest.MyPlugin))]
namespace nugetTest
{
    /// <summary>
    /// ロード・開放時の動作
    /// </summary>
    public class MyPlugin : IExtensionApplication
    {
        /// <summary>
        /// ロード時動作
        /// </summary>
        public void Initialize()
        {
        }
        /// <summary>
        /// クローズ時動作
        /// </summary>
        public void Terminate()
        {
        }
    }
}
```

- 先頭の属性は、AutoCADにこれがプラグインだと認識させるおまじないです
- ```{ネームスペース}.{クラス名}```を認識させています
- MyPluginクラスが利用するインタフェイス、[IExtensionApplication]はプラグインのロード時・開放時の挙動を制御するためのインタフェイスです
  - Initializeがロード時
  - Terminateが開放時

  のコードを記述します

### コマンド用クラス

- 「myCommands.cs」クラスファイルを作成します
- これだけだと、ローカライズ（多国語対応）時に認識されないので、リソースファイルも追加します
    - ~~**2024/1/29追記：AutoCAD2024ではローカライズにリソースファイルが必要なくなった？ようです。下記、1～3までは古いバージョンでは必要かと思うので下記記述は残します。2024では読み飛ばしてください。**~~
    - 2024/1/29追記2：嘘でした、リソースファイルの追記はローカライズに必要です。

- リソースファイルを追加しない場合、コンパイルは可能ですが、AutoCADでNETLOADした際にエラーが発生し、ロードされません。

10. [プロジェクト]を右クリック、[追加（D）]-[新しい項目（W）]を実行

    ![新しい項目の追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/901df30c-70c9-1a2c-40f3-43a98fa29789.png)


11. ファイル名を「myCommands.resx」にして追加項目は「リソースファイル」を選択
    - ファイル名に注意してください
    - 下記画像では「My・・・」になっていますが、「myCommands.resx」です

    ![リソースファイルの追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/6dfd46e2-4260-583c-9c35-e9d12717290a.png)


12. ファイルが次のように認識されているはずです

    ![リソースの追加状況](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/cf373c17-7dfa-6495-2c45-2932f5d846f1.png)


- コードを追加します。
- コードのクラス名は「MyCommands」でファイル名をつけるときとは変更しています。
- これはリソースファイルのコードと区別のためです。

```cs
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

// これはコマンドですよ、という宣言
[assembly: CommandClass(typeof(nugetTest.MyCommands))]
namespace nugetTest
{
    /// <summary>
    /// コマンド用クラス
    /// </summary>
    public class MyCommands
    {
        /// <summary>
        /// コマンドラインから実行するコマンドの定義
        /// </summary>
        [CommandMethod("MyGroup", "MyCommand", "MyCommandLocal", CommandFlags.Modal)]
        public void MyCommand()
        {
        }

        /// <summary>
        /// 先に図形をピックしてある前提で動作するコマンドの定義
        /// </summary>
        [CommandMethod("MyGroup", "MyPickFirst", "MyPickFirstLocal", CommandFlags.Modal | CommandFlags.UsePickSet)]
        public void MyPickFirst()
        {
            PromptSelectionResult result = Application.DocumentManager.MdiActiveDocument.Editor.GetSelection();
            if (result.Status == PromptStatus.OK)
            {
                // ----->>> 図形が選択されていた場合の動作
            }
            else
            {
                // ----->>> 図形が選択されていない場合の動作
            }
        }

        /// <summary>
        /// セッションで有効なコマンド動作
        /// </summary>
        [CommandMethod("MyGroup", "MySessionCmd", "MySessionCmdLocal", CommandFlags.Modal | CommandFlags.Session)]
        public void MySessionCmd()
        {
        }

        /// <summary>
        /// Lisp関数を自作する際のコード
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        [LispFunction("MyLispFunction", "MyLispFunctionLocal")]
        public int MyLispFunction(ResultBuffer args)
        {
            return 1;
        }
    }
}
```

- リソースにも追記します

![リソースの追記](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426989/7e05d22f-5aed-4ccf-c5e2-874a3f1bcf6d.png)


| 名前                | 値             | コメント |
| ------------------- | -------------- | -------- |
| MyCommandLocal      | MyCommand      |          |
| MyLispFunctionLocal | MyLispFunction |          |
| MyPickFirstLocal    | MyPickFirst    |          |
| MySessionCmdLocal   | MySessionCmd   |          |

#　終わりに

- ローカライズを含まない場合は、リソースを作成せずクラスファイルだけで進められます

    その場合は、以下のようにコードを記載してください

    ```cs
    [CommandMethod("MyGroup", "MyCommand", CommandFlags.Modal)]
    ```

- 自分で実施の際、このローカライズにかなりの時間迷ったので、ウイザードで作成した場合と自分で1からクラスライブラリを用意した場合での異なる部分を強調したく、ローカライズをあえて取り上げました
- 開発者の皆様のお役に立てれば幸いです