DotNetBrowser v2
10 posts
• Page 1 of 1
DotNetBrowser v2
Hello, the new way with version 2 of DotNetBrowser to execute javascript from .Net is like this:
string title = browser.MainFrame.ExecuteJavaScript<string>("document.title").Result;
The APL signature looks like this:
System.Threading.Tasks.Task`1[T] ExecuteJavaScript[T](System.String, Boolean)
System.Threading.Tasks.Task`1[System.Object] ExecuteJavaScript(System.String, Boolean)
The Visual Studio signature looks like this:
System.Threading.Tasks.Task<string> DotNetBrowser.Frames.IFrame.ExecuteJavaScript<string>(string javaScript, [bool userGesture=false])
Asynchronously executes JavaScript code using the current context and converts the execution result to the specified .NET type.
When I execute the following in APL:
browser.MainFrame.ExecuteJavaScript(⊂'document.title')
I am getting a LENGTH ERROR
Is there a way to make this work ?
Thanks in advance.
string title = browser.MainFrame.ExecuteJavaScript<string>("document.title").Result;
The APL signature looks like this:
System.Threading.Tasks.Task`1[T] ExecuteJavaScript[T](System.String, Boolean)
System.Threading.Tasks.Task`1[System.Object] ExecuteJavaScript(System.String, Boolean)
The Visual Studio signature looks like this:
System.Threading.Tasks.Task<string> DotNetBrowser.Frames.IFrame.ExecuteJavaScript<string>(string javaScript, [bool userGesture=false])
Asynchronously executes JavaScript code using the current context and converts the execution result to the specified .NET type.
When I execute the following in APL:
browser.MainFrame.ExecuteJavaScript(⊂'document.title')
I am getting a LENGTH ERROR
Is there a way to make this work ?
Thanks in advance.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: DotNetBrowser v2
I don't have the thousand dollars to license the product (which looks interesting, to be honest), and don't have the patience to try and install the trial version. But, I think the solution to your problem may be in the C# signature:
System.Threading.Tasks.Task<string> DotNetBrowser.Frames.IFrame.ExecuteJavaScript<string>(string javaScript, [bool userGesture=false])
The second argument is optional. But that's only in C#, because it seems to be implemented using a feature (https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments) only available to the C# language at the moment. From APL, try and specify the second argument as well:
Let us know if it works!
System.Threading.Tasks.Task<string> DotNetBrowser.Frames.IFrame.ExecuteJavaScript<string>(string javaScript, [bool userGesture=false])
The second argument is optional. But that's only in C#, because it seems to be implemented using a feature (https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments) only available to the C# language at the moment. From APL, try and specify the second argument as well:
- Code: Select all
browser.MainFrame.ExecuteJavaScript 'document.title' 0
Let us know if it works!
-
StefanoLanzavecchia - Posts: 113
- Joined: Fri Oct 03, 2008 9:37 am
Re: DotNetBrowser v2
Hello Stefano, thanks for the suggestion. Unfortunately, it is not working. I am getting the following error:
browser.MainFrame.ExecuteJavaScript 'document.title' 0
EXCEPTION: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
browser.MainFrame.ExecuteJavaScript'document.title' 0
∧
Any more suggestions?
browser.MainFrame.ExecuteJavaScript 'document.title' 0
EXCEPTION: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
browser.MainFrame.ExecuteJavaScript'document.title' 0
∧
Any more suggestions?
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: DotNetBrowser v2
Hi Pierre,
This signature reminds me of another question I have seen in our support archives. I will give John Daintree's answer in the hope that it can serve as an example of what to do.
DotNetBrowser.Frames.IFrame.ExecuteJavaScript<string>(string javaScript, [bool userGesture=false])
The question was to translate the following into APL:
spreadSheet.WorkbookPart.AddNewPart<WorksheetPart>();
At that time, John Daintree wrote this:
OK, so this is a bit tricky, because we don’t directly support Generics, which is what all the `1 and <type> and [T] stuff is all about. But we can get there.
ssnew2.WorkbookPart.AddNewPart<WorksheetPart>();
The <WorksheetPart> above indicates that we need to call a version of AddNewPart which returns a WorksheetPart object. In fact the display form of AddNewPart gives us a clue:
wkbpt.AddNewPart
T AddNewPart[T]()
T AddNewPart[T](System.String)
T AddNewPart[T](System.String, System.String)
To call spreadSheet.WorkbookPart.AddNewPart<WorksheetPart>(), what we need to do is define a function that calls the first of these overloads, AND we need to specify that T is WorksheetPart.
MakeGenericMethod to the rescue (https://docs.microsoft.com/en-us/dotnet ... ericmethod)
We want to call the Niladic overload above (the T AddNewPart[T]()), so we use GetMethod to get the Generic definition:
⎕←m1←wkbpt.GetType.GetMethod'AddNewPart' (0⍴⊂⎕null)
T AddNewPart[T]()
We then need to create a concrete version of the generic where T is WorksheetPart. First we need to find the Type of WorksheetPart. Fortunately this is defined in the same assembly as WorkbookPart, which we already have an instance of.
assem←wkbpt.GetType.Assembly
atype←assem.GetType⊂'DocumentFormat.OpenXml.Packaging.WorksheetPart'
Now we can create the concrete function:
⎕←m←m1.MakeGenericMethod (⊂,atype)
DocumentFormat.OpenXml.Packaging.WorksheetPart AddNewPart[WorksheetPart]()
We can then invoke the method m, on the appropriate WorkbookPart with an empty parameter list:
m.Invoke wkbpt ⍬
DocumentFormat.OpenXml.Packaging.WorksheetPart
So, the sequence is:
m1←wkbpt.GetType.GetMethod'AddNewPart' (0⍴⊂⎕null)
atype←wkbpt.GetType.Assembly.GetType⊂'DocumentFormat.OpenXml.Packaging.WorksheetPart'
m←m1.MakeGenericMethod (⊂,atype)
m.Invoke wkbpt ⍬
Regards,
Vince
This signature reminds me of another question I have seen in our support archives. I will give John Daintree's answer in the hope that it can serve as an example of what to do.
DotNetBrowser.Frames.IFrame.ExecuteJavaScript<string>(string javaScript, [bool userGesture=false])
The question was to translate the following into APL:
spreadSheet.WorkbookPart.AddNewPart<WorksheetPart>();
At that time, John Daintree wrote this:
OK, so this is a bit tricky, because we don’t directly support Generics, which is what all the `1 and <type> and [T] stuff is all about. But we can get there.
ssnew2.WorkbookPart.AddNewPart<WorksheetPart>();
The <WorksheetPart> above indicates that we need to call a version of AddNewPart which returns a WorksheetPart object. In fact the display form of AddNewPart gives us a clue:
wkbpt.AddNewPart
T AddNewPart[T]()
T AddNewPart[T](System.String)
T AddNewPart[T](System.String, System.String)
To call spreadSheet.WorkbookPart.AddNewPart<WorksheetPart>(), what we need to do is define a function that calls the first of these overloads, AND we need to specify that T is WorksheetPart.
MakeGenericMethod to the rescue (https://docs.microsoft.com/en-us/dotnet ... ericmethod)
We want to call the Niladic overload above (the T AddNewPart[T]()), so we use GetMethod to get the Generic definition:
⎕←m1←wkbpt.GetType.GetMethod'AddNewPart' (0⍴⊂⎕null)
T AddNewPart[T]()
We then need to create a concrete version of the generic where T is WorksheetPart. First we need to find the Type of WorksheetPart. Fortunately this is defined in the same assembly as WorkbookPart, which we already have an instance of.
assem←wkbpt.GetType.Assembly
atype←assem.GetType⊂'DocumentFormat.OpenXml.Packaging.WorksheetPart'
Now we can create the concrete function:
⎕←m←m1.MakeGenericMethod (⊂,atype)
DocumentFormat.OpenXml.Packaging.WorksheetPart AddNewPart[WorksheetPart]()
We can then invoke the method m, on the appropriate WorkbookPart with an empty parameter list:
m.Invoke wkbpt ⍬
DocumentFormat.OpenXml.Packaging.WorksheetPart
So, the sequence is:
m1←wkbpt.GetType.GetMethod'AddNewPart' (0⍴⊂⎕null)
atype←wkbpt.GetType.Assembly.GetType⊂'DocumentFormat.OpenXml.Packaging.WorksheetPart'
m←m1.MakeGenericMethod (⊂,atype)
m.Invoke wkbpt ⍬
Regards,
Vince
- Vince|Dyalog
- Posts: 440
- Joined: Wed Oct 01, 2008 9:39 am
Re: DotNetBrowser v2
Hello Vince, thanks for the info. Here is what I have tried:
browser.MainFrame.ExecuteJavaScript
System.Threading.Tasks.Task`1[T] ExecuteJavaScript[T](System.String, Boolean)
System.Threading.Tasks.Task`1[System.Object] ExecuteJavaScript(System.String, Boolean)
typeArray←System.Array.CreateInstance(System.Type)(2)
typeArray[0]←System.Type.GetType⊂'System.String'
typeArray[1]←System.Type.GetType⊂'System.Boolean'
typeArray
System.Type[]
browser.MainFrame.GetType.GetMethod'ExecuteJavaScript' typeArray
EXCEPTION: Ambiguous match found.
browser.MainFrame.GetType.GetMethod'ExecuteJavaScript' typeArray
∧
From what I can see the 2 APL signatures are the same so it is normal to get an 'Ambiguous match'.
Is there a way to help the interpreter distinguish between the 2 signatures?
Thanks in advance.
browser.MainFrame.ExecuteJavaScript
System.Threading.Tasks.Task`1[T] ExecuteJavaScript[T](System.String, Boolean)
System.Threading.Tasks.Task`1[System.Object] ExecuteJavaScript(System.String, Boolean)
typeArray←System.Array.CreateInstance(System.Type)(2)
typeArray[0]←System.Type.GetType⊂'System.String'
typeArray[1]←System.Type.GetType⊂'System.Boolean'
typeArray
System.Type[]
browser.MainFrame.GetType.GetMethod'ExecuteJavaScript' typeArray
EXCEPTION: Ambiguous match found.
browser.MainFrame.GetType.GetMethod'ExecuteJavaScript' typeArray
∧
From what I can see the 2 APL signatures are the same so it is normal to get an 'Ambiguous match'.
Is there a way to help the interpreter distinguish between the 2 signatures?
Thanks in advance.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: DotNetBrowser v2
Hello Vince, what I am looking really is using the second signature that has no 'generics':
System.Threading.Tasks.Task`1[T] ExecuteJavaScript[T](System.String, Boolean)
System.Threading.Tasks.Task`1[System.Object] ExecuteJavaScript(System.String, Boolean) ⍝ ← I want to use this one
The second signature has no generics. Is there a way to 'help' the interpreter to use a signature when there are 2 that are identical or ambiguous?
Thanks in advance.
System.Threading.Tasks.Task`1[T] ExecuteJavaScript[T](System.String, Boolean)
System.Threading.Tasks.Task`1[System.Object] ExecuteJavaScript(System.String, Boolean) ⍝ ← I want to use this one
The second signature has no generics. Is there a way to 'help' the interpreter to use a signature when there are 2 that are identical or ambiguous?
Thanks in advance.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: DotNetBrowser v2
Hello Vince, DotNetBrowser's company has suggested me to make a dll wrapper for the ambiguous calls which I did and it is working now.
Let me know if there is a way to resolve those calls in APL without resorting to write a dll wrapper.
Regards,
Pierre Gilbert
Let me know if there is a way to resolve those calls in APL without resorting to write a dll wrapper.
Regards,
Pierre Gilbert
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: DotNetBrowser v2
Pierre, I had a look at this as an exercise and found that you can ignore all the hassle normal C# developers go through and simply explore the methods available in a class by formatting them as text and then picking the one you want.
Instead of:
You can do:
Also, unfortunately you can't invoke the method with a 0 as the second argument for false as this doesn't seem to get automatically converted into a Boolean type. I found you have to explicitly cast it.
Here is a class that on instantiation prepares the engine, browser, method and arguments. In the ExecuteJS method, it simply replaces the first argument with the statement passed in and then invokes the method call and waits for the result.
And then you use it like this:
Instead of:
- Code: Select all
typeArray←System.Array.CreateInstance(System.Type)(2)
typeArray[0]←System.Type.GetType⊂'System.String'
typeArray[1]←System.Type.GetType⊂'System.Boolean'
browser.MainFrame.GetType.GetMethod'ExecuteJavaScript' typeArray
You can do:
- Code: Select all
methods_txt←⍕¨methods←browser.MainFrame.GetType.GetMethods ⍬
ind←1⍳⍨∨/'[System.Object] ExecuteJavaScript(System.String, Boolean)'⍷↑methods_txt
MethodInfo←ind⊃methods
Also, unfortunately you can't invoke the method with a 0 as the second argument for false as this doesn't seem to get automatically converted into a Boolean type. I found you have to explicitly cast it.
Here is a class that on instantiation prepares the engine, browser, method and arguments. In the ExecuteJS method, it simply replaces the first argument with the statement passed in and then invokes the method call and waits for the result.
- Code: Select all
:Class DotNetBrowserAPL
:Using System
:Using ,.\DotNetBrowser.dll
:Using ,.\DotNetBrowser.Core.dll
∇ make;methods;methods_txt;ind
:Access Public
:Implements Constructor
Engine←DotNetBrowser.Engine.EngineFactory.Create ⍬
Browser←Engine.CreateBrowser
methods_txt←⍕¨methods←Browser.MainFrame.GetType.GetMethods ⍬
ind←1⍳⍨∨/'[System.Object] ExecuteJavaScript(System.String, Boolean)'⍷↑methods_txt
MethodInfo←ind⊃methods
Args←Array.CreateInstance Object 2
(Args.SetValue⍠('CastToTypes'(Boolean Int32)))0 1
∇
∇ r←ExecuteJS statement;res
:Access Public
Args.SetValue (,statement) 0
res←MethodInfo.Invoke Browser.MainFrame Args
r←res.Result
∇
:EndClass
And then you use it like this:
js←⎕NEW DotNetBrowserAPL
js.ExecuteJS'1+2+3'
6
- gil
- Posts: 73
- Joined: Mon Feb 15, 2010 12:42 am
Re: DotNetBrowser v2
Thanks Gil, it's working. You are a lifesaver.
-
PGilbert - Posts: 440
- Joined: Sun Dec 13, 2009 8:46 pm
- Location: Montréal, Québec, Canada
Re: DotNetBrowser v2
Ah, that's great, Gil! Thanks.
I will take note of this example for others in the future.
Regards,
Vince
I will take note of this example for others in the future.
Regards,
Vince
- Vince|Dyalog
- Posts: 440
- Joined: Wed Oct 01, 2008 9:39 am
10 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group