tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトルIEの自動ログイン
記事No16107
投稿日: 2015/04/10(Fri) 16:02
投稿者はなまるき
連投失礼します。

DB内にあるサイトのURL,LoginID,Passwordを登録しておき、
そのサイトをリストから選択すれば自動でログインできる
ものを作成しています。

IE上のTextBoxに値を入れるコードは以下になります。

Public Sub IEInputTextbox(ByRef objIE As Object, str As String, Value As String)
    
    On Error Resume Next
    
    Dim objInput As Object
    Dim str1 As String
    
    For Each objInput In objIE.document.getElementsByTagName("Input")
        If InStr(1, objInput.outerHTML, str, vbTextCompare) <> 0 Then
            objInput.Value = Value
            Exit For
        End If
    Next

End Sub


あるサイトの結果として
InputタグのouterHTML:objInput.outerHTML <input name="pass" class="inputText login" type="password">
検索要素str     :"pass"
なのですが、instr関数の戻り値が0になります。

これはなぜでしょうか?

TextBoxを特定するのにおいて、サイトによりnameを使うのかIDを使うのか
まちまちであるためouterHTMLという大枠での検索にしています。

[ツリー表示へ]
タイトルRe: IEの自動ログイン
記事No16108
投稿日: 2015/04/10(Fri) 16:25
投稿者はなまるき
補足です

  Public Sub IEInputTextbox(ByRef objIE As Object, str As String, Value As String)
     ’str="pass"です
     On Error Resume Next
    
     Dim objInput As Object
     Dim str1 As String
    
     For Each objInput In objIE.document.getElementsByTagName("Input")
         If InStr(1, objInput.outerHTML, str, vbTextCompare) <> 0 Then
             objInput.Value = Value
             Exit For
         End If
     Next

  End Sub


InputタグのouterHTML
:objInput.outerHTML <input name="pass" class="inputText login" type="password">

検索要素str     :"pass"

において次のような実験をしてみました。

@上記のまま
InStr(1, objInput.outerHTML, str, vbTextCompare) 戻り値:0

A明示的に値を入れなおす
str="pass"
InStr(1, objInput.outerHTML, str, vbTextCompare) 戻り値:>0

B変数に変数を入れてみる
Dim str1 as string
str1=str
InStr(1, objInput.outerHTML, str1, vbTextCompare) 戻り値:=0


タだしところが、strに”inputText login”を渡す場合は戻り値は>0となります。


元々strにはstring型の変数を渡しています。

dim objIE as object
dim rs as adodb.recordset
dim str as string
dim v as string

set objIE=OpenIE()・・・省略
set rs=Createreocordset(strSQL)・・・省略
str=rs.fields("PasswordElement")
v=rs.fields("Value")

ret=IEInputTextbox(objIE,str,v)

[ツリー表示へ]
タイトルRe^2: IEの自動ログイン
記事No16113
投稿日: 2015/04/10(Fri) 23:55
投稿者魔界の仮面弁士
> A明示的に値を入れなおす
> str="pass"
> InStr(1, objInput.outerHTML, str, vbTextCompare) 戻り値:>0

そういう結果になるのだとすれば、outerHTML 側よりも
str の内容を疑った方が良さそうですね。

 Debug.Print Len("pass"), Len(str)   '共に 4 を返すか?
 Debug.Print InStr(1, "pass", str, vbBinaryCompare)   '0 になるか?


> v=rs.fields("Value")
これは本来、
 v = rs.Fields("Value").Value
もしくは
 v = rs.Collect("Value")
と記述されるべきかと思います。

ごくごく希なケースではあるのですが、特定の環境、たとえば一部の ODBC ドライバですとか
サードパーティ製 Oracle プロバイダ等においては、Value プロパティを省略してしまうと、
正しい値が得られないというケースが存在します。

たとえば VB 非標準の Variant 値を返してしまうケースとか、
vbNullString が含まれている時にクラッシュするものとか、
データ末尾に不可読文字がゴミが含まれてしまう(含まれない事もある)こととか。

# ADO や DAO だと報告件数が少ないですけど、oo4o だと有名な問題だったり。
# http://otn.oracle.co.jp/forum/message.jspa?messageID=28012514

[ツリー表示へ]
タイトルRe: IEの自動ログイン
記事No16110
投稿日: 2015/04/10(Fri) 18:36
投稿者魔界の仮面弁士
> DB内にあるサイトのURL,LoginID,Passwordを登録しておき、
> そのサイトをリストから選択すれば自動でログインできる
> ものを作成しています。

それらのサイトは、どのタイプの認証方法を採用しているのでしょうか?

BASIC 認証のサイトなら、Navigate2 の引数で Authorization ヘッダーを送出することになりますね。

フォーム認証の場合は、提示されているような DOM 操作で行うことになりますが、
その場合、相手先のページの正確な HTML 構造を知る必要がありそうです。


>  Public Sub IEInputTextbox(ByRef objIE As Object, str As String, Value As String)
最初の引数だけ、あえて ByRef 指定にしたのは何故でしょうか?

それと、VB には「Str 関数」が存在しますので、str という変数名は避けた方が良いかと思います。
(予約語では無いので、str という名前が使えないわけでは無いですが…)


> InputタグのouterHTML:objInput.outerHTML <input name="pass" class="inputText login" type="password">
> 検索要素str     :"pass"
> なのですが、instr関数の戻り値が0になります。

たとえば、
 Dim outerHTML As String
 'outerHTML = objInput.outerHTML
 outerHTML = "<input name=""pass"" class=""inputText login"" type=""password"">"
 idx = InStr(1, outerHTML, "pass", vbTextCompare)
のように、HTML 文字列をオンコードで書いてみた場合も InStr が 0 を返しますか?

もし、上記であれば 0 を返さないようであれば、そもそも想定したものとは
異なる文字列を InStr に渡してしまっているのだと思います。
たとえばページ遷移や JavaScript の動作タイミングなどの都合で、
outerHTML から想定とは異なる文字列が渡されていたりはしませんか?

[ツリー表示へ]
タイトルRe^2: IEの自動ログイン
記事No16112
投稿日: 2015/04/10(Fri) 22:12
投稿者はなまるき
> フォーム認証の場合は、提示されているような DOM 操作で行うことになりますが、
> その場合、相手先のページの正確な HTML 構造を知る必要がありそうです。

フォーム認証です

>
> >  Public Sub IEInputTextbox(ByRef objIE As Object, str As String, Value As String)
> 最初の引数だけ、あえて ByRef 指定にしたのは何故でしょうか?

引数の文字を変えているうちに消えたものと推察しますが意図的ではありません。


>
>  Dim outerHTML As String
>  'outerHTML = objInput.outerHTML
>  outerHTML = "<input name=""pass"" class=""inputText login"" type=""password"">"
>  idx = InStr(1, outerHTML, "pass", vbTextCompare)
> のように、HTML 文字列をオンコードで書いてみた場合も InStr が 0 を返しますか?
返しません。
補足に記載していますが、outerHTMLはそのままで、strが"pass"だと0を返し、strが"inputText login"
だと>0(正確な値は割愛しています)を返します。
元々はstrはstrElementという引数を使用していました。
結果はstrの時と同様です。
strの中の文字列を扱っているというよりかはstrという入れ物を扱っている印象を受けました。

[ツリー表示へ]
タイトルRe^2: IEの自動ログイン
記事No16116
投稿日: 2015/04/11(Sat) 09:00
投稿者はなまるき

> たとえばページ遷移や JavaScript の動作タイミングなどの都合で、
> outerHTML から想定とは異なる文字列が渡されていたりはしませんか?

1行ずつステップインしながら値をデバッグウィンドウで確認しているので
それは無いと思います。

[ツリー表示へ]
タイトルRe^3: IEの自動ログイン
記事No16117
投稿日: 2015/04/11(Sat) 17:19
投稿者魔界の仮面弁士
> 1行ずつステップインしながら値をデバッグウィンドウで確認しているので
> それは無いと思います。

何にせよ、InStr の結果が異なるという事は、InStr 関数に渡されているのが
「想定しているものとは別の文字列」になってしまっているわけですから、
デバッグではそれが何なのかを突き止める必要がありますね。


不可読文字が混入している可能性なども考慮し、str, outerHTML のそれぞれで

 '------------
 Debug.Print "文字数 ="; Len(S), "ポインタ ="; Hex(StrPtr(S))
 For L = 1 To Len(s)
  Debug.Print Right("0000" & Hex(AscW(Mid(s, L, 1))), 4); " ";
 Next L
 Debug.Print Tab(1); S
 '------------

を実行してみてください。

たとえば str = "pass" の場合は、上記処理によって
文字数 = 4    ポインタ =何某
0070 0061 0073 0073
pass
を得る事ができます。

「Recordset から受取った文字列」をそのまま渡した場合と、
「リテラルで埋め込んだ文字列」を固定的に渡した場合とで、
上記で(ポインタ以外の箇所が)異なる結果になっていませんか?

[ツリー表示へ]
タイトル解決しました
記事No16127
投稿日: 2015/04/13(Mon) 22:58
投稿者はなまるき
str="pass" の結果

【固定的に渡した値』
文字数 = 4    ポインタ =833D974
0070 0061 0073 0073
pass

【Recordsetからの値】
文字数 = 6    ポインタ =833E3EC
0070 0061 0073 0073 000D 000A
pass

outerHTMLはどちらも同じでした


DataBaseに登録時にキャリッジリターンが入っていたようです。。。
IEのソースをこぴぺしたつもりでしたが、そうでしたか。

ありがとうございました。

[ツリー表示へ]