Page 1 of 1

opening a webpage and filling fields, possible?

Posted: Sat Apr 02, 2011 1:58 pm
by gabriel
Hello:
is it possible to open a webpage and filling some fields (like username and password etc.....) automatically using PB?
also is it possible to emulate cliking on buttons to go to another page?

Thanks

Re: opening a webpage and filling fields, possible?

Posted: Sat Apr 02, 2011 7:49 pm
by luis
This is a crude example based on IHTMLWindow2 (see http://msdn.microsoft.com/en-us/library ... 85%29.aspx) and suitable for an embedded window inside your application.

It would require a lot of work to make it robust, but it can get you started.

Basically you use javascript exactly as you would do in a normal html page.

To click a button, just move around using #VK_DOWN etc and then press #VK_RETURN.

Code: Select all

Enumeration ; windows
 #WIN_MAIN
EndEnumeration

Enumeration ; gadgets
 #WEB_MAIN
EndEnumeration


#PUSH_CTRL     = 0
#PUSH_ALT      = 1
#PUSH_SHIFT    = 2

#URL_BASE$ = "http://www.purebasic.com"
#URL_START$ = #URL_BASE$ + "/securedownload/Login.php?language="

DataSection

  IID_IHTMLDocument: ; {626FC520-A41E-11CF-A731-00A0C9082637}
    Data.l $626FC520
    Data.w $A41E, $11CF
    Data.b $A7, $31, $00, $A0, $C9, $08, $26, $37

  IID_IHTMLDocument2: ; {332C4425-26CB-11D0-B483-00C04FD90119}
    Data.l $332C4425
    Data.w $26CB, $11D0
    Data.b $B4, $83, $00, $C0, $4F, $D9, $01, $19

  IID_IHTMLDocument3: ; {3050F485-98B5-11CF-BB82-00AA00BDCE0B}
    Data.l $3050F485
    Data.w $98B5,$11CF
    Data.b $BB,$82,$00,$AA,$00,$BD,$CE,$0B

  IID_IHTMLDocument4: ; {3050F69A-98B5-11CF-BB82-00AA00BDCE0B}
    Data.l $3050F69A
    Data.w $98B5, $11CF
    Data.b $BB, $82, $00, $AA, $00, $BD, $CE, $0B

  IID_IHTMLDocument5: ; {3050F80C-98B5-11CF-BB82-00AA00BDCE0B}
    Data.l $3050F80C
    Data.w $98B5, $11CF
    Data.b $BB, $82, $00, $AA, $00, $BD, $CE, $0B

  IID_IHTMLElement: ; {3050F1FF-98B5-11CF-BB82-00AA00BDCE0B}
    Data.l $3050F1FF
    Data.w $98B5, $11CF
    Data.b $BB, $82, $00, $AA, $00, $BD, $CE, $0B
    
EndDataSection


Macro KEY_DOWN (iKey)
  keybd_event_ (iKey, 0, 0, 0)
EndMacro    

Macro KEY_UP (iKey)
  keybd_event_(iKey, 0, #KEYEVENTF_KEYUP, 0)
EndMacro    

Procedure.i WebGadget_GetHTMLDocument2 (nGadget)
 Protected oBrowser.IWebBrowser2 = GetWindowLongPtr_(GadgetID(nGadget), #GWL_USERDATA)
 Protected oDocumentDispatch.IDispatch
 Protected oHTMLDocument.IHTMLDocument2
 Protected iBusy
     
 Repeat
    While WindowEvent(): Delay(0): Wend    
    oBrowser\get_Busy(@iBusy): Delay(10)        
 Until iBusy = #VARIANT_FALSE

 If oBrowser
    If oBrowser\get_document(@oDocumentDispatch) = #S_OK 
        If oDocumentDispatch\QueryInterface(?IID_IHTMLDocument2, @oHTMLDocument) = #S_OK
            oDocumentDispatch\Release()
        EndIf
    EndIf
 EndIf
             
 ProcedureReturn oHTMLDocument 
EndProcedure

Procedure.i WebGadget_GetHTMLDocumentParent (nGadget)
 Protected oHTMLDocument.IHTMLDocument2 = WebGadget_GetHTMLDocument2 (nGadget)
 Protected oWindow.IHTMLWindow2
    
 If oHTMLDocument
    oHTMLDocument\get_parentWindow(@oWindow)
 EndIf
 
 oHTMLDocument\Release()  

 ProcedureReturn oWindow
EndProcedure 

Procedure WebGadget_SetFocus (nGadget)
 Protected oWindow.IHTMLWindow2 = WebGadget_GetHTMLDocumentParent (nGadget)
    
 If oWindow    
    oWindow\focus()
    oWindow\Release()
 EndIf
EndProcedure 

Procedure WebGadget_ExecScript (nGadget, sScriptCode.s, sScriptLanguage.s = "JavaScript")    
 Protected oWindow.IHTMLWindow2 = WebGadget_GetHTMLDocumentParent (nGadget)
 Protected tVariant.VARIANT

 If oWindow
    oWindow\execScript (sScriptCode, sScriptLanguage, @tVariant)
    oWindow\Release()
 EndIf    
EndProcedure 

Procedure WebGadget_SetFocusByName (nGadget, sFieldName.s)
 Protected sScript.s
 
 sScript = "var elements = document.getElementsByName('"+ sFieldName + "');"
 sScript + "for (var i = 0; i < elements.length; ++i)"
 sScript + "{"
 sScript + "if (elements[i].tagName.toLowerCase() == 'input')"
 sScript + "{"
 sScript + "elements[i].focus();"
 sScript + "break;"
 sScript + "}"
 sScript + "}"

 WebGadget_ExecScript (nGadget, sScript)
EndProcedure 

Procedure PushKey (iKey, iMod = 0)
 
 If iMod & #PUSH_CTRL
    KEY_DOWN (#VK_CONTROL) 
 EndIf
  
 If iMod & #PUSH_SHIFT
    KEY_DOWN (#VK_SHIFT) 
 EndIf
  
 If iMod & #PUSH_ALT
    KEY_DOWN (#VK_MENU) 
 EndIf
   
 If iKey
    KEY_DOWN (iKey)
    KEY_UP (iKey) 
 EndIf
 
 If iMod & #PUSH_ALT
    KEY_UP (#VK_MENU) 
 EndIf
  
 If iMod & #PUSH_SHIFT
    KEY_UP (#VK_SHIFT) 
 EndIf
  
 If iMod & #PUSH_CTRL
    KEY_UP (#VK_CONTROL)
 EndIf
 
EndProcedure 

Procedure Main()

 Protected iRetVal, iEvent, iStepCount
 Protected sUrl.s
 
 iRetVal = OpenWindow(#WIN_MAIN, 10, 10, 800, 600, "WebRobot")
 
 iRetVal = WebGadget(#WEB_MAIN, 5, 5, 790, 550, #URL_START$)     
 
 Repeat
    iEvent = WaitWindowEvent()
    
    Select iEvent
        Case #PB_Event_Gadget
            Select EventGadget()                                   
                Case #WEB_MAIN
                    Select EventType()
                        Case #PB_EventType_DownloadEnd                            
                            iStepCount + 1
                            Select iStepCount
                                Case 1:
                                    WebGadget_SetFocus(#WEB_MAIN)
                                    
                                    WebGadget_SetFocusByName(#WEB_MAIN, "Login")
                                    
                                    PushKey(#VK_U)
                                    PushKey(#VK_S)
                                    PushKey(#VK_E)                                    
                                    PushKey(#VK_R)                                    

                                    WebGadget_SetFocusByName(#WEB_MAIN, "Password")

                                    PushKey(#VK_P)
                                    PushKey(#VK_A)
                                    PushKey(#VK_S)                                    
                                    PushKey(#VK_S)                                    
                                                                        
                                    PushKey(#VK_RETURN)  
                                                                       
                                Case 2:
                                    Debug "Ended."
                            EndSelect 
                    EndSelect                   
            EndSelect
    EndSelect
 
 Until iEvent = #PB_Event_CloseWindow

EndProcedure


Main()

BTW I selected the objects by name, but you can do by ID also, if they are specified in the source ...

Re: opening a webpage and filling fields, possible?

Posted: Sat Apr 02, 2011 8:04 pm
by Kwai chang caine
Very interesting code LUIS
Thanks a lot to sharing 8)

Re: opening a webpage and filling fields, possible?

Posted: Sun Apr 03, 2011 11:21 am
by gabriel
Thank you very much LUIS :D
Grazie

Re: opening a webpage and filling fields, possible?

Posted: Sun Apr 03, 2011 12:21 pm
by djes
Yeah, great example! Thank you Luis!

Re: opening a webpage and filling fields, possible?

Posted: Sun May 22, 2011 2:01 pm
by MachineCode
Nice example, but how do we make it work with any web site? I'd like to send an update to my Facebook status, for instance.

Re: opening a webpage and filling fields, possible?

Posted: Sun May 22, 2011 7:17 pm
by Nico
here is one of my codes March 7, 2008

Code: Select all

;---------------------------------------------------------------------------------- 
; Auto Login Forum 
; PureBasic Version 4.10 
; Ce code montre comment procéder pour remplir un formulaire 
; de connexion d'accès à un Forum automatiquement 
; Ce code n'est pas optimisé pour fonctionner sur des pages contenant des Frames 
;---------------------------------------------------------------------------------- 
; Fonctionnement: 
; Si l'URL de navigation correspond à un élément de la liste AutoLogin() 
; on compte le nombre de <FORM> dans la page, puis 
; pour chaque <FORM>, on comptabilise le nombre d'éléments ci dessous: 
; <INPUT> de type text 
; <INPUT> de type password 
; <INPUT> de type submit 
; Une <FORM> est considérée comme apte à recevoir les données si 
; elle comptabilise ces 3 types mais une seule fois pour chacun d'entre eux 
; et si le submit est placé à la fin de cette séquence 
; La première <FORM> qui correspond à ces critères est alors remplie des données 
; d'enregistrement et validée. 
;---------------------------------------------------------------------------------- 

Enumeration 
  #Main 
  #Web 
  #Status 
  #Panel 
  #Progress 
EndEnumeration 

Structure VARIANT_SPLIT
  StructureUnion
    Variant.VARIANT
    Split.l[4]
  EndStructureUnion
EndStructure 

Interface IHTMLElementCollection_FIXED
  QueryInterface(a,b)
  AddRef()
  Release()
  GetTypeInfoCount(a)
  GetTypeInfo(a,b,c)
  GetIDsOfNames(a,b,c,d,e)
  Invoke(a,b,c,d,e,f,g,h)
  toString(a)
  put_length(a)
  get_length(a)
  get__newEnum(a)
  item(a1,a2,a3,a4,b1,b2,b3,b4,c)
  tags(a1,a2,a3,a4,b)
EndInterface 

Interface IHTMLFormElement_Fixed
  QueryInterface(a, b)
  AddRef()
  Release()
  GetTypeInfoCount(a)
  GetTypeInfo(a, b, c)
  GetIDsOfNames(a, b, c, d, e)
  Invoke(a, b, c, d, e, f, g, h)
  put_action(a.p-bstr)
  get_action(a)
  put_dir(a.p-bstr)
  get_dir(a)
  put_encoding(a.p-bstr)
  get_encoding(a)
  put_method(a.p-bstr)
  get_method(a)
  get_elements(a)
  put_target(a.p-bstr)
  get_target(a)
  put_name(a.p-bstr)
  get_name(a)
  put_onsubmit(a.p-Variant)
  get_onsubmit(a)
  put_onreset(a.p-Variant)
  get_onreset(a)
  submit()
  reset()
  put_length(a)
  get_length(a)
  get__newEnum(a)
  item(a1,a2,a3,a4,b1,b2,b3,b4,c)
  tags(a.p-Variant, b)
EndInterface 

Structure Login
  Url.s
  Nom.s
  Password.s
EndStructure 

Global NewList AutoLogin.Login()
Global UserName.s,Password.s,WebBrowser.IWebBrowser2

AddElement (AutoLogin())
AutoLogin()\Url= "http://www.purebasic.fr/english/ucp.php?mode=login" 
AutoLogin()\Nom= " ;<--- A remplir 
AutoLogin()\Password= ";<--- A remplir 

Procedure ProcessInputElement(*pFormElement.IHTMLFormElement_Fixed, Valid.l)
  Protected *pElemDisp.IDispatch = #Null 
  Protected *pInputElement.IHTMLInputElement = #Null 
  Protected *pElement.IHTMLElement= #Null 
  Protected a.l,Number.l,varIndex.VARIANT_SPLIT
  Protected NbText.l,NbPassword.l,NbSubmit.l
  Protected hr.l,Submit.l
  
  varIndex\Variant\vt = #VT_I4 
  
  If *pFormElement\get_length(@Number)= #S_OK 
    For a= 0 To Number-1
      varIndex\Variant\lVal= a
      
      hr= *pFormElement\item(varIndex\Split[0], varIndex\Split[1], varIndex\Split[2], varIndex\Split[3], varIndex\Split[0], varIndex\Split[1], varIndex\Split[2], varIndex\Split[3], @*pElemDisp)
      If hr=0 And *pElemDisp>0
        hr=*pElemDisp\QueryInterface(?IID_IHTMLInputElement, @*pInputElement)
        If hr=0 And *pInputElement>0
          hr=*pInputElement\get_type(@*bstr)
          If hr=0 And *bstr>0
            Propriete.s= PeekS (*bstr,-1, #PB_Unicode )
            SysFreeString_ (@*bstr)
            
            If Valid=0
              If Propriete= "text" 
                NbText=NbText+1
              ElseIf Propriete= "password" 
                NbPassword=NbPassword+1
              ElseIf Propriete= "submit" And NbText=1 And NbPassword=1
                NbSubmit=NbSubmit+1
              EndIf 
            Else 
              If Propriete= "text" 
                *pInputElement\put_value(AutoLogin()\Nom)
              ElseIf Propriete= "password" 
                *pInputElement\put_value(AutoLogin()\Password)
              ElseIf Propriete= "submit" 
                If *pElemDisp\QueryInterface(?IID_IHTMLElement, @*pElement.IHTMLElement)= #S_OK 
                  *pElement\Click()
                  *pElement\Release()
                  Submit= 1
                  a= Number
                EndIf 
              EndIf 
            EndIf 
          EndIf 
          *pInputElement\Release()
        EndIf 
        *pElemDisp\Release()
      EndIf 
    Next a
  EndIf 
  
  If NbSubmit=1 And NbText=1 And NbPassword=1
    ProcedureReturn ProcessInputElement(*pFormElement,1)
  EndIf 
  
  If Submit
    ProcedureReturn 1
  Else 
    ProcedureReturn 0
  EndIf 
EndProcedure 

Procedure ProcessFormsCollection(*pElemColl.IHTMLElementCollection_FIXED)
  Protected *pElemDisp.IDispatch = #Null 
  Protected *pFormElement.IHTMLFormElement_Fixed = #Null 
  Protected a.l,Number.l,*bstr,varIndex.VARIANT_SPLIT
  Protected hr.l,Ret.l
  
  varIndex\Variant\vt = #VT_I4 
  
  If *pElemColl\get_length(@Number)= #S_OK 
    For a=0 To Number-1
      varIndex\Variant\lVal= a
      
      hr= *pElemColl\item(varIndex\Split[0], varIndex\Split[1], varIndex\Split[2], varIndex\Split[3], varIndex\Split[0], varIndex\Split[1], varIndex\Split[2], varIndex\Split[3], @*pElemDisp.IDispatch)
      If hr=0 And *pElemDisp>0
        hr= *pElemDisp\QueryInterface(?IID_IHTMLFormElement, @*pFormElement)
        If hr=0 And *pFormElement>0
          If ProcessInputElement(*pFormElement,0)
            a=Number
            Ret=1
          EndIf 
          *pFormElement\Release()
        EndIf 
        *pElemDisp\Release()
      EndIf 
    Next a
  EndIf 
  
  If Ret
    ProcedureReturn 1
  Else 
    ProcedureReturn 0
  EndIf 
EndProcedure 

Procedure ProcessDocument(*pDoc.IHTMLDocument2)
  Protected *pElemColl.IHTMLElementCollection_FIXED = #Null 
  Protected hr.l,Ret.l
  
  hr= *pDoc\get_forms(@*pElemColl)
  If hr=0 And *pElemColl>0
    Ret=ProcessFormsCollection(*pElemColl)
    *pElemColl\Release()
  EndIf 
  
  If Ret
    ProcedureReturn 1
  Else 
    ProcedureReturn 0
  EndIf 
EndProcedure 

Procedure Auto_Login(Url.s)
  Protected *pDispatch.IDispatch,*pDocument2.IHTMLDocument2
  Protected hr.l,Ret.l,message.s
  
  
  ForEach AutoLogin()
    If AutoLogin()\Url=Url
      Ret=1
      Break
    EndIf 
  Next 
  
  If Ret
    hr= WebBrowser\get_document(@*pDispatch)
    If hr=0 And *pDispatch>0
      hr=*pDispatch\QueryInterface(?IID_IHTMLDocument2, @*pDocument2)
      If hr=0 And *pDocument2>0
        If ProcessDocument(*pDocument2)
          message= "Le programme à rempli ce formulaire pour vous ; )" + Chr (13)
          message+ "Si vos informations de Login sont correctes, vous serez connecté!" 
          MessageRequester ( "Info" ,message)
        EndIf 
        *pDocument2\Release()
      EndIf 
      *pDispatch\Release()
    EndIf 
  EndIf 
EndProcedure 

OpenWindow ( #Main ,0,0,800,600, "Auto Login" , #PB_Window_SystemMenu | #PB_Window_ScreenCentered )

If CreateStatusBar ( #Status , WindowID ( #Main ))
  AddStatusBarField (600)
  AddStatusBarField (200)
EndIf 

StatusBarText ( #Status , 0, "" )
StatusBarText ( #Status , 1, "" )

CreateGadgetList ( WindowID ( #Main ))
PanelGadget ( #Panel , 2, 24, 798, 550)
AddGadgetItem ( #Panel , -1, "" )
WebGadget ( #Web ,2,2,788,520, "http://www.purebasic.fr/english/ucp.php?mode=login" )
CloseGadgetList ()

ProgressBarGadget ( #Progress , 10, 4, 200, 10, 0, 100)

WebBrowser.IWebBrowser2 = GetWindowLong_ ( GadgetID ( #Web ), #GWL_USERDATA )

Repeat 
  Event= WaitWindowEvent ()
  Select Event
    Case #PB_Event_Gadget 
      Select EventGadget ()
        Case #Web 
          Select EventType ()
              
            Case #PB_EventType_TitleChange 
              Title.s= GetGadgetItemText ( #Web , #PB_Web_PageTitle )
              SetGadgetItemText ( #Panel , 0, Title, 0)
              
            Case #PB_EventType_StatusChange 
              StatusTexte.s= GetGadgetItemText ( #Web , #PB_Web_StatusMessage )
              StatusBarText ( #Status , 0, StatusTexte)
              
            Case #PB_EventType_DownloadProgress 
              Progress= GetGadgetAttribute ( #Web , #PB_Web_Progress )
              ProgressMax= GetGadgetAttribute ( #Web , #PB_Web_ProgressMax )
              
              If Progress<>ProgressMax
                HideGadget ( #Progress ,0)
                SetGadgetState ( #Progress , Progress)
              Else 
                HideGadget ( #Progress ,1)
              EndIf 
              
            Case #PB_EventType_DownloadEnd 
              Url.s= GetGadgetText ( #Web )
              Auto_Login(Url)
          EndSelect 
      EndSelect 
      
    Case #WM_CLOSE 
      quit.l=1
  EndSelect 
Until quit=1
End 

DataSection 
  IID_IHTMLElement:
  Data.l $3050F1FF
  Data.w $98B5, $11CF
  Data.b $BB, $82, $00, $AA, $00, $BD, $CE, $0B
  
  IID_IHTMLInputElement:
  Data.l $3050F5D2
  Data.w $98B5, $11CF
  Data.b $BB, $82, $00, $AA, $00, $BD, $CE, $0B
  
  IID_IHTMLFormElement:
  Data.l $3050F1F7
  Data.w $98B5, $11CF
  Data.b $BB, $82, $00, $AA, $00, $BD, $CE, $0B
  
  IID_IHTMLDocument2:
  Data.l $332C4425
  Data.w $26CB, $11D0
  Data.b $B4, $83, $00, $C0, $4F, $D9, $01, $19
EndDataSection