VB6でも新技術に対応！C# DLL連携でレガシーの壁を突破する

## ごあいさつ
こんにちは、「エイジ＠フジワーランド」です
過去にVB6で大規模なセミオーダーパッケージを作成してしまったため、いまだにVB6での機能追加や保守をやってます
しかしAWSのS3アクセスやoo4o廃止でODP.netでの接続を余儀なくされたりとVB6単体では対処できないことも多くなってきました
.netに移行すれば？の話はおいといて、必要部分のみをC#でDLL作成してなんとかしのいでます
同じような境遇の方の参考になればと思い記事を公開いたしました

## この記事でわかること
VB6からODP.net経由でORACLEアクセスするDLLを最終的に作成しますが
今回はVBAとC#で作ったDLLの「疎通」ができるところまでの手順を解説します

## 手順
### 1.準備編
#### 1-1. VisualStudio2022 を 管理者として実行　で起動する
管理者として実行しないとリビルドでDLLが上書きできない時があるので
トラブル防止のつもりで管理者として実行にしてます
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/2544f9d7-0a19-ee05-1d71-c28a89ee4088.png)


#### 1-2. 新しいプロジェクトの作成 を選択
起動後は「新しいプロジェクトの作成」を選択してください
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/b21e37f8-1ba7-d1b8-8f99-c3b88a9bd51c.png)



#### 1-3.クラスライブラリ(.NET Framework) C# を選択
.NET Frameworkを選択しているのは ODP.netからの使用を見越してです
言語はVB.netでももちろんOKですが、将来性？を見込んでC#を選択してます
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/ede55143-d001-0962-9401-4eeb119dc806.png)


#### 1-4. プロジェクト名と、フレームワークのバージョンを指定
プロジェクト名は私がやってる会社名をベースにしてますので自由につけてください
場所もどこでもいいです
フレームワークはみなさんがどれを選択すればベストかはわからないのでとりあえずここでは最終4.8を選択します
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/c5348662-7450-6ac2-3fc8-bd77e2253787.png)


#### 1-5. 準備完了
コードが入力できる状態になったら準備完了です
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/e49235f2-afe8-bbd3-e99c-10c89874dc0d.png)


### 2.テストDLLコーディング
#### 2-1. ファイル名変更
次回記事以降でODP.netに接続するためのDLLにするので、ここでファイル名を変更しておきます
もちろん好きな名前をつけて頂いてもいいしデフォままでも大丈夫です
![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/41b87c9f-e092-7765-abae-4843ef826be5.png)


#### 2-2. DBAccess.cs を入力
名前空間も私がやってる会社名をベースしてますので自由に変更してください
ここで重要なのは 
```csharp
[ProgId("RapidAppsODP.DBAccess")] // VB6から参照するクラス名
```
です
この設定でVB6等から
```vb
    Set RapidAppsODP = CreateObject("RapidAppsODP.DBAccess")
```
こうやって参照が可能になります
GUIDは2-3.を参照してください

```csharp:DBAccess.cs
using System;
using System.Runtime.InteropServices;

namespace RapidAppsODP
{
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    [Guid("773f1c60-c88c-42e1-a42c-654c4b24b62b")] 
    public interface IDBAccess
    {
        string GetVersion();
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)] 
    [Guid("3ac32b63-a01e-43a1-8288-32bff805591e")] 
    [ProgId("RapidAppsODP.DBAccess")] // VB6から参照するクラス名
    
    public class DBAccess : IDBAccess
    {
        public string GetVersion()
        {
            return "RapidAppsODP Ver1.0";
        }
    }

}
```

#### 2-3. GUID の変更
2-4.のコードで 2箇所Guidを定義していますが、以下サイト等でGUIDを生成して書き換えてください
https://www.guidgenerator.com/

![image7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/f4793373-14be-80df-6163-21013482abfa.png)


### 3.コンパイル
#### 3-1. プロジェクトのプロパティ設定1
アセンブリをCOM参照可能にするにチェックを入れる
![image9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/12527b22-2e4d-ced2-13b0-54c84db456f3.png)


#### 3-2. プロジェクトのプロパティ設定2
対象プラットフォーム: AnyCPU
COM相互運用機能の登録 にチェック
※ VB6が32ビットだからといって、対象プラットフォームをx86にしてしまってはダメですよ
![image10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/86edeea4-89c9-9286-27a1-4c583e74f6df.png)


#### 3-3. 保存( 忘れがち )
忘れがちなので

#### 3-4.ビルド
以下にDLLが作成されます
{1-4.で指定したプロジェクトの場所}\RapidAppsODP\bin\Debug\RapidAppsODP.dll
![image8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/f5b86eb7-b2de-5b8d-9c02-5bb269db48d3.png)


### 4.テスト
#### 4-1.レジストリ登録
コマンドプロンプトを管理者権限で開いて以下を実行してください
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /tlb ビルドしたDLL名.dll
```
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /tlb D:\git\fsp\04_DLL\02ODP\RapidAppsODP\bin\Debug\RapidAppsODP.dll
```
ちなみにファイル移動させて別の場所でレジストリ登録も可能です
移動はDLLファイルのみでOKで、他に必要なファイルはありません

#### 4-2.  VisualBasicEditor を 起動
開発メニューがないときは Excelオプションのリボンのユーザー設定を確認してみてください
![image12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/474a459d-3b26-2351-c2fa-d63aaa7021ff.png)


#### 4-3.プロジェクトエクスプローラーの ThisWorkBook を開く
![image13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/bf1f1d0e-d0fa-40e5-2e50-b0dcdbaf994e.png)


#### 4-4. テストコードを作成
![image14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/36f1f222-b037-86e3-4f80-e53a4e0f246f.png)

```vb:ThisWorkBook
Option Explicit
Public Sub pbsDLLTest()
    Dim RapidAppsODP As Object
    Set RapidAppsODP = CreateObject("RapidAppsODP.DBAccess")
    Call MsgBox(RapidAppsODP.GetVersion)
End Sub
```

#### 4-5. テスト実行
これが出たら成功です
![image11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1622018/775c0a76-839f-3418-46a8-a834ebd1f655.png)


エラーで 「ActiveXオブジェクトが作成できません」が出る場合がありますが、
レジストリエディタでオブジェクト名検索してなければレジストリ登録失敗、あれば呼び出しの名前が違うことが大抵の原因です
私の場合は 「3-2. プロジェクトのプロパティ設定2」で
VB6が32ビットなので対象プラットフォームをx86にしてエラーとなりハマりました
→ 対象プラットフォームは AnyCPU にして解決しましたが要注意です（自戒です）

## 終わりに
詰まらずに最後までいけましたでしょうか？
これでVB6でもDLLを経由して新しい技術への入口につながってしまいました
私の知見が少しでも皆さんのお役に立てれば幸いです