お世話になっています。
###前提
過去に書かれたVB6のソースコードを
VB.NETへアップグレードする作業を行っています。
VB6でWIN32APIを使用していたコード(以下、旧ソース)を、VB.NETにアップグレードする際
WIN32API関数 FtpGetFileを使用する箇所で疑問発生しました。
(.Net Framework 3.5です)
またFTPコマンドおよび、旧ソースでのFileGetには成功しており、FTPサーバ側の問題でないことは確認できています。
###謎
発生している問題として、
WIN32API関数 FtpGetFile をVB.NETで使用すると
戻り値0(ファイル取得失敗)が返ってきます。
Visual Basic6 リファレンス FtpGetFile
によると、転送元ファイル名および 転送先ファイル名は文字列の引数として使用すると書いてあります。
ところが、旧ソース(VB6)の定義部では、型はAnyとなっていました。
VB6 FtpGetFile 定義部
VB6
1Private Declare Function FtpGetFile Lib "wininet.dll" _ 2 Alias "FtpGetFileA" _ 3 (ByVal hFtpSession As Long, _ 4 ByRef lpszRemoteFile As Any, _ 5 ByRef lpszNewFile As Any, _ 6 ByVal fFailIfExists As Long, _ 7 ByVal dwFlagsAndAttributes As Long, _ 8 ByVal dwFlags As Long, _ 9 ByVal dwContext As Long _ 10 ) As Long
↑をVisual Studio 2015による自動アップグレード実施すると、
Any は String として解釈されています。
アップグレードされたVB.NET FtpGetFile 定義部
VBNET
1'UPGRADE_ISSUE: パラメータ 'As Any' の宣言はサポートされません。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="FAE78A8D-8978-4FD4-8208-5B7324A8F795"' をクリックしてください。 2 Private Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" (ByVal hFtpSession As Integer, ByRef lpszRemoteFile As String, ByRef lpszNewFile As String, ByVal fFailIfExists As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Integer
ところが、これをこのまま使用すると、戻り値0(ファイル取得失敗)が返ってきます。
VB.NET使用箇所コード
VBNET
1' GetFileName PutFileName にはそれぞれ XXX/XX/XXX.xxx形式の文字列が入っています。 2Result = FtpGetFile(ssnFtp, GetFileName, PutFileName, 1, FILE_ATTRIBUTE_NORMAL, 1, 0)
そこで旧ソースの使用箇所を確認すると、引数にByte型に変換した値を使用していました。
旧ソース(VB6)使用箇所コード
VB6
1' 2 bytGetFile = StrConv((GetFileName& vbNullChar), vbFromUnicode) 3 bytPutFile = StrConv((PutFileName& vbNullChar), vbFromUnicode) 4 lngRet = FtpGetFile(lngFtp, _ 5 bytGetFile (0), _ 6 bytPutFile (0), _ 7 1&, _ 8 FILE_ATTRIBUTE_NORMAL&, _ 9 1&, _ 10 0&)
※ためしにVB6側のソース修正し、ファイルパスの箇所を文字列で渡したところ、ファイル取得に失敗しました。
(ファイルパスの引数箇所が原因と推察した理由はここになります。)
ということで、VB.NET側で以下のようにしてみたところ
VBNET
1'FtpGetFile 定義変更 2 'Private Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" (ByVal hFtpSession As Integer, ByRef lpszRemoteFile As String, ByRef lpszNewFile As String, ByVal fFailIfExists As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Integer 3 Private Declare Function FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" (ByVal hFtpSession As Integer, ByRef lpszRemoteFile As Byte, ByRef lpszNewFile As Byte, ByVal fFailIfExists As Integer, ByVal dwFlagsAndAttributes As Integer, ByVal dwFlags As Integer, ByVal dwContext As Integer) As Integer 4 5 6 'UPGRADE_TODO: System.Text.UnicodeEncoding.Unicode.GetBytes() を使うためにコードがアップグレードされましたが、動作が異なる可能性があります。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="93DD716C-10E3-41BE-A4A8-3BA40157905B"' をクリックしてください。 7 bytGetFile= System.Text.Encoding.GetEncoding(932).GetBytes(GetFileName & vbNullChar) 8 'UPGRADE_ISSUE: 定数 vbFromUnicode はアップグレードされませんでした。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="55B59875-9A95-4B71-9D6A-7C294BF7139D"' をクリックしてください。 9 'UPGRADE_TODO: System.Text.UnicodeEncoding.Unicode.GetBytes() を使うためにコードがアップグレードされましたが、動作が異なる可能性があります。 詳細については、'ms-help://MS.VSCC.v90/dv_commoner/local/redirect.htm?keyword="93DD716C-10E3-41BE-A4A8-3BA40157905B"' をクリックしてください。 10 bytPutFile= System.Text.Encoding.GetEncoding(932).GetBytes(PutFileName & vbNullChar) 11 12 Result = FtpGetFile(ssnFtp, bytGetFile(0), bytPutFile(0), 1, FILE_ATTRIBUTE_NORMAL, 1, 0) 13
うまく取得できました。
###質問
上記のような動作になってしまうのはなぜなのでしょうか?(Stringで渡すとダメだがByteだとOK)
FtpGetFileの仕様で、ファイルパスはByteでしか受け付けないようになっているのでしょうか
(だとするとVisual StudioのUpgrade ToolでStringになるのは不親切な気もしますが。)
ご存知の方いらっしゃいましたら教えていただけないでしょうか。
###補足情報(言語/FW/ツール等のバージョンなど)
Visual Studio 2015 / .Net Framework 3.5
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/09/06 04:49
2016/09/06 04:58
2016/09/06 08:54