はじめまして。
今、VB6.0にてWinInetを使用してFTPプログラムを初めて作成しているのですが
FTPのカレントディレクトリ変更がうまくいきません。
FTPサーバのC:\FTPtestをFTPサーバディレクトリに設定しています。
この1階層下の「C:\FTPtest\data」ディレクトリ内のデータを
GETしたいのですがうまくいきません。
事象としては「FtpSetCurrentDirectory」関数後に
Err.LastDllErrorプロパティを用いると
12003(パスなし?)が表示されてしまいます。
下記にソースを記述致しますのでFTPに詳しい方
是非教えて頂けないでしょうか。宜しくお願い致します。
************************************
Private Const msFtpSvr = "11.111.11.11" 'FTP Server IP
Private Const msFtpDir = "C:\FTPtest" 'FTP Server Dir
Private Const msFtpUid = "abcdefg" 'FTP Login UserID
Private Const msFtpPwd = "12345" 'FTP Login Password
Private Const msReciveDir = "E:\APP\data" 'FTP Recive Server Dir
Private Const msFtpFilNm = TENSODATA.txt 'FTP Target FileName
Private Const msRecFilNm = GETDATA.txt 'FTP Recive FileName
'AccessType
Private Const INTERNET_OPEN_TYPE_PRECONFIG = 0&
Private Const INTERNET_OPEN_TYPE_DIRECT = 1&
Private Const INTERNET_OPEN_TYPE_PROXY = 3&
'File Attribute
Private Const FILE_ATTRIBUTE_READONLY = &H1&
Private Const FILE_ATTRIBUTE_HIDDEN = &H2&
Private Const FILE_ATTRIBUTE_SYSTEM = &H4&
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10&
Private Const FILE_ATTRIBUTE_ARCHIVE = &H20&
Private Const FILE_ATTRIBUTE_NORMAL = &H80&
Private Const FILE_ATTRIBUTE_TEMPORARY = &H100&
Private Const FILE_ATTRIBUTE_COMPRESSED = &H800&
Private Const FILE_ATTRIBUTE_OFFLINE = &H1000&
'FTP TransferType
Private Const FTP_TRANSFER_TYPE_ASCII = &H1&
Private Const FTP_TRANSFER_TYPE_BINARY = &H2&
'Cache Flags
Private Const INTERNET_FLAG_RELOAD = &H80000000
Private Const INTERNET_FLAG_DONT_CACHE = &H4000000
Private Const INTERNET_FLAG_RESYNCHRONIZE = &H800
Private Const INTERNET_FLAG_NEED_FILE = &H10
Private Const INTERNET_FLAG_HYPERLINK = &H400
'ConnectServerPort
Private Const INTERNET_INVALID_PORT_NUMBER = 0
Private Const INTERNET_DEFAULT_FTP_PORT = 21
Private Const INTERNET_DEFAULT_GOPHER_PORT = 70
Private Const INTERNET_DEFAULT_HTTP_PORT = 80
Private Const INTERNET_DEFAULT_HTTPS_PORT = 443
Private Const INTERNET_DEFAULT_SOCKS_PORT = 1080
'ConnectService
Private Const INTERNET_SERVICE_FTP = 1&
Private Const INTERNET_SERVICE_GOPHER = 2&
Private Const INTERNET_SERVICE_HTTP = 3& '
'=====================================================================
'API(WinInet)定義
'=====================================================================
'WinInet を初期化
Private Declare Function InternetOpen Lib "wininet.dll" _
Alias "InternetOpenA" _
(ByVal lpszAgent As String, ByVal dwAccessType As Long, _
ByVal lpszProxyName As String, ByVal lpszProxyBypass As String, _
ByVal dwFlags As Long) As Long
'(FTP, HTTP, Gopher)サービスに接続する
Private Declare Function InternetConnect Lib "wininet.dll" _
Alias "InternetConnectA" _
(ByVal hInternetSession As Long, ByVal lpszServerName As String, _
ByVal nServerPort As Integer, ByVal lpszUsername As String, _
ByVal lpszPassword As String, ByVal dwService As Long, _
ByVal dwFlags As Long, ByVal dwContext As Long) As Long
'カレントディレクトリを変更
Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
Alias "FtpSetCurrentDirectoryA" _
(ByVal hFtpSession As Long, ByRef lpszDirectory As Byte) As Long
'ファイルをローカルディスクにコピー
Private Declare Function FtpGetFile Lib "wininet.dll" _
Alias "FtpGetFileA" _
(ByVal hFtpSession As Long, ByRef lpszRemoteFile As Byte, _
ByRef lpszNewFile As Byte, ByVal fFailIfExists As Long, _
ByVal dwFlagsAndAttributes As Long, ByVal dwFlags As Long, _
ByVal dwContext As Long) As Long
'WinInet で作成したハンドルをクローズ
Private Declare Function InternetCloseHandle Lib "wininet.dll" _
(ByVal hInternet As Long) As Long
'=====================================================================
Public Function FtpImgGet()
Dim lngInethnd As Long 'InterNet Open Handle
Dim lngFtphnd As Long 'InterNet Connect Handle
Dim lngRet As Long '戻り値
Dim strFTPDir As String 'FTP Serverの変更後CurrentDirectory
Dim strLclDir As String 'DownLoad したファイルを保存する Directory
Dim bytFtpBuff() As Byte 'FTP Server 内の Download するファイル名
Dim bytLclBuff() As Byte 'Download したファイルを保存するファイル名
Dim objFileSys As Object
On Error GoTo FTPDATAGETINI_ERR
strFTPDir = msFtpDir & "\data"
Set objFileSys = CreateObject("Scripting.FileSystemObject")
'InternetOpen (Handle を取得) インターネットへの接続します
lngInethnd = InternetOpen(vbNullString, INTERNET_OPEN_TYPE_PRECONFIG, _
vbNullString, vbNullString, 0)
'InternetConnect (上記で取得した Handle で FTP Server に Connect)
lngFtphnd = InternetConnect(lngInethnd, msFtpSvr, INTERNET_DEFAULT_FTP_PORT, _
msFtpUid, msFtpPwd, INTERNET_SERVICE_FTP, 0, 0)
'FTP Server の取得ファイルが存在する Directory
bytFtpBuff = StrConv((strFTPDir & vbNullChar), vbFromUnicode)
' 'FTP Server の CurrentDirectory を変更
lngRet = FtpSetCurrentDirectory(lngFtphnd, bytFtpBuff(0))
MsgBox Err.LastDllError ← 12003(パスなし?)が表示される。
'FTP Server から取得するファイルの名前
bytFtpBuff = StrConv((msFtpFilNm & vbNullChar), vbFromUnicode)
'DownLoad 先をフルパスで指定
strLclDir = msReciveDir & "\" & msRecFilNm
bytLclBuff = StrConv((strLclDir & vbNullChar), vbFromUnicode)
'ローカルに、すでに同一ファイル名が存在する場合は削除
If objFileSys.FileExists(strLclDir) Then
Kill strLclDir
End If
'DownLoad (ASCII-MODEの場合&キャッシュを使わずサーバからダウンロードを強制)
lngRet = FtpGetFile(lngFtphnd, bytFtpBuff(0), bytLclBuff(0), 1, FILE_ATTRIBUTE_NORMAL, _
FTP_TRANSFER_TYPE_ASCII Or INTERNET_FLAG_RELOAD, 0)
'オブジェクトの解放
Set objFileSys = Nothing
Exit Function
FTPDATAGETINI_ERR:
'InternetConnect がされた後なのか判断
If lngFtphnd <> 0 Then
'Internet Handle Close 処理
lngRet = InternetCloseHandle(lngFtphnd)
End If
End
End Function
ftpコマンドやFFFTPの様なツールで同じ事を試すとどうなりますか?
アクセス権設定は大丈夫ですか?
ftpサーバの設定は大丈夫ですか?
レス有難うございます。
>ftpコマンドやFFFTPの様なツールで同じ事を試すとどうなりますか?
>アクセス権設定は大丈夫ですか?
>ftpサーバの設定は大丈夫ですか?
→設定、権限等は問題ないと思います。
設定してあるディレクトリのデータの場合GET出来るので
GETしてくるディレクトリの変更が上手くいっていないと考えております。
サーバの設定によっては、接続時に
ftp://server/
ではなく、
ftp://server/ユーザフォルダ/
に接続される場合がありますので、注意してください。
> 12003(パスなし?)が表示されてしまいます。
自身で設定しているサーバであれば、APIによる通信後に、
サーバ側のアクセスログを確認されてみては如何でしょう。
lngRet = FtpSetCurrentDirectory(lngFtphnd, bytFtpBuff(0))
を単に
lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)
としたらどうなりますか。
レス有難うございます。
>ftp://server/ユーザフォルダ/
>に接続される場合がありますので、注意してください。
→注意してみてみます。
>> 12003(パスなし?)が表示されてしまいます。
>自身で設定しているサーバであれば、APIによる通信後に、
>サーバ側のアクセスログを確認されてみては如何でしょう。
→アクセスログってどうやって見るんでしたっけ?(管理ツール?)
初歩的な質問ですいません。
>lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)
>としたらどうなりますか。
→このようにしてみましたが同じ結果でした。
> →アクセスログってどうやって見るんでしたっけ?(管理ツール?)
IISなら、「管理ツール」からftpサイトのプロパティを開き、
ログのプロパティにて指定されたパスに、テキスト形式の
*.log があります。
あとは、エラーになってしまうと言う APIによるFTP の場合と、
期待動作している方(ツール等によるFTP)の場合とで、
サーバ側のアクセスログを比較すれば、解決の糸口になるかと。
で、既に指摘がありますが、
> Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
> Alias "FtpSetCurrentDirectoryA" _
> (ByVal hFtpSession As Long, ByRef lpszDirectory As Byte) As Long
この宣言は、〜A系関数の呼び出しなので、文字列は
ByVal lpszDirectory As String の方が簡単でしょう。
(ByVal As String にした場合は、StrConvを行う必要が無くなります)
これがもし、W系関数である場合は、宣言を ByRef As Byte にして、
バイト配列の先頭要素を参照渡しする手法が使えますが、
この場合も、StrConv を使う必要は無いと思います。
アクセスログの件有難う御座います。
確認してみます。
Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
Alias "FtpSetCurrentDirectoryA" _
(ByVal hFtpSession As Long, ByRef lpszDirectory As String) As Long
・
・
・
'StrConvを使用しない
lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)
ってことですよね!?
これで試した結果も「12003(パスなし?)」が表示されてしまいます。
余談ですが、W系関数って何でしょうか?
すいません。
読み落としがありました。
Private Declare Function FtpSetCurrentDirectory Lib "wininet.dll" _
Alias "FtpSetCurrentDirectoryA" _
(ByVal hFtpSession As Long, ByVal lpszDirectory As String) As Long
・
・
・
'StrConvを使用しない
lngRet = FtpSetCurrentDirectory(lngFtphnd,strFTPDir)
で取得する事ができました。
レスをしてくれた皆様有難う御座いました。
解決です。
> 余談ですが、W系関数って何でしょうか?
失礼しました。あれでは説明不足ですよね。
文字列を扱うAPIの多くは、
ANSI文字列(システム既定のコード/Shift_JIS)を使うバージョン
Wide文字列(Unicode)を使うバージョン
の2種類を持っていますよね。
前者は関数名の最後がAで終わり、後者はWで終わります。
そして今回の場合、『Alias "FtpSetCurrentDirectoryA"』
という「最後がAで終わる関数」を使っていましたので、
それを指した発言でした。m(_ _)m
W系は、『Alias "FtpSetCurrentDirectoryW"』です。
ツイート | ![]() |