VB.NETでメールを送信するプログラムを作成しています。
http://dobon.net/vb/dotnet/internet/smtpmail.html
の様にSystem.Web.Mail.SmtpMailクラスを使うとメール送信できたの
ですが、「Win98系だとエラーになる」
「不定期にエラーになる(XPのSP2をあてたのが原因か?)」
等の理由から、フリーのDLLを使わせていただく事にしました。
そこで、Declareステートメントや
http://dobon.net/vb/dotnet/links/extractarchive.html
にあるようにDllImportを使ってアンマネージDLLを呼び出そうとしているのですがうまくいきません。
マーシャリング等が関係していたりするのでしょうか?
本DLLのFAQ
http://www.bea.hi-ho.ne.jp/cgi-bin/user/byoko/bnews
にも同じような現象で苦しんでいる方がいらっしゃったのですが、
COM使用で断念したようです。。
下記にソースを載せます。
また実際、System.Web.Mail.SmtpMailクラスはWin98系だと失敗するのでしょうか?(そのような記述は見つからなかったのですが。。)
アンマネージDLLの呼び出しが始めてなので、
本当はSystem.Web.Mail.SmtpMailクラスを使いたいのですが。。
初歩的な間違いをしているのかもしれませんが、
どこを勘違いしてるのかわかりません。。
宜しくお願いします。
○Declareステートメントを使用した場合○
#宣言
Private Declare Function SendMail Lib "bsmtp" _
(ByVal szServer As String, ByVal szTo As String, ByVal szFrom As String, _
ByVal szSubject As String, ByVal szBody As String, ByVal szFile As String) As String
宣言文が「名前空間のステートメントが無効です」というエラーになっています。
・DLL 関数を保持するクラスを作成した場合
#宣言
Imports System.Runtime.InteropServices
Public Class BSMTP
Declare Function SendMail Lib "BSMTP.dll" _
(ByVal szServer As String, ByVal szTo As String, ByVal szFrom As String, _
ByVal szSubject As String, ByVal szBody As String, ByVal szFile As String) As String
End Class
#使用時
strRet = BSMTP.SendMail(strSmtp, strTo, strFrom, strSubject, strBody, Nothing)
「実行時例外がスローされました : System.NullReferenceException -
オブジェクト参照がオブジェクト インスタンスに設定されていません。」
というエラーになります。
○DllImport属性を使用した場合○
#宣言
Imports System.Runtime.InteropServices
<DllImport("bsmtp")> _
Private Shared Function SendMail(ByVal szServer As String, ByVal szTo As String, ByVal szFrom As String, _
ByVal szSubject As String, ByVal szBody As String, ByVal szFile As String) As String
End Function
宣言文が「名前空間のステートメントが無効です」というエラーになっています。
・DLL 関数を保持するクラスを作成した場合
#宣言
Public Class BSMTP
<DllImport("bsmtp.dll", CharSet:=CharSet.Auto)> _
Public Shared Function SendMail(ByVal szServer As String, ByVal szTo As String, _
ByVal szFrom As String, ByVal szSubject As String, ByVal szBody As String, _
ByVal szFile As String) As String
End Function
End Class
#使用時
strRet = BSMTP.SendMail(strSmtp, strTo, strFrom, strSubject, strBody, Nothing)
「実行時例外がスローされました : System.NullReferenceException -
オブジェクト参照がオブジェクト インスタンスに設定されていません。」
というエラーになります。
> 宣言文が「名前空間のステートメントが無効です」というエラーになっています。
その宣言は、「どこに」記載していますか?
Module〜End Module
Class〜End Class
Structure〜End Structure
などの中に書かないと、そのようなエラーになりますよ。
> 「実行時例外がスローされました : System.NullReferenceException -
API宣言が間違っています。各引数を ByRef As String にしてください。
> また実際、System.Web.Mail.SmtpMailクラスはWin98系だと失敗するのでしょうか?(そのような記述は見つからなかったのですが。。)
http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfsystemwebmailsmtpmailclasstopic.asp
》 プラットフォーム: Windows 2000, Windows XP Professional, Windows Server 2003 ファミリ
魔界の仮面弁士さん、ありがとうございました!
>その宣言は、「どこに」記載していますか?
Imports〜 の直ぐ下に記載していました。。
該当のものはModule〜End Moduleの中に記載し、
各引数はByRefに変えたら全てうまくいきました!
(CharSetは削除)
本当にありがとうございました。
ところで、引数について私の参考書にはByValで宣言されているものもあったのですが、
なぜ今回ByValではNGでByRefに変更したらうまくいったのでしょうか?
(呼び出すDLL側の仕様でしょうかね。。?)
#MSDNにSystem.Web.Mail.SmtpMail対象OSについてしっかり記載されていましたね。。
#すみません、ありがとうございました!
> ところで、引数について私の参考書にはByValで宣言されているものもあったのですが、
> なぜ今回ByValではNGでByRefに変更したらうまくいったのでしょうか?
う〜ん。
簡潔に説明できる自身が無いので、細かい説明はパスさせて下さい。
# C形式の文字列云々とか、OLEのBSTR文字列の説明とかを
# 始めてしまうと、キリが無いし…。
> (呼び出すDLL側の仕様でしょうかね。。?)
まぁ、そういう事です。
http://www.hi-ho.ne.jp/babaq/bsmtp.html のページでは、VB6/VBA向けの
コードで記述されていますので、よく見ないと、ByRef で宣言する仕様に
なっている事に気づき難いかも知れませんね。
ほとんどの文字列系DLLは、Stringの受け渡しを、ByVal As String で
行う事になります。ByRefで渡すタイプはごく稀です。
たとえば、よく使われる USER32 とか GDI32 とか KERNEL32 などのDLLでは、
文字列は基本的に ByVal As String で渡す仕様になってます。
(Unicode文字列形式を要求するタイプは、ByRef As Byteなどになりますが)
OLE/COMベースの処理を行うDLLの中には、今回のように、ByRefで
文字列を渡す仕様の物もありますが、そういう DLL は、
さほど多くありません。
そもそも、OLE/COM系DLLの場合、参照設定して使うタイプが多いですしね。(^^;)
一箇所補足。m(_ _)m
> たとえば、よく使われる USER32 とか GDI32 とか KERNEL32 などのDLLでは、
> 文字列は基本的に ByVal As String で渡す仕様になってます。
> (Unicode文字列形式を要求するタイプは、ByRef As Byteなどになりますが)
上記の「ByRef As Byte」の一文は、VB6 や VBA の場合です。
VB.NETの場合は、宣言時に ANSIモード/Unicocdモードを指定できるように
拡張されていますので、Unicode文字列を扱うDLLの場合も ByVal As String が使えます。
ByRefで渡すタイプはまれだからサンプルもByValで渡すものばかりだったんですね。。
魔界の仮面弁士さん、
丁寧に解説頂き、本当にありがとうございまいました。
ツイート | ![]() |