こんばんは。
Windows Mobile 5.0(.net compact framework2.0上)上でFTPのクライアント機能で困っています。
基本的なことだとは思いますが,教えて下さい。
compact frameworkということで,wininet.dllを利用しようとしています。
InternetOpenは出来るのですが,InternetConnectでNULLが帰ってきてしまいます。
以下にテスト用に作ったアプリのコードを掲載します。
FormにButtonを一つ置き,ボタンを押すとFTPに接続するだけのプログラムです。
実行はPDAのエミュレーター上で動き,FTPはエミュレーターが動いているPC自身で動いています。
エミュレータ上にインストールしたシェアウェアのFTPクライアントからアクセスできることは確認済みです。
また,全く同等なソースを通常の(PC用の).net frameworkプロジェクトで動かすと何も問題なく動きます。
Imports System.Text
Public Class Form1
Private hSession As Int32 = 0
Private hFtpSession As Int32 = 0
Private Const INTERNET_OPEN_TYPE_DIRECT = 1
Private Const INTERNET_DEFAULT_FTP_PORT As Integer = 21
Private Const INTERNET_SERVICE_FTP As Int32 = 1
Private Const INTERNET_FLAG_PASSIVE As Int32 = &H8000000
Private Const scUserAgent = "vb wininet"
Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _
(ByVal sAgent As String, ByVal lAccessType As Int32, ByVal sProxyName As String, _
ByVal sProxyBypass As String, ByVal lFlags As Integer) As Int32
Private Declare Function InternetConnect Lib "wininet.dll" Alias _
"InternetConnectA" (ByVal hInternetSession As System.IntPtr, ByVal _
sServerName As String, ByVal nServerPort As Integer, ByVal _
sUsername As String, ByVal sPassword As String, ByVal _
lService As Int32, ByVal lFlags As Int32, ByVal lContext As System.IntPtr) As System.IntPtr
Private Declare Function InternetCloseHandle Lib "wininet.dll" _
(ByVal hInternet As Integer) As Boolean
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim strHost As String
strHost = System.Net.Dns.GetHostName()
Dim ip As System.Net.IPHostEntry
Dim ipAddr As System.Net.IPAddress
Dim blnResult As Boolean = False
hSession = 0
hSession = InternetOpen(scUserAgent, INTERNET_OPEN_TYPE_DIRECT, vbNullString, vbNullString, 0)
If hSession Then
hFtpSession = 0
Dim nFlag As Integer
Dim timeout As ULong = 1000
Dim lblength As Long = Len(timeout)
hFtpSession = InternetConnect(hSession, "***.***.***.***", INTERNET_DEFAULT_FTP_PORT, _
"Username", "Password", INTERNET_SERVICE_FTP, 0, 0)
If hFtpSession = 0 Then
MessageBox.Show("NG/hFtpSession/" + Err.LastDllError.ToString())
Else
MessageBox.Show("OK/hFtpSession")
InternetCloseHandle(hFtpSession)
End If
Else
MessageBox.Show("NG/hSession" + Err.LastDllError.ToString())
InternetCloseHandle(hSession)
End If
End Sub
End Class
よろしくお願いします。
> InternetOpenは出来るのですが,InternetConnectでNULLが帰ってきてしまいます。
戻り値や Err.LastDllError など、具体的なエラー内容を明示してください。
> Private Const INTERNET_OPEN_TYPE_DIRECT = 1
型が無いですね。Option Strict/Option Explicit を On にしておきましょう。
> Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA"
Windows CE は Unicode 環境ですから、A 系ではなく W 系で
実装してみてください。
下記の eVB3 サンプルでも、Wide 系 API を使っていますよね。
http://support.microsoft.com/kb/305598/ja
魔界の仮面弁士さん,コメントありがとうございます。
ご指摘に従い,Option Strict/ExplicitをOn,Wide系,Err.LastDllErrorを加えて,
リスト1のように修正しました。
その結果,hSessionの値は13369348でInternetOpenは出来ましたが,
やはりInternetConnectは戻り値hFtpSessionは0でした。
その際のErr.LastDllErrorは12029(サーバーに接続出来ない)でした。
(以前のプログラムでは12002(タイムアウト)でしたが。)
その後の,InternetCloseHandle(hSession)では例外NotSupportedExceptionが発生してしまいます。
と言うことは,最初のInternetOpenも実は正常に実行出来ていないのでしょうか?
また,その際のErr.LastDllErrorはなぜか12029でした。
リスト1
Option Strict On
Option Explicit On
Imports System.Text
Public Class Form1
Private hSession As IntPtr = 0
Private hFtpSession As IntPtr = 0
Private Const INTERNET_OPEN_TYPE_PRECONFIG As Long = 0
Private Const INTERNET_OPEN_TYPE_DIRECT As Long = 1
Private Const INTERNET_DEFAULT_FTP_PORT As Integer = 21
Private Const INTERNET_SERVICE_FTP As Long = 1
Private Const INTERNET_FLAG_PASSIVE As Long = &H8000000
Private Const scUserAgent As String = "vb wininet"
Declare Function InternetCloseHandle Lib "wininet" ( _
ByVal hInet As System.IntPtr) As Long
Declare Function InternetConnect Lib "wininet" Alias "InternetConnectW" ( _
ByVal hInet As System.IntPtr, _
ByVal lpszServerName As String, _
ByVal nServerPort As Integer, _
ByVal lpszUsername As String, _
ByVal lpszPassword As String, _
ByVal dwService As Int32, _
ByVal dwFlags As Int32, _
ByVal dwContext As System.IntPtr) As System.IntPtr
Declare Function InternetOpen Lib "wininet" Alias "InternetOpenW" ( _
ByVal lpszAgent As String, _
ByVal dwAccessType As Int32, _
ByVal lpszProxyName As String, _
ByVal lpszProxyBypass As String, _
ByVal dwFlags As Integer) As System.IntPtr
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim blnResult As Boolean = False
hSession = System.IntPtr.Zero
Try
hSession = InternetOpen(scUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
Catch ex As Exception
MessageBox.Show("InternetOpen Exception/" + ex.ToString())
MessageBox.Show("InternetOpen Error/" + Err.LastDllError.ToString())
Return
End Try
If hSession <> System.IntPtr.Zero Then
hFtpSession = System.IntPtr.Zero
Try
hFtpSession = InternetConnect(hSession, "***.***.***.***", INTERNET_DEFAULT_FTP_PORT, _
"UserName", "PassWord", INTERNET_SERVICE_FTP, 0, System.IntPtr.Zero)
Catch ex As Exception
MessageBox.Show("InternetOpen Exception/" + ex.ToString())
MessageBox.Show("InternetOpen Error/" + Err.LastDllError.ToString())
InternetCloseHandle(hSession)
Return
End Try
If hFtpSession = System.IntPtr.Zero Then
MessageBox.Show("NG/hFtpSession/" + Err.LastDllError.ToString())
Else
MessageBox.Show("OK/hFtpSession")
Try
InternetCloseHandle(hFtpSession)
Catch ex As Exception
MessageBox.Show("InternetCloseHandle(hFtpSession) Exception/" + ex.ToString())
MessageBox.Show("InternetCloseHandle(hFtpSession) Error/" + Err.LastDllError.ToString())
End Try
End If
Try
InternetCloseHandle(hSession)
Catch ex As Exception
MessageBox.Show("InternetCloseHandle(hSession) Exception/" + ex.ToString())
MessageBox.Show("InternetCloseHandle(hSession) Error/" + Err.LastDllError.ToString())
End Try
Else
MessageBox.Show("NG/hSession" + Err.LastDllError.ToString())
End If
End Sub
End Class
> シェアウェアのFTPクライアントからアクセスできることは確認済みです。
それだと確認にならない気がします。
そのソフトは、wininet ではなく winsock を使っているのかも知れませんし。
まず、デバイス上の Pocket Internet Explorer から、ftp.microsoft.com を
開く事はできていますか? できているという前提で:
> 実行はPDAのエミュレーター上で動き
実機で実行させた場合はどうですか?
> リスト1のように修正しました。
・Long 型は NG です。
eVB3 の Long は 32bit ですが、VB2005 では 64bit サイズです。
・hSession = 0 と hSession = IntPtr.Zero が混在しているのは見苦しいかも。
間違いでは無いのですけれどね。
・同様に、Int32 と Integer が同居しているのも、統一感が無いかも。
InternetConnect とか。
魔界の仮面弁士さん,コメントありがとうございます。
アドバイスありがとうございます。
>デバイス上の Pocket Internet Explorer から、ftp.microsoft.com を
>開く事はできていますか?
開けました。
>実機で実行させた場合はどうですか?
残念ながら,実機は貸し出しているので,月曜日になったら確認してみます。
>・Long 型は NG です。
> eVB3 の Long は 32bit ですが、VB2005 では 64bit サイズです。
Long型はInt32へ,Integer型もInt32と明示してみました。
>・hSession = 0 と hSession = IntPtr.Zero が混在しているのは見苦しいかも。
> 間違いでは無いのですけれどね。
IntPtr.Zeroに統一しました。
現在のリストをリスト2として添付しています。
現在の結果,hSessionの値は13369348でInternetOpenは出来ましたが,
やはりInternetConnectは戻り値hFtpSessionは0でした。
その際のErr.LastDllErrorは12029(サーバーに接続出来ない)でした。
その後の,InternetCloseHandle(hSession)では例外NotSupportedExceptionは発生しなくなりました。
一歩前進?でしょうか。
アドバイスよろしくお願いします。
Option Strict On
Option Explicit On
Imports System.Text
Public Class Form1
Private hSession As IntPtr = System.IntPtr.Zero
Private hFtpSession As IntPtr = System.IntPtr.Zero
Private Const INTERNET_OPEN_TYPE_PRECONFIG As Int32 = 0
Private Const INTERNET_OPEN_TYPE_DIRECT As Int32 = 1
Private Const INTERNET_DEFAULT_FTP_PORT As Int32 = 21
Private Const INTERNET_SERVICE_FTP As Int32 = 1
Private Const INTERNET_FLAG_PASSIVE As Int32 = &H8000000
Private Const scUserAgent As String = "vb wininet"
Declare Function InternetCloseHandle Lib "wininet" ( _
ByVal hInet As System.IntPtr) As Int32
Declare Function InternetConnect Lib "wininet" Alias "InternetConnectW" ( _
ByVal hInet As System.IntPtr, _
ByVal lpszServerName As String, _
ByVal nServerPort As Int32, _
ByVal lpszUsername As String, _
ByVal lpszPassword As String, _
ByVal dwService As Int32, _
ByVal dwFlags As Int32, _
ByVal dwContext As System.IntPtr) As System.IntPtr
Declare Function InternetOpen Lib "wininet" Alias "InternetOpenW" ( _
ByVal lpszAgent As String, _
ByVal dwAccessType As Int32, _
ByVal lpszProxyName As String, _
ByVal lpszProxyBypass As String, _
ByVal dwFlags As Int32) As System.IntPtr
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim strHost As String
strHost = System.Net.Dns.GetHostName()
Dim ip As System.Net.IPHostEntry
Dim ipAddr As System.Net.IPAddress
ip = System.Net.Dns.GetHostByName(strHost)
ipAddr = ip.AddressList(0)
MessageBox.Show("Host:" + strHost.ToString() + "/IP:" + ipAddr.ToString(), _
"Networkの確認", MessageBoxButtons.OKCancel, _
MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1)
Dim blnResult As Boolean = False
hSession = System.IntPtr.Zero
Try
hSession = InternetOpen(scUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, vbNullString, vbNullString, 0)
Catch ex As Exception
MessageBox.Show("InternetOpen Exception/" + ex.ToString())
MessageBox.Show("InternetOpen Error/" + Err.LastDllError.ToString())
Return
End Try
If hSession <> System.IntPtr.Zero Then
hFtpSession = System.IntPtr.Zero
Try
hFtpSession = InternetConnect(hSession, "***.***.***.***", INTERNET_DEFAULT_FTP_PORT, _
"UserName", "PassWord", INTERNET_SERVICE_FTP, 0, System.IntPtr.Zero)
Catch ex As Exception
MessageBox.Show("InternetOpen Exception/" + ex.ToString())
MessageBox.Show("InternetOpen Error/" + Err.LastDllError.ToString())
InternetCloseHandle(hSession)
Return
End Try
If hFtpSession = System.IntPtr.Zero Then
MessageBox.Show("NG/hFtpSession/" + Err.LastDllError.ToString())
Else
MessageBox.Show("OK/hFtpSession")
Try
InternetCloseHandle(hFtpSession)
Catch ex As Exception
MessageBox.Show("InternetCloseHandle(hFtpSession) Exception/" + ex.ToString())
MessageBox.Show("InternetCloseHandle(hFtpSession) Error/" + Err.LastDllError.ToString())
End Try
End If
Try
InternetCloseHandle(hSession)
Catch ex As Exception
MessageBox.Show("InternetCloseHandle(hSession) Exception/" + ex.ToString())
MessageBox.Show("InternetCloseHandle(hSession) Error/" + Err.LastDllError.ToString())
End Try
Else
MessageBox.Show("NG/hSession" + Err.LastDllError.ToString())
End If
End Sub
End Class
こんばんは。
だいぶ時間過ぎてしまいましたが,その後をお知らせしておきます。
結局,あっさり解決しました。
前回のコードにおいて,InternetOpenの第2引数dwAccessを
INTERNET_OPEN_TYPE_PRECONFIGからINTERNET_OPEN_TYPE_DIRECTに
変更したらあっさり繋がりました。
魔界の仮面弁士さんのアドバイス通り,正しい引数の型の使用と
十分な検証が重要でした。
ありがとうございました。
また,よろしくお願いします。
| ツイート |
|