質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

1065閲覧

C#で作成したDLLをVB6より呼び出せるようにしたい

退会済みユーザー

退会済みユーザー

総合スコア0

VB

VB(ビジュアルベーシック)はマイクロソフトによってつくられたオブジェクト指向プログラミング言語のひとつで、同社のQuickBASICが拡張されたものです。VB6の進化版といわれています。

DLL

DLL(Dynamic Link Library)とは、他のモジュールからも使用する事が出来る、関数とデータが格納されているモジュールのことです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2023/09/21 02:01

編集2023/09/29 06:43

2023年9月29日 修正

業務内容漏洩リスクを指摘されたため、質問の内容を伏せさせていただきます。
協力していただいた方々、大変申し訳ありません。

動作はできたもののまだテストはしていない状況です。
テストが通り世に出回りましたら、ブログなど何らかの方法で公開させていただきます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

今だと、NativeAOT+UnmanagedCallersOnlyAttributeで作成する方法もあるようです。

C#で書いたライブラリをPHPやGoから呼び出す

投稿2023/09/28 01:43

nururi

総合スコア98

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOZ6.0

2023/09/28 03:30

oh! これは知りませんでした。 tototomo さんは、おそらく VS2019 Community を使ってらっしゃいますが 怪しげなものを使うより、VS2022 と .NET7 を入れておきかえたほうがいいかも。 ソースはほぼそのまま使えるので。
退会済みユーザー

退会済みユーザー

2023/09/28 04:41

VS2019 Communityを使っています。 送信システムを利用している顧客が、自由にWindowsのインストールできない厳格な管理下ですので、Win10に標準で入っているであろう.NET4をターゲットにしました。 この方法も1手段として考えてみます。
guest

0

DLLExport を使ったクラスのサンプルです。
SendMailInternal にメール送信処理を書いてください。
SmtpClient ではなく、MailKit を使いましょう。

csharp

1using System; 2using System.Text; 3using System.Runtime.InteropServices; 4 5namespace smtpmail 6{ 7 public class SendMailCaller 8 { 9 // VB の宣言 10 //Private Declare Function SendMail Lib "smtpmail" _ 11 // (sServer As String, sTo As String, sFrom As String, _ 12 // sSubject As String, sBody As String, sFile As String) As String 13 14 [DllExport(CallingConvention.StdCall)] 15 public static IntPtr SendMail( 16 ref IntPtr iServer, ref IntPtr iTo, ref IntPtr iFrom, 17 ref IntPtr iSubject, ref IntPtr iBody, ref IntPtr iFile) { 18 19 string sServer = GetByRefString(iServer); 20 string sTo = GetByRefString(iTo); 21 string sFrom = GetByRefString(iFrom); 22 string sSubject = GetByRefString(iSubject); 23 string sBody = GetByRefString(iBody); 24 string sFile = GetByRefString(iFile); 25 26 string result = SendMailInternal( 27 sServer, sTo, sFrom, 28 sSubject, sBody, sFile); 29 30 return ResultString(result); 31 } 32 33 private static string GetByRefString(IntPtr ptr) { 34 if (ptr == IntPtr.Zero) { 35 return string.Empty; 36 } 37 return Marshal.PtrToStringAnsi(ptr); 38 } 39 40 private static IntPtr ResultString(string value) { 41 if (string.IsNullOrEmpty(value)) { 42 return IntPtr.Zero; 43 } 44 var enc = Encoding.GetEncoding("SHIFT_JIS"); 45 var bytes = enc.GetBytes(value); 46 return SysAllocStringByteLen(bytes, bytes.Length); 47 } 48 49 [DllImport("oleaut32.dll", CharSet = CharSet.Ansi)] 50 private static extern IntPtr SysAllocStringByteLen( 51 byte[] bytes, int len); 52 53 private static string SendMailInternal( 54 string sServer, string sTo, string sFrom, 55 string sSubject, string sBody, string sFile) { 56 57 Console.WriteLine($"sServer={sServer.Length}{sServer}"); 58 Console.WriteLine($"sTo={sTo.Length}{sTo}"); 59 Console.WriteLine($"sFrom={sFrom.Length}{sFrom}"); 60 Console.WriteLine($"sSubject={sSubject.Length}{sSubject}"); 61 Console.WriteLine($"sBody={sBody.Length}{sBody}"); 62 Console.WriteLine($"sFile={sFile.Length}{sFile}"); 63 64 // ここにメール送信処理を書いてください。 65 66 return "SendMail Success!"; 67 } 68 69 } 70} 71

投稿2023/09/22 04:02

KOZ6.0

総合スコア2628

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2023/09/22 07:11

VB6からの情報を渡せるようになりました。ありがとうございます。 しかし、まだ問題がありまして、 実行すると エラーが発生しました: ファイルまたはアセンブリ 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'、またはその依存関係の 1 つが読み込めませんでした。見つかったアセンブリのマニフェスト定義はアセンブリ参照に一致しません。 (HRESULT からの例外:0x80131040) となります。 MailKitなど別DLLもVB6の実行フォルダに置いてはいるのですが、参照ができないようです。 ここで苦戦しています。
退会済みユーザー

退会済みユーザー

2023/09/22 09:14

VB6 とC#のやりとりは出来ています。内部のメール処理を外した単純な形にしたところ、引数も渡すことができ、戻り値も受け取ることができました。 ただ、MailKitの実行箇所でエラーとなってしまいます。 この質問は一旦完了としましたので、別質問であげさせていただきました。 よろしければ一度ご確認いただければと思います。ここまで進めたことに本当に感謝です。 https://teratail.com/questions/7ttit0ui1ufccf
guest

0

まず、C# .NETで新しいDLLプロジェクトを作成します。そのプロジェクト内でメール送信などの必要な機能を実装します。 VB6からC# .NET DLLを呼び出すには、DLLをCOM相互運用可能にする必要があります。Pay by Plate Ma .NETプロジェクトのプロパティで、[プロパティ] > [ビルド] タブに移動し、[COM相互運用を有効にする]オプションをチェックします。

[ComVisible(true)]
public interface IMyMailSender
{
void SendMail(string to, string subject, string body);
}

投稿2023/09/21 05:42

sarensfa2

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

C# で VB6 から呼び出せる dll を作るなら、 COM を作ってください。

まずは本家。

「COM クラスの例」
https://learn.microsoft.com/ja-jp/dotnet/csharp/advanced-topics/interop/example-com-class

あとは、VBA 用に作った先人がいらっしゃいますので、「VBA C# COM」でネット検索するとでてくるでしょう。

どこかの偉い人がレガシー dll として作る方法を提供していますが、裏技なのでお勧めしません。

おすすめのページです。

「C# で COM オブジェクトを作ってみる」
https://qiita.com/tomochan154/items/1ce33f2aef167c0fed9d

AnyCPU でビルドすると、32bit/64bit 双方で動く dll になるようです。
VB6 なので、32bit だけで良いのですが、ここで注意事項。

Visual Studio 2019 までは 32bit だったので、ビルドすると 32bit の COM として登録されますが、2020 は 64bit なので 64bit の COM として登録されるので手動で登録する必要があります。


追記:VB6側は変更できないというのを見落としていたので

前述したとおり、C# は基本的にレガシー DLL を作成できません。
なので、C# の DLL を呼び出したいのであれば、C++/CLR でラッパー DLL を作ることになるでしょう。

VB6 → C++/CLR → C# という感じで呼び出すわけですね。

VB の宣言が

vb

1Private Declare Function SendMail Lib "smtpmail" _ 2 (sServer As String, sTo As String, sFrom As String, _ 3 sSubject As String, sBody As String, sFile As String) As String

のようになっているので C++/CLR 側は

c++

1extern "C" { 2 __declspec(dllexport) BSTR WINAPI SendMail( 3 BSTR* sServer, BSTR* sTo, BSTR* sFrom, 4 BSTR* sSubject, BSTR* sBody, BSTR* sFile) { 5 char buf[] = "this is a pen"; 6 return SysAllocStringByteLen(buf, lstrlenA(buf)); 7 } 8}

という感じになるかと思います。

文字列は BSTR で渡されますが、困ったことに VB 側が Unicode から Ansi に変換してしまいます。

ですから、Ansi → Unicode の変換を行ってから C# の DLL を呼び出す必要があります。

逆に C# から渡された文字列は、Unicode から Ansi への変換を行ってから VB6 に戻す必要があります。

投稿2023/09/21 04:30

編集2023/09/22 08:03
KOZ6.0

総合スコア2628

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2023/09/21 05:16

ありがとうございます。Visual Studio 2019でx86指定でビルドしています。 また、参考サイトでC#ソースを手直ししました。 が、状況は変わりませんでした。
KOZ6.0

2023/09/21 05:28

参照設定して使うんですよ
退会済みユーザー

退会済みユーザー

2023/09/21 07:13

ありがとうございます。冒頭に書いたとおり、 VB6の開発環境は作れないので、現状の記述のままで利用できるDLLをC#で作成する必要があります。
退会済みユーザー

退会済みユーザー

2023/09/21 08:10

VB6は現在リリースしているexeのまま活用し、呼び出しているDLLのみを入れ替える、ということです。
KOZ6.0

2023/09/21 10:03 編集

Private Declare Function SendMail Lib "smtpmail" _ (sServer As String, sTo As String, sFrom As String, _ sSubject As String, sBody As String, sFile As String) As String これって String の引数に ByVal はついてないんですか?
退会済みユーザー

退会済みユーザー

2023/09/22 00:53

はい、ByVal はついておりません。
退会済みユーザー

退会済みユーザー

2023/09/22 02:04

解決しました。dumpbinコマンドで関数名が表示されるようになりました。 ``` C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\SDK\ScopeCppSDK\vc15\VC\bin>dumpbin /exports "C:\Users\user\source\repos\smtpmail\bin\Debug\x86\smtpmail.dll" Microsoft (R) COFF/PE Dumper Version 14.12.25835.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file C:\Users\user\source\repos\smtpmail\bin\Debug\x86\smtpmail.dll File Type: DLL Section contains the following exports for \smtpmail.dll 00000000 characteristics 650CF0D1 time date stamp Fri Sep 22 10:41:37 2023 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 0000391E SendMail Summary 2000 .reloc 2000 .rsrc 2000 .sdata 2000 .text ``` ラッパーを作るのは、引き継ぎを考えると難しいと思ったので下記アドバイスを実施しました。 ``` では DllExport.bat を使ってみてください。 「C++からC# DLL を直接利用する方法」 https://qiita.com/Midoliy/items/58d56e202f104ebf867a ``` ソースはこれだけで、プロジェクトをアセンブリ登録する必要もありませんでした。 ``` using System; using System.Threading.Tasks; using MimeKit; using MimeKit.Text; using MailKit.Net.Smtp; using MailKit.Security; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Net.Security; namespace smtpmail { public class smtpmail { // VB6から呼び出す関数の宣言 [DllExport] public static string SendMail( string szServer, string szTo, string szFrom, string szSubject, string szBody, string szFile) { ``` SendMailが見つからないエラーは解消され、また新たなエラーとなりましたが、VB6とC#間も文字コードの問題だと思いますので、 ログを仕込んでこれから調べていきます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問