Grabbing the URLs of all browser tabs

Started by etippelt, May 06, 2015, 01:54:12 PM

Previous topic - Next topic

etippelt

Quick question in case anyone can point me in the right direction. At the moment I have two different windows of the Chrome browser open, each with multiple tabs open, and another windows of the IE browser, also with several tabs open.  Is there a way I can grab all the URLs from the various browser tabs and write them to a file?
Thanks in advance
EdT
Using Winbatch since 1995. Excellent tool, awesome support always.


etippelt

Thanks - a good starting point. Now I need to figure out how to change focus to each tab in turn.
Using Winbatch since 1995. Excellent tool, awesome support always.

etippelt

Hmm,
Run into a problem with the C# code subroutine in the second link (written by Deana Falk)

Running under 2015A I get an error on line 71:
  ObjectClrOption ( 'use', 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')

which states: 1848 CLR:Type name not found
then continues:  objCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')

I have the .NET framework 4.52 installed, but I had a search in the registry for System.Core  and the entries looked consistent with the code that is erroring out, for both version, culture and PublicKeyToken.

I have tried running under both 32 bit and 64 bit settings and the error is consistent in both cases.  I am not a programmer so am at a loss what to try next.

If anyone can steer me in the right direction, I would be most grateful.

Thanks
EdT

Using Winbatch since 1995. Excellent tool, awesome support always.

td

The line

Code (winbatch) Select
ObjectClrOption ( 'use', 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')

is not correct and is likely causing the puke (technical term) on the next line.  I have no idea why its there but remove the '.Core' from the assembly name.  You end up with this

Code (winbatch) Select
ObjectClrOption ( 'use', 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')

and hopefully a happy script with no unseemly regurgitation.

"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

Just a curiosity question...where did "System.Core" come from, as that wasn't in the Tech Database code?  At least I'm not seeing it.

Jim

td

It was (note past tense as apposed to present tense) in the the Tech Database example.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

etippelt

Thanks - that has fixed the error.  Now I need to find out why the box is displaying nothing even though there are many tabs open in Chrome...
Using Winbatch since 1995. Excellent tool, awesome support always.

etippelt

Adding in some extra display code shows that the code is returning a null value each time the sub is called, so it would appear that there has been a change in Chrome again, which stops the code working. Back to the drawing board.
Cheers
Ed
Using Winbatch since 1995. Excellent tool, awesome support always.

JTaylor

Here is the latest that fixed things as of version 38.  I just tested and it works.   I've gotten a little smarter since I did the first version.   Not sure about that "Core" thing as it was in my code and used to work. 

Jim


Code (winbatch) Select


;************************************************************************************************************
;**  This retrieves the Current URL from Chrome Version 38. May work with earlier versions as I changed
;**  what I did for version 35 but no good way to test.
;**  Guessing it will break again soon (but maybe not as this approach is a bit more flexible) but offers an
;**  approach that could be modified as versions change.
;**  JTaylor 2014-10-14
;************************************************************************************************************

  If !AppExist("chrome.exe",0, 0) Then
    Display(2,"Note","Chrome is not running.")
    Exit
  EndIf

  GoSub Load_Routines
  Load_GetMyURL()
  url_save = ""

  While 1
    url   = sha1.GetMyURL()
    If url != url_save Then Display(2,"URL",url)
    url_save = url
    TimeDelay(3)
  EndWhile

Exit


:LOAD_ROUTINES

#DefineSubRoutine Load_GetMyURL()

;***************************************************************************
;**  Run C# in memory using WinBatch - Use Namespace.Class defined in CSharpeSource
;**
;** Purpose:  Run C# in memory using WinBatch - Using Namespace.Class defined in CSharpeSource
;** Inputs:
;** Outputs: Results in message
;**
;** Developer: Deana Falk 2014.04.14
;***************************************************************************

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Load assemblies into the WinBatch process.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  ObjectClrOption ( 'use', 'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Compiles the c# code in Memory
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  objCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')
  objParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
  objParams.GenerateInMemory = ObjectType( "VT_BOOL", 1 ) ;TRUE
 
  objParams.ReferencedAssemblies.Add("System.dll")
  objParams.ReferencedAssemblies.Add("C:\Windows\Microsoft.NET\assembly\GAC_MSIL\UIAutomationTypes\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationTypes.dll")
  objParams.ReferencedAssemblies.Add("C:\Windows\Microsoft.NET\assembly\GAC_MSIL\UIAutomationClient\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationClient.dll")

;Make sure the cSharp code includes both namepspace and class that can be later used by ObjectCLRNew
  cSharpSource =               `namespace URLEngine {`:@LF
  cSharpSource = cSharpSource :`using System;`:@LF
  cSharpSource = cSharpSource :`using System.Text;`:@LF
  cSharpSource = cSharpSource :`using System.Threading;`:@LF
  cSharpSource = cSharpSource :`using System.Runtime.InteropServices;`:@LF
  cSharpSource = cSharpSource :`using System.Text.RegularExpressions;`:@LF
  cSharpSource = cSharpSource :`using System.Collections.Generic;`:@LF
  cSharpSource = cSharpSource :`using System.Windows.Automation;`:@LF
  cSharpSource = cSharpSource :`using System.Diagnostics;  `:@LF
  cSharpSource = cSharpSource :`public class MyURLEngine {`:@LF
  cSharpSource = cSharpSource :`public string GetMyURL() `:@LF
  cSharpSource = cSharpSource :`  { `:@LF
  cSharpSource = cSharpSource :`    `:@LF
  cSharpSource = cSharpSource :`  Process[] procsChrome = Process.GetProcessesByName("chrome");  `:@LF
  cSharpSource = cSharpSource :`  int myint = procsChrome.Length;  `:@LF
  cSharpSource = cSharpSource :`  string mystring = myint.ToString();  `:@LF
; cSharpSource = cSharpSource :`  return mystring;  `:@LF
  cSharpSource = cSharpSource :`  foreach (Process chrome in procsChrome) {  `:@LF
  cSharpSource = cSharpSource :`  if (chrome.MainWindowHandle == IntPtr.Zero) { continue; }`:@LF
  cSharpSource = cSharpSource :`  AutomationElement elm = AutomationElement.FromHandle(chrome.MainWindowHandle);  `:@LF
  cSharpSource = cSharpSource :`  AutomationElement elmUrlBar = null;  `:@LF
  cSharpSource = cSharpSource :`  try {  `:@LF
  cSharpSource = cSharpSource :`      elmUrlBar = elm.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Address and search bar"));`:@LF
  cSharpSource = cSharpSource :`      if (elmUrlBar == null) { return ""; } // not the right chrome.exe  `:@LF
  cSharpSource = cSharpSource :`      }  `:@LF
  cSharpSource = cSharpSource :`  catch {  `:@LF
  cSharpSource = cSharpSource :`      continue;  `:@LF
  cSharpSource = cSharpSource :`      } `:@LF
  cSharpSource = cSharpSource :`  if (elmUrlBar == null) { continue; }`:@LF
  cSharpSource = cSharpSource :`  AutomationPattern[] patterns = elmUrlBar.GetSupportedPatterns();  `:@LF
  cSharpSource = cSharpSource :`  if (patterns.Length == 1) {  `:@LF
  cSharpSource = cSharpSource :`  try {  `:@LF
  cSharpSource = cSharpSource :`        string ret = ((ValuePattern)elmUrlBar.GetCurrentPattern(patterns[0])).Current.Value;  `:@LF
  cSharpSource = cSharpSource :`        return ret;  `:@LF
  cSharpSource = cSharpSource :`  } catch { }  `:@LF
  cSharpSource = cSharpSource :`        continue;  `:@LF
  cSharpSource = cSharpSource :`  }  `:@LF
  cSharpSource = cSharpSource :`  }  `:@LF

  cSharpSource = cSharpSource :` return "";  `:@LF

  cSharpSource = cSharpSource :`     } `:@LF
 
  cSharpSource = cSharpSource :` }`:@LF
  cSharpSource = cSharpSource :`}`:@LF

  objResult = objCSharp.CompileAssemblyFromSource(objParams,cSharpSource)

  ;Compiler Output
  If objResult.Output.Count > 0 Then
    strOutput = ''
    For x = 0 to objResult.Output.Count-1
       If strOutput == "" Then
         strOutput = objResult.Output.Item(x)
       Else
         strOutput = strOutput:@LF:objResult.Output.Item(x)
       EndIf
    Next
    Pause('Compiler Output',strOutput)
  Endif
 
  ; Compiler Errors
  If objResult.Errors.Count > 0 Then
    strErrors = ''
    ForEach ce In objResult.Errors
      ;Pause("Error", ce.ToString())
      If strErrors == "" Then
        strErrors = ce.ToString()
      Else
        strErrors = strErrors:@LF:ce.ToString()
      EndIf
    Next
    Pause('Compiler Errors',strErrors)
    Exit
  EndIf

  sha1 = ObjectClrNew( 'URLEngine.MyURLEngine' )

#EndSubRoutine

Return

etippelt

Hi Jim,
I did get a URL displayed with your code, but after that the app never exited, and looking closer at the code, the while loop does not appear to have an exit strategy:

  While 1
    url   = sha1.GetMyURL()
    If url != url_save Then Display(2,"URL",url)
    url_save = url
    TimeDelay(3)
  EndWhile

In the event that url = url_save then you end up in an endless loop.  I'm guessing that an "else" is missing in your logic.  When you test your code, does it display all tabs in sequence, or just the one that has focus?  Are you running as 32 bit or 64 bit ?

Cheers
Ed
Using Winbatch since 1995. Excellent tool, awesome support always.

JTaylor

No.  That is by design.  It was for a particular project and I just posted it as it was.   Should have mentioned that fact but, as you note, it is fairly obviously.   I figured your main interest was the function containing the C# code and you would discard the rest or alter as needed.  Wasn't really trying to give you a final solution to your problem...just helping you along the way a bit.  Plus the code in the Tech Database needs updated with the version I posted.  Hopefully this version is flexible enough it will last more than 2-3 versions of Chrome updates.

Jim

JTaylor

I just realized I hadn't responded to all your questions...

It displays the active Tab, again by design.

32-bit.

Unfortunately Chrome doesn't list all of it's tabs as windows like IE or it would be easier to get what you want.   You might look at Selenium if you can't find another way to retrieve the information.  Wish I had a good answer for you.


Jim

etippelt

Thanks Jim, appreciate all the help.  I will explore a few avenues as task manager certainly shows numerous Chrome processes running so the answer may be to enumerate all the relevant processes, then set the focus on them in turn and finally run the code to grab the URL.
Using Winbatch since 1995. Excellent tool, awesome support always.

td

Since the 'inactive' Chrome processes do not appear to have Windows attached to them, you may have to resort to using the lowly 'SendKey' function to send ctl+tab keys to  Chrome to given each process in turn an active window.   This is of course a common approach used with the soon to be replaced Internet Explorer.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade