WinInet はまだまだ研究中のため、今のところ大したことは書けません。 よってこのコーナーはベータ版とさせていただきます。 テクニックの紹介というより、研究成果の中間発表といった感じのコーナーです(笑)
Visual Basic でインターネット上のデータを操作するには色々な方法がありますが、 ActiveX コントロールを使わない方法で代表的なものとしては、 WinSock API を使用する方法と WinInet API を使用する方法があります。 このコーナーでは WinInet について取り扱います。
WinInet とは Win32 Internet Functions の略で、"Wininet.dll" を呼び出して使用します。 ただしこの DLL は、 Microsoft Internet Explorer 3.0 以上がインストールされている環境にしかありませんので、 WinSock と比較すると汎用性では劣ります。 しかし、Microsoft の Netscape 潰しの策が功を奏し Windows 98 発売以来の IE の普及はすさまじいので、 大半の Win32 ユーザーは IE 入ってると思います(^^;
WinInet を使用すれば、WinSock よりずっと簡単に、データの送受信を行うことができます。 ポートを開いて・・・ホスト名をアドレスに変換して・・・などといった一連の処理は、 すべて WinInet が自動的にやってくれますので、 比較的 TCP/IP 初心者にもとっつきやすい API です。 そのかわり WinInet で扱えるプロトコルは HTTP, HTTPS, FTP, GOPHER だけ(たぶん)で、 POP3 や SMTP などとは通信できません。
WinInet で HTTP クライアントみたいなやつを作ってみたくなったので、
とりあえず VB のサンプルを探してみたのですが、FTP のサンプルは結構あるのに、
HTTP クライアントのサンプルは全然ありませんね〜(泣)
でも、さいわい C/C++ で書かれたすばらしい解説ページをいくつか見つけました。
それと Microsoft で公開されている Visual Basic 用 WinInet 宣言モジュールを参考にして、
なんとか作ることができました。
Wininet Programing | すばらしいです。WinInet の使い方を初心者向けに解説されています(C/C++) |
MASAPICO's PAGE | WinInet API 各関数の説明が詳しく、非常に役立ちました(C/C++) |
WinINet Functions | MSDN ライブラリの WinInet リファレンス。英語(C/C++) |
vbinet.exe | Visual Basic 用 WinInet 宣言モジュール。とりあえず、これは入手しましょう(笑) |
まず手っ取り早く、 vbinet.exe アーカイブ(自己解凍式アーカイブ : 27.7KB)をダウンロードし、その中の Wininet.bas(modWinInet) をプロジェクトに組み込みましょう。 これで WinInet の主要な関数はすぐに使えるようになります。
ところが、InternetReadFile() の宣言文がよくありませんね(^^;
Public Declare Function InternetReadFile Lib "wininet.dll" _ (ByVal hFile As Long, _ ByVal sBuffer As String, _ ByVal lNumBytesToRead As Long, _ lNumberOfBytesRead As Long) As Integer
第2引数 sBuffer が、String 型として宣言されてしまっています。
これではデータを文字列型変数に読み込むということになるため、
ANSI/Shift-JIS で記述されたページくらいしか読み込めません。
もし文字コードが EUC や UTF-8 で記述されたページや、その他画像ファイル等バイナリデータを読み込んだ場合には、
データの内容が破壊されてしまいます。
これでは悲惨なので、バイナリデータも受け取れるように宣言文を書き換えましょう。
戻り値が Integer 型というのもおかしいので、Long 型に変更しておきます。
ついでに、lNumberOfBytesRead も ByRef キーワードを明示しておきます。
Public Declare Function InternetReadFile Lib "wininet.dll" _ (ByVal hFile As Long, _ ByRef lpBuffer As Any, _ ByVal lNumBytesToRead As Long, _ ByRef lNumberOfBytesRead As Long) As Long |
これで、引数 lpBuffer にバイト型配列の要素を指定※1することにより、
バイナリデータの読み込みも可能になります。
※1 実際に渡されるのは、実は「ポインタ」値です。
ポインタについては、一冊の本が出てるほど解説がめんどくさいものなので、またの機会に(^^;
この modWinInet ですが、他にも各所不適当な部分が散見されますので、 実際に使用される際は上記の参考ページの情報などを元に改良などを行った方が良いと思われます。 まあ間違いだらけの Win32api.txt よりはましかもしれません(^^;
InternetReadFile() の宣言文を書き換えたら、 次に以下のようなオブジェクト名のコントロールをフォーム上に配置して下さい。
txtUrl - テキストボックス txtProxy - テキストボックス txtRecvData - テキストボックス(MultiLine = True) cmdGetInetData - コマンドボタン
あとは以下のようなコードをフォーム内に記述して下さい。 あくまでもサンプルですので、「こうした方がいい」なんてメールはやめて下さい(笑)
Option Explicit Private Const USER_AGENT = "WinInet Test" 'User_agentヘッダ(任意) 'InternetReadFile で一度に読み込むサイズ Private Const WI_READ_READSIZE = 1024 'データを受け取るバッファサイズの初期値 '必ず WI_READ_READSIZE 以上のサイズを指定して下さい Private Const WI_INITBUFSIZE = 32767 '----- GetHttpData ----- 'HTTP上のデータを取得します。 ' '引数 strUrl ' データを取得したいHTTPのアドレス(URL)を指定します。 ' '引数 bytRecvData() ' 受信したデータを格納するバッファを、Byte型配列で指定します。 ' ここに実際に受信したデータが格納されます。 ' '引数 strProxy ' 省略可能です。Proxyサーバーを経由してデータを送受信したい場合、 ' ここに "proxy.hoge.co.jp:8080" のような型式で指定します。 ' 省略または "" を渡した場合、レジストリに登録されている ' アクセス方法で送受信します。 ' '戻り値 ' 成功した場合、読み込んだデータの総サイズが返ります。 ' 失敗した場合、0 が返ります。 ' Private Function GetHttpData _ (ByVal strUrl As String, _ ByRef bytRecvData() As Byte, _ Optional ByVal strProxy As String) As Long Dim lngInetHandle As Long 'インターネットハンドルを格納 Dim lngUrlHandle As Long 'URLハンドルを格納 Dim lngArraySize As Long 'データを受け取るバッファ bytRecvData のサイズ Dim lngRet As Long 'InternetReadFile の戻り値を格納 Dim lngTotalRead As Long '受信したデータの総サイズ 兼 バッファへのポインタ Dim lngReadSize As Long '受信したデータのサイズ If Len(strUrl) = 0 Then Exit Function '経由するProxyサーバーが指定されている場合 If Len(strProxy) Then 'インターネットハンドルを作成 lngInetHandle = InternetOpen(USER_AGENT, _ INTERNET_OPEN_TYPE_PROXY, _ strProxy, _ vbNullString, _ 0) '経由するProxyサーバーが指定されていない場合 Else 'インターネットハンドルを作成 lngInetHandle = InternetOpen(USER_AGENT, _ INTERNET_OPEN_TYPE_PRECONFIG, _ vbNullString, _ vbNullString, _ 0) End If If lngInetHandle = 0 Then Exit Function '失敗したら関数を抜ける 'URLハンドルを作成 lngUrlHandle = InternetOpenUrl(lngInetHandle, _ strUrl, _ vbNullString, _ 0, _ INTERNET_FLAG_RELOAD, _ 0) If lngUrlHandle = 0 Then GoTo CloseInetHandle '失敗したら CloseInetHandle に飛ぶ lngArraySize = WI_INITBUFSIZE - 1 ReDim bytRecvData(lngArraySize) 'バッファの初期サイズを確保する Do '次回受信時、バッファのサイズをオーバーしてしまう危険性がある場合 If (lngTotalRead + WI_READ_READSIZE) > lngArraySize Then 'バッファサイズを WI_INITBUFSIZE バイト増やす lngArraySize = lngArraySize + WI_INITBUFSIZE ReDim Preserve bytRecvData(lngArraySize - 1) End If 'インターネット上のデータを読み込む lngRet = InternetReadFile(lngUrlHandle, _ bytRecvData(lngTotalRead), _ WI_READ_READSIZE, _ lngReadSize) lngTotalRead = lngTotalRead + lngReadSize '読み込んだ総サイズを計算 '受信サイズが0、または読み込み失敗の場合、ループを抜ける If (lngReadSize = 0) Or (lngRet = 0) Then Exit Do Loop If lngTotalRead Then '実際にデータが読み込まれた場合 '配列サイズを実サイズに削る ReDim Preserve bytRecvData(lngTotalRead - 1) GetHttpData = lngTotalRead '読み込んだバイト数を返す Else Erase bytRecvData '総受信サイズが 0 の場合、配列を消去 End If Call InternetCloseHandle(lngUrlHandle) 'URLハンドルを閉じる CloseInetHandle: Call InternetCloseHandle(lngInetHandle) 'インターネットハンドルを閉じる End Function Private Sub cmdGetInetData_Click() Dim lngSize As Long 'GetHttpData()の戻り値(受信サイズ)を格納する Dim bytArray() As Byte 'データを受け取るバッファ(Byte型配列) 'txtUrl で指定したURLのデータを取得 lngSize = GetHttpData(txtUrl.Text, bytArray(), txtProxy.Text) If lngSize Then '成功したら、バッファのデータをUnicodeに変換し txtRecvData に表示 txtRecvData.Text = StrConv(bytArray, vbUnicode) End If Erase bytArray End Sub |
べたテキスト版 :
gethttp.txt (4.50KB)
※ 右クリックで「対象をファイルに保存(A)」して下さい
まずダイヤルアップ接続してインターネットができる環境にしてから、
テキストボックス txtUrl に "http://www.vector.co.jp/" などのURLを入力し、
コマンドボタン cmdGetInetData をクリックしてみて下さい。
すると、テキストボックス txtRecvData にHTMLファイルのソースが読み込まれます※1, 2。
※1 日本語文字コードが Shift-JIS 以外のページは正常に表示されません。
※2 改行コードが CR または LF の場合、正常に改行されません。
このサンプルでは受信したデータを Unicode に変換してテキストボックスに出力していますが、
バッファのデータを Put ステートメントで書き出してやれば、バイナリファイルとしても保存できますね(^^)
また文字コードが EUC, JIS で記述されたページも、NKF32.DLL などで変換してやれば読めます。
参考 : NKF32.DLL で文字コード変換
参考 : 文字列を UTF-8 に変換
宣言文 | |
---|---|
Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" _ (ByVal sAgent As String, _ ByVal lAccessType As Long, _ ByVal sProxyName As String, _ ByVal sProxyBypass As String, _ ByVal lFlags As Long) As Long |
|
戻り値 | |
この関数が成功した場合、インターネットのハンドルが返ります。 失敗した場合は 0 が返ります。 | |
引数 | 説明 |
sAgent | 任意。ここに指定した名前で User_agent ヘッダが送られる。 |
lAccessType | インターネットへのアクセス方法を指定。INTERNET_OPEN_TYPE_DIRECT など。(下記定数表参照) |
sProxyName | プロキシサーバーを使用する場合、"proxy.hoge.co.jp:8080" のように指定。 |
sProxyBypass | イントラネット内など、プロキシを経由させたくないコンテンツがある場合はここにそのホストを指定。 |
lFlags | 下記定数表参照。 |
lAccessType の定数 | |
Const INTERNET_OPEN_TYPE_PRECONFIG = 0 |
レジストリに記録されている方法(IE と共通?)でアクセスする。 |
Const INTERNET_OPEN_TYPE_DIRECT = 1 |
プロキシを経由せずにアクセスする。 |
Const INTERNET_OPEN_TYPE_PROXY = 3 |
sProxyName で指定したプロキシ経由でアクセスする。 |
lFlags の定数 | |
Const INTERNET_FLAG_ASYNC = &H10000000 |
InternetSetStatusCallback() を使用した非同期処理を行う場合に指定する。 |
Const INTERNET_FLAG_FROM_CACHE = &H1000000 |
インターネットからデータを取得せず、キャッシュからのみデータを取得する。 |
Const INTERNET_FLAG_OFFLINE = &H1000000 |
同上(^^; |
宣言文 | |
---|---|
Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" _ (ByVal hInternetSession As Long, _ ByVal sUrl As String, _ ByVal sHeaders As String, _ ByVal lHeadersLength As Long, _ ByVal lFlags As Long, _ ByVal lContext As Long) As Long | |
戻り値 | |
この関数が成功した場合、URLのハンドルが返ります。 失敗した場合は 0 が返ります。 | |
引数 | 説明 |
hInternetSession | InternetOpen() で返されたハンドルを指定 |
sUrl | HTTP の場合、http:// から始まる、HTTP プロトコルの URL を指定。 |
sHeaders | HTTP サーバーに送信するヘッダを指定。 |
lHeadersLength | sHeaders の文字数。もし sHeaders が NULL でなかった場合に -1 を指定すると、 勝手に文字数を計算してくれる。 |
lFlags | どのようにオープンするかを示す。(定数表参照) |
lContext | InternetSetStatusCallback() 使用時に、コールバック関数の第二引数に渡す任意の値を指定する。 |
lFlags の定数 | |
Const INTERNET_FLAG_RELOAD = &H80000000 |
キャッシュを使わずに、サーバーからデータを取得する。 |
Const INTERNET_FLAG_NO_CACHE_WRITE = &H4000000 |
キャッシュにデータを書き込まない。 |
Const INTERNET_FLAG_NO_AUTO_REDIRECT = &H200000 |
自動的にリダイレクト(Location ヘッダなど)しない。 |
Const INTERNET_FLAG_PRAGMA_NOCACHE = &H100 |
プロキシサーバーのキャッシュを使用しない。 |
宣言文 | |
---|---|
Declare Function InternetReadFile Lib "wininet.dll" _ (ByVal hFile As Long, _ ByRef lpBuffer As Any, _ ByVal lNumBytesToRead As Long, _ ByRef lNumberOfBytesRead As Long) As Long | |
戻り値 | |
この関数が成功した場合、1 が返ります。 失敗した場合は 0 が返ります。 ただし、IE4 の時はファイルの読込が終了しても 1 のままでしたので注意が必要です。 | |
引数 | 説明 |
hFile | InternetOpenUrl() などで返されたハンドルを指定。 |
lpBuffer | 読み込み結果を受け取るバッファを指定。 |
lNumBytesToRead | 一度に読み込むバイト数を指定。 |
lNumberOfBytesRead | 実際に読み込まれたバイト数がここに格納される。読み込みが終了したら 0 が格納される。 |
宣言文 | |
---|---|
Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer | |
戻り値 | |
この関数が成功した場合、1 が返ります。 失敗した場合は 0 が返ります。 | |
引数 | 説明 |
hInet | InternetOpen(), InternetOpenUrl() などで開いたハンドルを指定。そのハンドルを閉じる。 |
基本的に WinInet は同期的な処理を行います。つまり接続→データの取得が終了するまで、
アプリケーションがフリーズしてしまうことになります。
また、サーバーからの応答がなかった場合の、WinInet のデフォルトタイムアウト時間は 300 秒だそうです。
いくら何でも 5 分間フリーズしてしまうのは悲しすぎるので、
自分でタイムアウト時間を設定しましょう。
宣言文 | |
---|---|
Declare Function InternetSetOption Lib "wininet.dll" Alias "InternetSetOptionA" _ (ByVal hInternet As Long, _ ByVal lOption As Long, _ ByRef sBuffer As Any, _ ByVal lBufferLength As Long) As Integer | |
戻り値 | |
この関数が成功した場合、1 が返ります。 失敗した場合は 0 が返ります。 | |
引数 | 説明 |
hInternet | HTTP プロトコルの場合、InternetOpen() で取得したインターネットのハンドルを指定。 |
lOption | 設定するオプションをあらわすフラグを設定。(定数表参照) |
sBuffer | lOption で指定したオプションの値が入っているバッファを指定。 |
lBufferLength | sBuffer のサイズ。 |
lOption の定数 | |
Const INTERNET_OPTION_CONNECT_TIMEOUT = 2 |
接続タイムアウトを指定するためのフラグ。値は sBuffer にミリ秒単位で指定。 |
Const INTERNET_OPTION_RECEIVE_TIMEOUT = 6 |
受信タイムアウトを指定するためのフラグ。値は sBuffer にミリ秒単位で指定。 |
Const INTERNET_OPTION_SEND_TIMEOUT = 5 |
タイムアウトを指定するためのフラグ。値は sBuffer にミリ秒単位で指定。 |
Const INTERNET_OPTION_CONNECT_RETRIES = 3 |
接続リトライ回数を指定するためのフラグ。値は sBuffer に指定。(デフォルトでは 5 回) |
InternetOpen() でインターネットのハンドルを取得した後、 そのハンドルを使用して InternetSetOption() を呼び出します。
lngConnectTimeOut = 15 * 1000 '接続タイムアウト15秒 lngReceiveTimeOut = 30 * 1000 '受信タイムアウト30秒 Call InternetSetOption(lngInetHandle, INTERNET_OPTION_CONNECT_TIMEOUT, lngConnectTimeOut, LenB(lngConnectTimeOut)) Call InternetSetOption(lngInetHandle, INTERNET_OPTION_RECEIVE_TIMEOUT, lngReceiveTimeOut, LenB(lngReceiveTimeOut)) |
ちなみに非同期で処理を行う方法はあることはあるのですが、けっこう難しいです。 Microsoft に参考資料があります。関係ありそうな資料のリンクを集めてみました。一番下の機械翻訳タイトルは笑えますが(^^;
[INFO] Visual Basic 内で WinInet API を非同期的に使用する
サンプル非同期に WinInet API と呼び出す 使用 AsyncHTTP の方法
BUG: バイト読み取るは、非同期の InternetReadFile に設定されていません。
一番上のリンク先に、
ここで注意する必要があるのは、Visual Basic 内で非同期の WinInet API を実現するのに必要な一連の技術は、WinInet を非同期モードで使用して C/C++ アプリケーションを記述するのに必要な技術に匹敵するということです。このことからも、Visual Basic で WinInet API を非同期的に使用することは望ましい方法ではありません。
なんて少し挑発的な(笑)記述があったので無理やりコーディングしてみたのですが、一応動作させることは出来ました。
ちなみに VC++ でも試しに記述してみたのですが、なぜかそちらは動きませんでした(爆)。
しかし正直、VB の非同期操作についてよく解っていないため、
処理待ちに空ループを使用していたりして動作が著しく不安定で、
まだ実用化レベルには至っていないので非公開とさせていただきます。
ソースを公開することは無理だと思いますが、万年初心者の私でも何とか作れたので(笑)、
コールバック関数などの処理に詳しい人にとってはそれほど難しくはないと思います。がんばってください(^^;
このページではまだ触れていませんが、InternetConnect() で HTTP 接続する場合は URL を分割して引数に渡す必要があります。
具体的には、"http://www.geocities.co.jp/SilkRoad/4511/" に接続したい場合は、
スキーム名 | : | "http" |
ホスト名 | : | "www.geocities.co.jp" |
パス | : | "/SilkRoad/4511/" |
Option Explicit Public Declare Function InternetCrackUrl Lib "wininet.dll" Alias "InternetCrackUrlA" _ (ByVal lpszUrl As String, _ ByVal dwUrlLength As Long, _ ByVal dwFlags As Long, _ ByRef lpUrlComponents As URL_COMPONENTS) As Long Public Const ICU_ESCAPE = &H80000000 '(un)escape URL characters Public Const ICU_DECODE = &H10000000 'use internal username & password '----- URL_COMPONENTS 構造体 ----- Public Type URL_COMPONENTS dwStructSize As Long 'URL_COMPONENTS 構造体のサイズ(60) lpszScheme As String 'スキーム("http", "ftp" など) dwSchemeLength As Long 'lpszScheme のサイズ nScheme As Long 'スキームの種類。INTERNET_SCHEME 定数参照 lpszHostName As String 'ホスト名("www.yahoo.co.jp" など) dwHostNameLength As Long 'lpszHostName のサイズ nPort As Long 'ポート番号 lpszUserName As String 'ユーザー名 dwUserNameLength As Long 'lpszUserName のサイズ lpszPassword As String 'パスワード dwPasswordLength As Long 'lpszPassword のサイズ lpszUrlPath As String 'パス("/index.html" など) dwUrlPathLength As Long 'lpszUrlPath のサイズ lpszExtraInfo As String 'pointer to extra information (e.g. ?foo or #foo) dwExtraInfoLength As Long 'lpszExtraInfo のサイズ End Type Public Const INTERNET_SCHEME_PARTIAL = -2 Public Const INTERNET_SCHEME_UNKNOWN = -1 Public Const INTERNET_SCHEME_DEFAULT = 0 Public Const INTERNET_SCHEME_FTP = 1 Public Const INTERNET_SCHEME_GOPHER = 2 Public Const INTERNET_SCHEME_HTTP = 3 Public Const INTERNET_SCHEME_HTTPS = 4 Public Const INTERNET_SCHEME_FILE = 5 Public Const INTERNET_SCHEME_NEWS = 6 Public Const INTERNET_SCHEME_MAILTO = 7 Public Const INTERNET_SCHEME_SOCKS = 8 Public Const INTERNET_SCHEME_FIRST = INTERNET_SCHEME_FTP Public Const INTERNET_SCHEME_LAST = INTERNET_SCHEME_SOCKS Private Const INTERNET_MAX_HOST_NAME_LENGTH = 256 'ホスト名の最大サイズ。以下同上(^^; Private Const INTERNET_MAX_USER_NAME_LENGTH = 128 Private Const INTERNET_MAX_PASSWORD_LENGTH = 128 Private Const INTERNET_MAX_PORT_NUMBER_LENGTH = 5 Private Const INTERNET_MAX_PORT_NUMBER_VALUE = 65535 Private Const INTERNET_MAX_PATH_LENGTH = 2048 Private Const INTERNET_MAX_SCHEME_LENGTH = 32 Private Const INTERNET_MAX_URL_LENGTH = INTERNET_MAX_SCHEME_LENGTH + 3 + INTERNET_MAX_PATH_LENGTH Private Const INTERNET_MAX_EXTRAINFO_LENGTH = 512 'wininet.h にはありませんが自分で追加しました '----- GetUrlComponents 関数 Version 1.00 ----- 'InternetCrackUrl() を呼び出し URL を分解します。 ' '引数 strUrl ' 分解の対象となる URL 文字列式を指定します。 ' '引数 ucUrlComponents ' 分解された URL の各要素を格納する URL_COMPONENTS 構造体を指定します。 ' 関数が成功した場合、ucUrlComponents の各メンバに情報が格納されます。 ' '引数 lngFlags ' 省略可能です。URL の分解方法を指定します。この引数を省略すると、 ' ICU_ESCAPE の値が使用されます。 ' '戻り値 ' 関数が成功した場合、True を返します。 ' '※ 注意事項 ※ ' 'この関数では、URL 文字列に全角文字(Shift-JIS で 2 バイトになる文字)が '使用された場合のことは考慮しておりません。もし使用された場合、 'ucUrlComponents の文字列型メンバに格納される文字列が不正なものに 'なってしまいます。もし全角文字が使用される可能性がある場合は、 '後半の Left$ 関数を、拙作の TrimNull 関数などに置き換えるなどして '変更した上でお使い下さい。 ' 'TrimNull - http://www.geocities.co.jp/SilkRoad/4511/vb/kowaza.htm#trimnull ' Public Function GetUrlComponents _ (ByRef strUrl As String, _ ByRef ucUrlComponents As URL_COMPONENTS, _ Optional ByVal lngFlags As Long = ICU_ESCAPE) As Boolean If Len(strUrl) = 0 Then Exit Function 'URL 文字列が 0 文字の場合、関数を抜ける With ucUrlComponents 'URL_COMPONENTS 構造体の各メンバの情報を設定 .dwStructSize = LenB(ucUrlComponents) 'URL_COMPONENTS のサイズを設定(60 バイト) .dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH 'dwSchemeLength を INTERNET_MAX_SCHEME_LENGTH に設定 .lpszScheme = String$(.dwSchemeLength, vbNullChar) 'lpszScheme を dwSchemeLength 個の NULL で埋める .dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH '以下同上(^^; .lpszHostName = String$(.dwHostNameLength, vbNullChar) .dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH .lpszUserName = String$(.dwUserNameLength, vbNullChar) .dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH .lpszPassword = String$(.dwPasswordLength, vbNullChar) .dwUrlPathLength = INTERNET_MAX_PATH_LENGTH .lpszUrlPath = String$(.dwUrlPathLength, vbNullChar) .dwExtraInfoLength = INTERNET_MAX_EXTRAINFO_LENGTH .lpszExtraInfo = String$(.dwExtraInfoLength, vbNullChar) End With If InternetCrackUrl(strUrl, Len(strUrl), lngFlags, ucUrlComponents) Then 'InternetCrackUrl() が成功した場合 With ucUrlComponents .lpszScheme = Left$(.lpszScheme, .dwSchemeLength) 'lpszScheme の余分な部分を削り再格納 .lpszHostName = Left$(.lpszHostName, .dwHostNameLength) '以下同上(^^;; .lpszUserName = Left$(.lpszUserName, .dwUserNameLength) .lpszPassword = Left$(.lpszPassword, .dwPasswordLength) .lpszUrlPath = Left$(.lpszUrlPath, .dwUrlPathLength) .lpszExtraInfo = Left$(.lpszExtraInfo, .dwExtraInfoLength) End With GetUrlComponents = True 'True を返す End If End Function |
なんとなく禍々しくも思えるソースコードです(爆)。なんで URL を分割するだけでここまでやらなきゃいけないんでしょうか?(^^;