C# In-Memory Compiling and Objects

Started by JTaylor, April 03, 2022, 11:24:27 AM

Previous topic - Next topic

JTaylor

Give the following...Is there a way to maintain the object reference so it isn't separated from the underlying RCW?


Code (winbatch) Select


GoSub Load_Routines

  browser = Load_Parser()

  doc = browser.doParsing(FileGet("hap_test1.html"))

  inode = doc.GetElementById("table")
  message("Outer",inode.InnerText)

  author = inode.OuterHtml
  message("Outer",author)
  author = inode.InnerHtml
  message("Inner",author)

  arr = doc.GetElementsByTagName("SPAN")

  Foreach a in arr
    author = a.InnerText
    message("Author",author)
  Next

Exit

; https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlelement.getelementsbytagname?view=windowsdesktop-6.0

:LOAD_ROUTINES


#DefineSubRoutine Load_Parser()
;***************************************************************************
;**  Run C# in memory using WinBatch - Use Namespace.Class defined in CSharpeSource
;** 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 ( 'useany', 'System')
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; 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("System.Windows.Forms.dll")

;Make sure the cSharp code includes both namepspace and class that can be later used by ObjectCLRNew
  cSrc = $"namespace HParser {
    using System;
    using System.Text;
    using System.Security.Cryptography;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Threading;
                   
    public class MyParser {

    private HtmlDocument doc;

    private HtmlDocument doParsing(string html)
        {
            long doc_name = DateTime.Now.Ticks;
            WebBrowser wbc = new WebBrowser();
            wbc.DocumentText = "Hello World"; 
            HtmlDocument doc = wbc.Document.OpenNew(true);
            doc.Write(html);
            return doc;
        }

     }
    } $"

  objResult = objCSharp.CompileAssemblyFromSource(objParams,cSrc)

  ;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

  browser = ObjectClrNew( 'HParser.MyParser' )
  return browser

#EndSubRoutine


Return


JTaylor

I think I got rid of the problem by removing the Thread stuff.   If it can be done with that in place it would be helpful as it is much faster.

I was somewhat, pleasantly, surprised when I discovered that the variables in the C# code retain their values.   Just assumed they were renewed afresh on each call.   Same mistake I made with extenders.

Jim

td

I can see some benefit to using a thread-based solution in that it allows the WIL DLL to continue processing COM and window messages. Wasn't sure if that was why you used it though. Variable access across threads can get tricky even though MSFT tries to hide the complexity behind a CLR cover.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

It is definitely MUCH faster with it in place.   I am making progress after taking that part out.   Now that I have a direction that seems viable I may see if I can plug it back in.  Just didn't know if there was some trick to keeping that separation from occurring.  Should know soon if I have solved the problem.  Thanks.

Jim

stanl

Interesting. Outside of your individual reasons to accomplish your goal it does add to the more central issue of WB's capacity to accommodate classes via C#. I was poking at it with my lame post about Generics, but the ultimate responses were positive. Any testing you might need - just ask.

JTaylor

Will do.  I am still searching for the Holy Grail of HTML parsing that doesn't require a browser window open and works well.   My Extender is okay but I am not overly thrilled with that part of it.   That goal as well as the usual desire to learn something new.

Thanks.

Jim

td

For what it is worth, the "t.ApartmentState = ApartmentState.STA" setting likely doomed using a second thread. However, changing the setting to MTA will cause a kernel fault so that is not an option either. 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

JTaylor

Thanks.  That helps me continue with the decision that dropping that is probably the way to go.   I tried again yesterday but no luck.  It is a little slower on the parsing but everything after that works quickly.

Jim

JTaylor

Fortunately I went back and tried passing the object to WB after removing the Thread stuff.   Learned a lot before I did that but it involved a lot of unnecessary work :)  In any event, if you do something like the following:

  browser = Load_Parser()

  doc = browser.doParsing(FileGet("hap_test1.html"))

you will then have access to the Document object of the page.   The world then opens up to you.    Method and Property names are case sensitive.   A link to the documentation is below.  It opens to HtmlElement but you can find other related classes to the left in the index.   HtmlDocument and HtmlElementCollection may be of particular interest.  I may add some additional Methods such as GetElementsByClass(), which is not available.   

   https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlelement.getelementsbytagname?view=windowsdesktop-6.0

I would be interested hearing about any problems or victories, as well as suggestions for additional methods or properties that are not available but would be useful.


Jim


Code (winbatch) Select


GoSub Load_Routines

  browser = Load_Parser()

  doc = browser.doParsing(FileGet("hap_test1.html"))

  inode = doc.GetElementById("table")
  message("Outer",inode.InnerText)

  author = inode.OuterHtml
  message("Outer",author)
  author = inode.InnerHtml
  message("Inner",author)

  arr = doc.GetElementsByTagName("SPAN")

  Foreach a in arr
    author = a.InnerText
    message("Author",author)
  Next

Exit

; https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlelement.getelementsbytagname?view=windowsdesktop-6.0

:LOAD_ROUTINES


#DefineSubRoutine Load_Parser()
;***************************************************************************
;**  Run C# in memory using WinBatch - Use Namespace.Class defined in CSharpeSource
;** 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 ( 'useany', 'System')
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; 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("System.Windows.Forms.dll")

;Make sure the cSharp code includes both namepspace and class that can be later used by ObjectCLRNew
  cSrc = $"namespace HParser {
    using System;
    using System.Text;
    using System.Security.Cryptography;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Threading;
                   
    public class MyParser {

    private HtmlDocument doc;

    private HtmlDocument doParsing(string html)
        {
            long doc_name = DateTime.Now.Ticks;
            WebBrowser wbc = new WebBrowser();
            wbc.DocumentText = "Hello World"; 
            HtmlDocument doc = wbc.Document.OpenNew(true);
            doc.Write(html);
            return doc;
        }

     }
    } $"

  objResult = objCSharp.CompileAssemblyFromSource(objParams,cSrc)

  ;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

  browser = ObjectClrNew( 'HParser.MyParser' )
  return browser

#EndSubRoutine


Return


JTaylor

This can probably be done without the in-memory compiling but once I start adding additional functionality it will be needed.    So if not interested in additional stuff just rework it to make things simpler.

Jim

JTaylor

Here is an updated version which contains a couple of Methods I added.  I am guessing there is not a way to add them to the DOM Classes so having to pass element/document objects as a parameter.

Code (winbatch) Select

;Jim Taylor - with a little(lot of) help from Deana & Tony

;Object Method and Property Names are Case Sensitive.

GoSub Load_Routines

  browser = Load_Parser() ; Creates in-memory Class object for the Parser.  All Methods I added require this object.

  ;#################################################
  ;Loads HTML and Parses it.   HtmlDocument object is returned
  ;https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.htmldocument?view=windowsdesktop-6.0

   doc = browser.doParsing(FileGet("hap_test1.txt"))
  ;#################################################

  ;#################################################
  ;Example of a call using Document Object.  HtmlElement object is returned
  ;https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlelement?view=windowsdesktop-6.0

   element = doc.GetElementById("table")
   Message("Element InnerText",element.InnerText)
  ;#################################################


  ;#################################################
  ;Example of a call which returns an HtmlElementCollection object.
  ;https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.htmlelementcollection?view=windowsdesktop-6.0

   elements = doc.GetElementsByTagName("a")
   Foreach element in elements
     Message("Element OuterHtml",element.OuterHtml)
   Next
  ;#################################################

  ;#################################################
  ;Example of a call which returns a SortedList
  ;This is NOT a part of the Classes so it requires the element object as a parameter.
  ;https://docs.microsoft.com/en-us/dotnet/api/system.collections.sortedlist?view=net-6.0

   slist = browser.GetAttributes(doc.GetElementById("table"))
   Message(slist.Count,slist.GetByIndex(slist.IndexOfKey("id")))
  ;#################################################

  ;#################################################
  ;Example of a call which returns a List.
  ;This is NOT a part of the Classes so it requires the document or element object as a parameter.
  ;as well as the TAG and the class value.
  ;It will return ONLY the elements which contain the class values you supply.  If more than one, separate them
  ;with blank spaces.  All values must be in the elements class value for it to be returned.
  ;https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-6.0

   elements = browser.GetElementsByClass(doc.GetElementById("table"), "SPAN", "celwidget")
   Foreach a in elements
     Message("Count ":elements.Count, a.OuterHtml)
   Next
  ;#################################################


Exit


:LOAD_ROUTINES


#DefineSubRoutine Load_Parser()
;***************************************************************************
;**  Run C# in memory using WinBatch - Use Namespace.Class defined in CSharpeSource
;** 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 ( 'useany', 'System')
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; 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("System.Windows.Forms.dll")

;Make sure the cSharp code includes both namepspace and class that can be later used by ObjectCLRNew
  cSrc = $"namespace HParser {
    using System;
    using System.Text;
    using System.Security.Cryptography;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Threading;

    public class MyParser {

    private HtmlDocument doc;
    int i = 0;
    List<HtmlElement> el_list = null;
    HtmlElementCollection els = null;
    SortedList<string,string> at_map = null;
    readonly MessageBoxButtons buttons = MessageBoxButtons.OK;

    private HtmlDocument doParsing(string html)
        {
            WebBrowser wbc = new WebBrowser();
            wbc.DocumentText = "Hello World"; 
            doc = wbc.Document.OpenNew(true);
            doc.Write(html);
            return doc;
        }

  private SortedList<string,string> GetAttributes(HtmlElement obj)
       {
          string txt = obj.OuterHtml;
          string[] arr = txt.Split('>');
          string[] att = null;
          txt = arr[0];
          txt = txt.Substring(txt.IndexOf(' '),txt.Length-txt.IndexOf(' ')).Trim();
          char[] carr = txt.ToCharArray();
          int fcom = 0;
          txt = "";
          for (i=0;i<carr.Length;i++)
          {   
            if (fcom == 1 && carr[i] == '"')
               fcom = 0;
            else if (fcom == 0 && carr[i] == '"')
               fcom = 1;
            if (fcom == 0 || carr[i] != ' ')
              txt = txt + carr[i].ToString();
            if (fcom == 1 && carr[i] == ' ')
              txt = txt + ".";
          }   

          arr = txt.Replace("\"","").Split(' ');

          at_map = new SortedList<string,string>();
          for (i=0;i<arr.Length;i++)
            {   
              if (arr[i].Trim() == "")
                 continue;
              att = arr[i].Split('=');
              at_map.Add(att[0],att[1].Replace("."," "));
            }   

          return at_map;
        }

    private void ClassWork(string eclass)
        {
          i = -1;

          string ctxt;
          int foundit = 0;
          el_list = new List<HtmlElement>();
          foreach (HtmlElement el in els)
          {
            i++;
            ctxt = el.GetAttribute("className");
            if (ctxt.Trim() == "")
              continue;
            if (ctxt == eclass)
              {
                el_list.Add(el);
              }
            else
              {
                 foundit = 1;
                 string[] elist = eclass.Split(' ');
                 string[] clist = ctxt.Split(' ');
                 foreach (string eitem in elist)
                 {
                    if (Array.IndexOf(clist, eitem) < 0)
                    {
                      foundit = 0;
                    }
                 }             //END FOREACH
                 if (foundit == 1)
                   el_list.Add(el);

              }                //END ELSE
          }                    //END FOREACH
        }                      //END ClassWork()


    private List<HtmlElement> GetElementsByClass(HtmlElement obj, string tag, string eclass)
       {
          if (tag.Trim() == "")
          {
             els = obj.All;
          }
          else
          {
             els = obj.GetElementsByTagName(tag);
          }
          ClassWork(eclass);
          return el_list;
        }

    private List<HtmlElement> GetElementsByClass(HtmlDocument obj, string tag, string eclass)
       {
         if (tag.Trim() == "")
          {
             els = obj.All;
          }
          else
          {
             els = obj.GetElementsByTagName(tag);
          }
          ClassWork(eclass);
          return el_list;
        }
     }   // END OF CLASS
    }    // END OF NAMESPACE

$"

  objResult = objCSharp.CompileAssemblyFromSource(objParams,cSrc)

  ;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

  browser = ObjectClrNew( 'HParser.MyParser' )
  return browser

#EndSubRoutine


Return




stanl

Works well. A bit of a slow start, but could be my laptop. Also, single quotes get translated to '

ChuckC

.NET supports the concept of "extension methods" being implemented that are associated with a specific class type.  They are placed into a static class that exists for the purpose of making extension methods available where the name of the class typically starts with the name of the class type that is being extended followed by "Extensions" such that the "String" class would have extensions located in a static class called "StringExtensions".

Within C#, once a "using" statement makes the extension class available in a code module, instances of classes for which extensions are present may simply have those extension methods accessed as if they were instance methods of the class itself.

I know that in PowerShell, extension method resolution isn't possible, so utilizing things like LINQ which implements 1000's of extension methods becomes somewhat tricky as the actual extension classes and their methods must be directly invoked with the "extended" class instance needing to be passed in as a parameter.

I suspect that WinBatch [WIL] would have behavior similar to PowerShell, but I could be mistaken.  Tony could clarify whether or not the WIL CLR hosting implementation can make extension methods available directly within WIL code.

JTaylor

Yes.   Without the Thread stuff the Initial parsing is slow.

Interesting.  I didn't do that :)

Jim

Quote from: stanl on April 06, 2022, 02:42:04 AM
Works well. A bit of a slow start, but could be my laptop. Also, single quotes get translated to '

JTaylor

Thank you.  I was just talking to my son about this possibility.  This gives me some terms for which to search.   I would, obviously, prefer attaching my methods to an appropriate class.

Jim

Quote from: ChuckC on April 06, 2022, 05:52:36 AM
.NET supports the concept of "extension methods" being implemented that are associated with a specific class type.  They are placed into a static class that exists for the purpose of making extension methods
I suspect that WinBatch [WIL] would have behavior similar to PowerShell, but I could be mistaken.  Tony could clarify whether or not the WIL CLR hosting implementation can make extension methods available directly within WIL code.

ChuckC

Here's some functional C# examples of extension methods.  They can apply to both classes and structs.


using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;


namespace MyExtensions
{
    public static class GuidExtensions
    {
        public static bool IsEmptyGUID(this Guid _This)
        {
            return (0 == Guid.Empty.CompareTo(_This));
        }
    }


    public static class StringExtensions
    {
        public static bool IsEmptyOrWhiteSpace(this string _This)
        {
            if (_This is null) return false;


            try
            {
                return (string.IsNullOrEmpty(_This) || string.IsNullOrWhiteSpace(_This));
            }
            catch (Exception ex)
            {
                throw new Exception($"StringExtensions.IsEmptyOrWhiteSpace() - Exception occurred!", ex);
            }
        }


        public static bool StartsWithAny(this string _This, IEnumerable<string> PrefixesIn)
        {
            try
            {
                if (PrefixesIn?.Any() ?? false)
                {
                    foreach (var prefix in PrefixesIn)
                    {
                        if (string.IsNullOrEmpty(prefix)) continue;

                        if (_This?.StartsWith(prefix, StringComparison.CurrentCulture) ?? false) return true;
                    }
                }


                return false;
            }
            catch (Exception ex)
            {
                throw new Exception($"StringExtensions.StartsWithAny() - Exception occurred!", ex);
            }
        }


        public static bool StartsWithAny(this string _This, IEnumerable<string> PrefixesIn, StringComparison ComparisonTypeIn)
        {
            try
            {
                if (PrefixesIn?.Any() ?? false)
                {
                    foreach (var prefix in PrefixesIn)
                    {
                        if (string.IsNullOrEmpty(prefix)) continue;

                        if (_This?.StartsWith(prefix, ComparisonTypeIn) ?? false) return true;
                    }
                }


                return false;
            }
            catch (Exception ex)
            {
                throw new Exception($"StringExtensions.StartsWithAny() - Exception occurred!", ex);
            }
        }


        public static bool StartsWithAny(this string _This, IEnumerable<string> PrefixesIn, bool IgnoreCaseIn, CultureInfo CultureIn)
        {
            try
            {
                if (PrefixesIn?.Any() ?? false)
                {
                    foreach (var prefix in PrefixesIn)
                    {
                        if (string.IsNullOrEmpty(prefix)) continue;

                        if (_This?.StartsWith(prefix, IgnoreCaseIn, CultureIn) ?? false) return true;
                    }
                }


                return false;
            }
            catch (Exception ex)
            {
                throw new Exception($"StringExtensions.StartsWithAny() - Exception occurred!", ex);
            }
        }
    }
}


Usage example:

var g1 = Guid.Empty;

var g2 = Guid.NewGuid();

var rc = false;

rc = g1.IsEmptyGUID();

rc = g2.IsEmptyGUID();

var s1 = "Prefix";

var s2 = "Suffix";

string[] items1 = { "Any", "Old", "Word" };

string[] items2 = { "Pre", "Suf" };

rc = s1.StartsWithAny(items1);

rc = s1.StartsWithAny(items2);

rc = s2.StartsWithAny(items1);

rc = s2.StartsWithAny(items2);



JTaylor

I was in the middle of posting when it told me there was a new post...

Was going to say that "extension methods" do work.   Don't know yet if I can make them do what I want but there is a possibility.   Read enough to try a simple example and now back to read the rest.

For any other interested parties....
      https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods

Thanks again.

Jim

JTaylor

It doesn't seem to work outside the C# code but I could be missing something.   :'(  :'(  :'(

Perhaps Tony can shed some light on whether it will work or not???

Thanks again.

Jim

ChuckC

That's what I was referring to earlier regarding Tony weighing in on how the WIL CLR hosting implementation handles the resolution of extension methods.


JTaylor

I know...I was just adding my voice to the request :)

Jim

td

It's a cute IL compiler trick. I could be wrong but I doubt it is something supported by the CLR hosting interfaces used by WIL. Static methods drifting the IL void don't sound promising anyway
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Quote from: JTaylor on April 06, 2022, 12:02:48 PM
I know...I was just adding my voice to the request :)

Jim


Best of luck. Unfortunately I have to go back to large REST requests and Json returns. Also, asked to look into Node.JS...

JTaylor

Oh well.  Would have been nice.

Thanks all.

Jim

JTaylor

The following is similar to the issues I have had in the past where the Shell.Explorer control would hang up unless I used a Display() or Message() call.   I know the WB folks took action to solve this problem and even changed Display() so it would not display when used with certain parameters as a way around the problem.   Any suggestions for c# code to accomplish the same thing.  The following works fine if I pop-up a message but never leaves the loop if I don't.   How can I unclog the pipes?  Thanks.

Jim


WebBrowser wbc = new WebBrowser();
wbc.ScriptErrorsSuppressed = true;
wbc.DocumentText = "Hello World"; 
wbc.Navigate((string)url);

while (wbc.ReadyState != WebBrowserReadyState.Complete && wbc.ReadyState != WebBrowserReadyState.Interactive)
   {
   // MessageBox.Show(wbc.ReadyState.ToString());
      Thread.Sleep(300);
   }
      this.RetString = wbc.Document.GetElementById("centerCol").OuterHtml;
      MessageBox.Show(this.RetString);

stanl

To be honest [or AKA Stupid] I have no idea what your goal is. Activating a 'Hello World'?

JTaylor

I am navigating to "url".

Probably should have posted more.   Not sure if the DocumentText was needed.   The original script wrote the submitted HTML to the page.   I am back to seeing if I can navigate to a URL and return a portion of the page.   I can't return an object with success but I can return the string results of Method calls.



Jim

stanl

I was reminded of the thread about using Agility Pack. That would beef up the C# code.

JTaylor

Yes, but was trying to avoid any dependencies.   

Jim