wininet.dllでftp接続するには?

解決


west  2007-07-27 08:05:14  No: 143759

こんばんは。

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

よろしくお願いします。


魔界の仮面弁士  2007-07-27 18:32:39  No: 143760

> 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


west  2007-07-28 08:10:29  No: 143761

魔界の仮面弁士さん,コメントありがとうございます。

ご指摘に従い,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


魔界の仮面弁士  2007-07-28 19:10:39  No: 143762

> シェアウェアの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 とか。


west  2007-07-28 20:09:50  No: 143763

魔界の仮面弁士さん,コメントありがとうございます。

アドバイスありがとうございます。

>デバイス上の 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


west  2007-08-21 07:35:24  No: 143764

こんばんは。

だいぶ時間過ぎてしまいましたが,その後をお知らせしておきます。

結局,あっさり解決しました。
前回のコードにおいて,InternetOpenの第2引数dwAccessを
INTERNET_OPEN_TYPE_PRECONFIGからINTERNET_OPEN_TYPE_DIRECTに
変更したらあっさり繋がりました。

魔界の仮面弁士さんのアドバイス通り,正しい引数の型の使用と
十分な検証が重要でした。

ありがとうございました。
また,よろしくお願いします。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加