Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

VBScript needed to open an URL in an existing IE window


  • Please log in to reply
9 replies to this topic
not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Can anybody help me with a VBScript that simply opens an URL in an existing Internet Explorer window?

I cannot get it to work and I cannot find any scripts online either... :cry:

I need to be able to reference to a specific IE window (based on title/URL), and then open another URL (or better, a JavaScript command) in that same window (not in a new window)

I found this, but this is way over my head, the bold part does partially what I need...

HTA application with VBScript



Dom Explorer
APPLICATIONNAME="Dom_Explorer"
BORDER="thick"BORDERSTYLE="normal"
CAPTION="yes" CONTEXTMENU="yes"
ID="oHTA" alert(oHTA.applicationName);
INNERBORDER="yes" MAXIMIZEBUTTON="yes" MINIMIZEBUTTON="yes"
NAVIGABLE="no" SCROLL="yes" SCROLLFLAT="no"
SELECTION="yes"SHOWINTASKBAR="yes" SINGLEINSTANCE="no"
SYSMENU="yes" VERSION="0.5" WINDOWSTATE="normal">


not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Here is more code, interesting parts are bold

To use, simply declare a (Public) variable as Browser. Then use any of the following methods:

NAVIGATE(LOC as string) | equivalent to typing loc into the address section of the browser
‘ REFRESH | Equivalent to pressing the refresh button in your browser
‘ BACK | Equivalent to pressing the back button in your browser
‘ BUTTON(CAPTION as string) | click the button containing text CAPTION
‘ HYPERLINK(TEXT as string, URL as string, DISABLEONCLICK as boolean) | click the hyperlink containing Text or linking to URL
‘ DROPDOWN(NAME as string, OPT as integer) | select option OPT from dropdown NAME
‘ TEXTBOX(NAME as string, TEXT as string) | fill textbox NAME with TEXT
‘ OPTION BUTTON(NAME as string, NUM as integer) | click the element NAME(NUM)
‘ FINDHTML(TEXT as string) | returns True if TEXT is found in the current page
‘ FINDNEXTTAG(TAGTYPE as string, TAGINDICATOR as string, TAGDELAY as integer) | searches for a TAGTYPE containing TAGINDICATOR and returns the content of TAGDELAY TAGTYPEs after it
‘ REGEXTRACT(PTN as string, SNG as boolean, STARTSTR as string, ENDSTR as string) | returns an array (value if SNG) of regular expression PTN in the code between STARTSTR and ENDSTR
RUNJAVASCRIPT(SCR as string) | executes the javascript SCR
‘ OBJECT | allows direct access to the browser object when the above methods are inadequate

Many of the parameters are optional and most functions have the capacity to return False if the element being interacted with is not found. Hope this proves useful!
... etc.



not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Why I do need this? I am trying to do web-page manipulation thru JavaScript. I use an Internet Explorer window, and set the addressbar with desired JavaScript. All good, but I cannot find a method to actually send the new url (JavaScript) without activating the IE Window :cry:

I want this to be as invisible as possible, but as soon as I send the {Enter}, the window gets activated.

So, I thought I'd try VBScript, it might offer a method to change the URL without activating the IE window...

Pfff...

Conclusion: No, I don't need COM/OLE support in AHK. VBScript is way to complicated (and deprecated too)...

not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Here is a demo script, should run as is...

; *** Init
#SingleInstance force
SetTitleMatchMode, 2
SetWinDelay, 0
DetectHiddenWindows, on

; *** Settings here

; the full url
TargetURL = http://www.autohotkey.com/

; partial (but unique) title of the window of the target URL
TargetWinPartialTitle = AutoHotkey - Free Mouse

/* information to retreive from the window/document

Examples:

document.bgColor
document.selection.createRange().text
document.lastModified
document.links.length
document.forms[0].aFormElement.value

You can also combine values, with a delimiter, for easy retreiving, like this:

document.selection.createRange().text+'|'+document.lastModified

You can test this beforehand by pasting it into the address bar of Internet Explorer
yourself (and Enter-ing) in this form:

javascript:alert(document.lastModified);

*/

; The values to get, pipe-delimited
TargetInfoToGetAll = document.lastModified|document.bgColor|document.links.length

; A unique ID
TargetInfoToGetID = JustTesting

; Interval between retreives (in milliseconds)
TargetGetInterval = 5000

; *** Probably no need to change below here
StringSplit, TargetInfoToGetAll, TargetInfoToGetAll, |
StringTrimLeft, TargetURLCookie, TargetURL, 7
StringSplit, TargetURLCookie, TargetURLCookie, .
TargetURLCookie := TargetURLCookie1 "." TargetURLCookie2
TargetWin = %TargetWinPartialTitle% ahk_class IEFrame
RegRead, CookiePath, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders, Cookies
CookiePath = %CookiePath%\%USERNAME%@%TargetURLCookie%[
InitJS()

; *** for Demo purposes
IfWinNotExist, %TargetWin%
	Run, %A_ProgramFiles%\Internet Explorer\IEXPLORE.EXE "%TargetURL%"
WinWait, %TargetWin%, , 10
If errorlevel = 1
{
	MsgBox, 16, Error, Error... Check settings
	ExitApp
}
MsgBox, 32, Ready for the Demo?,
(
Press OK if the site is loaded

This Demo will retreive 3 different values from the document,
show them in a ToolTip, and quit...

For 'inobtrusiveness', the Window will be hidden inbetween,
to give an idea of what I try to accomplish
)

; ***

;WinShow, %TargetWin%
;WinMove, %TargetWin%, , 10000, 0
;WinHide, %TargetWin%

Loop, %TargetInfoToGetAll0%
{

	TargetInfoToGet := TargetInfoToGetAll%A_Index%
	InitJS()

	WinMinimize, %TargetWin%

	;WinGet, curWin, ID, A
	;BlockInput, on
	;WinHide, %TargetWin%

; classic

	ControlSetText, Edit1, %JSCookieWrite%, %TargetWin%
	Sleep, 500
	ControlSend, Edit1, {ENTER}, %TargetWin%
	Sleep, 50

; alternative
/*
	SendMessage, 0x0C, 0, &JSCookieWrite, Edit1, %TargetWin% ; 0x0C is WM_SETTEXT
	Sleep, 50
	PostMessage, 0x100, 0x0000000d, 0x001c0001, Edit1, %TargetWin% ; 0x100 is WM_KEYFIRST, the other values make 'Enter'
	Sleep, 50
*/

	WinMinimize, %TargetWin%

	;WinHide, %TargetWin%
	;BlockInput, off
	;WinActivate, ahk_id %curWin%

	Sleep, 500 ; Allow time to write the cookie
	Loop, %CookiePath%*].txt ; --- Scan the existing cookies for ours 
	{ 
		FileReadLine, aCookieName, %A_LoopFileFullPath%, 1
		aCookiePath := A_LoopFileFullPath
		If aCookieName = %CookieName%
			break
	}
	FileReadLine, ReturnValue, %aCookiePath%, 2
	ToolTip, Scan#: %A_Index%`n`nInfo wanted: %TargetInfoToGet%`n`nValue: %ReturnValue%
	SetTimer, RemoveToolTip, 3000
	Sleep, %TargetGetInterval%
}
FileDelete, %aCookiePath%
ExitApp
Return

InitJS()
{
	global JSCookieWrite, TargetInfoToGet
	JSCookieWrite = javascript:var name='%TargetInfoToGetID%';var value=%TargetInfoToGet%;var date=new Date();date.setTime(date.getTime()+3000);var expires=";expires="+date.toGMTString();var ck=name+"="+value+expires+";path=/";document.cookie=ck;void(0);
}

RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
Return

ESC::
ExitApp
Return

Now how can I avoid the window activating? Maybe with some VBScript instead? I found no way to actually send the new URL/JavaScript without activation of the window... :cry:

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
The spam-blocker was a little overzealous by blocking your attempt to reply to this topic. I think I've fixed the problem.

not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
@Chris: Ah, ok... :p ... It's a lot of text... you can shorten the first two postings if needed.

But, tadaa! I have some very useful code now (to try: save as .vbs and run)

Dim oIE

Set oIE = CreateObject("InternetExplorer.Application")
oIE.Visible = 0 ' Hidden

oIE.Navigate "http://www.autohotkey.com"

Do While (oIE.Busy)
Wscript.Sleep 10
Loop

oIE.Navigate "javascript:alert(document.bgColor);"

Do While (oIE.Busy)
Wscript.Sleep 10
Loop

oIE.Navigate "javascript:alert(document.lastModified);"

Do While (oIE.Busy)
Wscript.Sleep 10
Loop

oIE.Quit

This works (for me), and hidden! :D

One problem. How can I reuse the created window (oIE ?), and avoid erroneously using another Internet Explorer window (or opening a new window/closing it every time I want to insert JavaScript commands)?

I don't know how to make the oIE reference 'global', so that I can reuse it, and change the URL/JS of 'my' hidden window (in an AHK loop) by something as simple as:

oIE.Navigate "javascript:alert('next command');"

This alone errors out (he dunno what oIE is)...

not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Ok, next script (needs cmdret.dll in script directory):

; The URL to load
URLToLoad = http://www.autohotkey.com

; The values to get from the URL
HTMLDOMValuesToGet = document.LinkColor|document.vLinkColor|document.bgColor|document.lastModified

; Set to 0 if you don't want to see the IE instance
; Set to 1 to make it visible
IEVisible = 1

; *** Probably no need to change below here

; Path to temporary output file
PathToVBScriptOutputFile = %A_ScriptDir%\VBScriptOutput.tmp

; Test for existance of needed peval.vbs, if it is not there, create it
IfNotExist, %A_ScriptDir%\peval.vbs
FileAppend,
(
Dim StdIn, script 
script = "" 
Set StdIn = WScript.StdIn 
Do While Not StdIn.AtEndOfStream 
    script = script + vbNewLine + StdIn.ReadLine 
Loop 
execute script
), %A_ScriptDir%\peval.vbs

; Create the VBScript from the wanted values for write
VBCodeForValues =
Loop, Parse, HTMLDOMValuesToGet, |
	VBCodeForValues = %VBCodeForValues%oFile`.Write`(oIE`.%A_LoopField%+"|"`)`n

; The actual VBScript
VBScript =
(
' Declare variables
Dim oIE, oFSO, oFile
' Create an IE instance
Set oIE = CreateObject("InternetExplorer.Application")
' Set visibility
oIE.Visible = %IEVisible%
' Open the URL
oIE.Navigate "%URLToLoad%"
' Wait for ready
Do While (oIE.Busy)
Wscript.Sleep 10
Loop
' Get values, and write to output file
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = oFSO.CreateTextFile("%PathToVBScriptOutputFile%", True)
%VBCodeForValues%
oFile.Close
' Close our IE instance
oIE.Quit
)

; Run the VBScript
VBScriptReturnCode := RunVBS(VBScript)

; Read the results from the temp-file
FileRead, VBScriptResult, %PathToVBScriptOutputFile%

; Delete the temp-file
FileDelete, %PathToVBScriptOutputFile%

; Present the results
Msgbox, 
(
Errorlevel: %ErrorLevel%
VBScriptReturnCode: %VBScriptReturnCode%
-------------------------------------
VBScriptResult (pipe-delimited):

%VBScriptResult%

-------------------------------------
)
return
;
; *** Functions
;
; CMDRet RunWaitEx function 
RunWaitEx(CMD, CMDdir, CMDin, ByRef CMDout, ByRef CMDerr) 
{ 
  VarSetCapacity(CMDOut, 100000) 
  VarSetCapacity(CMDerr, 100000) 
  RetVal := DllCall("cmdret.dll\RunWEx", "str", CMD, "str", CMDdir, "str", CMDin, "str", CMDout, "str", CMDerr) 
  Return, %RetVal% 
} 

Capture(CMD, input) 
{ 
    CMDOUT = 
    CMDERR = 
    RunWaitEx(CMD, a_scriptdir, input, CMDOUT, CMDERR) 
    return %CMDOUT% 
} 

; Code to run .vbs
RunVBS(VBScript) 
{ 
    Return Capture("cscript.exe //Nologo peval.vbs", VBScript) 
}

I still have not found a way to do the same with an existing window (to be able to reuse instead of recreating a new instance of IE every time). Cannot find how to get a 'handle' or whatever necessary...

Any help would be appreciated.

not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Still investigating on a way how to use the VBScript/WSH possibilities with AHK unobtrusively...

I use the Using VBscript in ahk without a temporary file script with cmdret.dll.

This already effectively hides the VBScript...

Now, I want to be able to return data from VBScript/WSH to an AHK-script.

WSH can write to file or to an environment variable, but this won't be 'invisible'/safe/unobtrusive...

Since VBScript cannot do SendMessage/PostMessage, I'm kindof stuck here...

But... I found this :) :

dynacall.dll

... dynacall.dll ... provides something like a "Declare statement" in VBScript. Basically it will allow you to call functions in other dlls (like any of the win32 API function)


Great! So I can do SendMessage/PostMessage!

Now, this vbs-script will work (from here):

Broadcast_it

sub Broadcast_it    'reduced version
    'broadcast wm_settingchange
    'Dynwrap pre-installed is required.
    const HWND_BROADCAST=&HFFFF
    const WM_SETTINGCHANGE=&H1A
    Dim oDynWrap 
    Set oDynWrap=createobject("DynamicWrapper")
    oDynWrap.Register "user32.dll", "SendMessageA", "i=llll", "f=s", "r=l"
    oDynWrap.SendMessageA HWND_BROADCAST, WM_SETTINGCHANGE,0,0
    set oDynWrap=nothing
end sub

How can I change this to SendMessage a string from a VBScript to an AHK script (and receive with OnMessage...)?

I cannot get the values right apparently... Help!

not-logged-in-daonlyfreez
  • Guests
  • Last active:
  • Joined: --
Ok, nevermind... I didn't see the obvious... STDOUT 8)

So, no need for SendMessage/PostMessage, this will work (ofcourse still needs cmdret.dll in script folder):

VBScript =
(
Dim stringToSend
stringToSend = "Hi to AHK from VBScript"
WScript.StdOut.Write(stringToSend)
)

; Run the VBScript
VBScriptReturnCode := RunVBS(VBScript)
MsgBox % VBScriptReturnCode
ExitApp

;
; *** Functions
;
; CMDRet RunWaitEx function 
RunWaitEx(CMD, CMDdir, CMDin, ByRef CMDout, ByRef CMDerr) 
{ 
  VarSetCapacity(CMDOut, 100000) 
  VarSetCapacity(CMDerr, 100000) 
  RetVal := DllCall("cmdret.dll\RunWEx", "str", CMD, "str", CMDdir, "str", CMDin, "str", CMDout, "str", CMDerr) 
  Return, %RetVal% 
} 

; Get CMDout
Capture(CMD, input) 
{ 
    CMDOUT = 
    CMDERR = 
    RunWaitEx(CMD, a_scriptdir, input, CMDOUT, CMDERR) 
    return %CMDOUT% 
} 

; Code to run VBScript
RunVBS(VBScript) 
{ 
	; Test for existance of needed peval.vbs, if it is not there, create it
	IfNotExist, %A_ScriptDir%\peval.vbs
	FileAppend,
		(
		Dim StdIn, script 
		script = "" 
		Set StdIn = WScript.StdIn 
		Do While Not StdIn.AtEndOfStream 
		    script = script + vbNewLine + StdIn.ReadLine 
		Loop 
		execute script
		), %A_ScriptDir%\peval.vbs
	; Run the VBScript
    Return Capture("cscript.exe //Nologo peval.vbs", VBScript) 
}

Would still be interesting to use dynwrap.dll/SendMessage or PostMessage though (previous example works as 'standalone' vbs-script, but apparently it won't work anyway if I pipe it thru cmdret.dll, dunno)

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
I don't know the solution, but it's good that you found another approach.

By the way, Ton Plooy's Dynacall is also used internally by AutoHotkey's DllCall. He did a great job with it and it's good to see it being used in other places.