WinBatch® Technical Support Forum

Archived Boards => WinBatch Script Exchange => Topic started by: JTaylor on June 17, 2014, 08:25:10 AM

Title: Retrieve Current URL from Chrome - .NET
Post by: JTaylor on June 17, 2014, 08:25:10 AM
Here is code for retrieving the Current URL from Chrome.   I used Deana's excellent example of compiling C# code in-memory so I could create a Method for this purpose.

Jim

Code (winbatch) Select


;************************************************************************************************************
;**  This retrieves the Current URL from Chrome Version 35.
;**  I know it won't work with 32 (it will with a minor tweak) due to changes somewhere along the way to 35.
;**  Guessing it will break again soon but offers an approach that could be modified as versions change.
;************************************************************************************************************

  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.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; mscorlib assembly is automatically loaded by WinBatch when the CLR is loaded.
; ObjectClrOption ('use','mscorlib, version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')

; ObjectClrOption("version", "v2.0.50727")
; ObjectClrOption("use","System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
  ObjectClrOption ( 'use', 'System.Core, 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) {  `:@LF
  cSharpSource = cSharpSource :`    continue;  `:@LF
  cSharpSource = cSharpSource :`  } `:@LF
  cSharpSource = cSharpSource :`    `:@LF
  cSharpSource = cSharpSource :`  AutomationElement elm = AutomationElement.FromHandle(chrome.MainWindowHandle);  `:@LF
  cSharpSource = cSharpSource :`    `:@LF
  cSharpSource = cSharpSource :`  AutomationElement elmUrlBar = null;  `:@LF
  cSharpSource = cSharpSource :`  try {  `:@LF
  cSharpSource = cSharpSource :`        var elm1 = elm.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));  `:@LF
  cSharpSource = cSharpSource :`        if (elm1 == null) { continue; } // not the right chrome.exe  `:@LF
  cSharpSource = cSharpSource :`        var elm2 = TreeWalker.RawViewWalker.GetLastChild(elm1); // I don't know a Condition for this for finding :(  `:@LF
  cSharpSource = cSharpSource :`        var elm3 = elm2.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, ""));  `:@LF
  cSharpSource = cSharpSource :`        var elm4 = TreeWalker.RawViewWalker.GetNextSibling(elm3); // I don't know a Condition for this for finding :(  `:@LF
  cSharpSource = cSharpSource :`        var elm7 = elm4.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ToolBar));  `:@LF
  cSharpSource = cSharpSource :`        elmUrlBar = elm7.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Custom));  `:@LF
  cSharpSource = cSharpSource :`  } catch {  `:@LF
  cSharpSource = cSharpSource :`             continue;  `:@LF
  cSharpSource = cSharpSource :`  } `:@LF
  cSharpSource = cSharpSource :`    `:@LF
  cSharpSource = cSharpSource :`  if (elmUrlBar == null) {  `:@LF
  cSharpSource = cSharpSource :`    continue;  `:@LF
  cSharpSource = cSharpSource :`  }  `:@LF
  cSharpSource = cSharpSource :`    `:@LF
  cSharpSource = cSharpSource :`     if ((bool)elmUrlBar.GetCurrentPropertyValue(AutomationElement.HasKeyboardFocusProperty)) {  `:@LF
  cSharpSource = cSharpSource :`     continue;  `:@LF
  cSharpSource = cSharpSource :`  } `:@LF
  cSharpSource = cSharpSource :`    `:@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

Title: Re: Retrieve Current URL from Chrome - .NET
Post by: Deana on June 17, 2014, 10:07:32 AM
Hmm. I just tested on my Windows 7 system with Google Chrome (35.0.1916.153) running and the code you posted. It always seems to return: Chrome is Not Running.

What Windows platform and chrome version are you using?

Title: Re: Retrieve Current URL from Chrome - .NET
Post by: JTaylor on June 17, 2014, 12:34:46 PM
I'm on Windows 7 and Chrome Version 32.0.1700.107.

I'll update and see what happens.   At least you didn't get an error and for me that is quite the accomplishment  ;)

Jim
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: kdmoyers on June 17, 2014, 01:07:09 PM
I'm on win7 and Chrome Version 35.0.1916.114 m
I get "Chrome is Not Running" but it definitely is.
Then it loops till you terminate it.
-Kirby
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: JTaylor on June 17, 2014, 01:25:00 PM
Yeah...I see that on version 35 as well.   Bummer...had it working but guess something changed on that front between versions.  I'll get it figured out...unless someone beats me to it...I won't be offended if that happens  :)

Jim
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: JTaylor on June 17, 2014, 05:04:42 PM
How about now?  I updated the code.

Jim
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: kdmoyers on June 18, 2014, 05:08:55 AM
It works!!!!  sorta... it sometimes goes back to "not running."  I'll try to pin it down...
-Kirby
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: kdmoyers on June 18, 2014, 05:25:45 AM
It says "Chrome is not running" when you switch to a new blank tab, which is sorta true!
Otherwise I can't seem to fool it.  I'll let it run all day.  I changed the main program slightly
so I could resize a window to the bottom of the screen and leave it there.  The popup display
box was stealing focus.

Code (winbatch) Select
;Tell WIL not to complain when box is closed
IntControl(12, 1+4, 0, 0, 0)
;Enable Close button
IntControl(1008, 1, 0, 0, 0)

  boxopen("Chrome URL","")

  GoSub Load_Routines
  Load_GetMyURL()
  url_save = ""

  While 1
    url   = sha1.GetMyURL()
    If url != url_save
        ;Display(2,"URL",url)
        boxdataclear(1,"TOP")
        boxtext(url)
    endif
    url_save = url
    TimeDelay(3)
  EndWhile
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: JTaylor on June 18, 2014, 05:33:37 AM
I think I know what is causing that problem and will update things again a bit later.    One of the problems when one steals code that one doesn't fully understand.  I think I'm figuring it out though.   I believe it is related to the regex stuff which I am going to remove.

Jim
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: kdmoyers on June 18, 2014, 12:00:12 PM
It's been running for several hours now with narry a hickup, so seems pretty stable.
Nice Jim!
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: Deana on June 18, 2014, 12:41:36 PM
Nice. I posted a code sample to the tech database. Thanks for sharing: http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/dotNet/System_CodeDom+Grab~URL~from~Chrome.txt
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: JTaylor on June 18, 2014, 12:47:14 PM
Glad to hear it.   I'm still working on the situation where it is a local file (which is now working.  It was the regex stuff as I thought) and now I need to fix it so that it recognizes when it is running but no URL is present.  I guess the easiest approach would use AppExist to make sure it is running and then the blank URLs become a moot point.

Jim
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: JTaylor on June 18, 2014, 01:10:32 PM
I've changed the code above, hopefully for the last time.   Seems like no matter how much testing I do I usually miss something obvious but maybe I got it right this time.   Not sure how long before a new version will break it but maybe someone will find it useful.

Jim
Title: Re: Retrieve Current URL from Chrome - .NET
Post by: Deana on June 18, 2014, 01:52:14 PM
Updated the article to reflect your changes. http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/dotNet/System_CodeDom+Grab~URL~from~Chrome.txt