I'm migrating an install script from js to vb.net and I'm facing the following problem.
I'm having issues as JS is late-binded so I need to research the datatype returned by each method in order to make the strong typed counterpart in vb.net (or C# for the matter)
In the original js install script, I'm getting to a point where I don't know how to port this 2 calls:
var objWMIService = GetObject("winmgmts:\\\\.\\root\\cimv2");
var objAccount = objWMIService.Get("Win32_SID.SID='S-1-1-0'");
If I leave data type inference, I get COMType, so I can't call the Get method from the generated object.
I think I could solve this by using IDispatch, but It's been like 10 years since I used IDispatch and I can't rememeber exactly how to do it.
Also, after further research, I've seen that the internal COM is actually a SWBemServicesEX object, which I don't know what to reference in order to generate a COM interop system.
I would appreciate it a lot, if anyone can provide any ideas or solutions to this issue.
Current vb.NET code is just:
Dim objWMIService = GetObject("winmgmts:\\.\root\cimv2")
not sure how to be able to call the Get method from objWMIService, and how to determine what this method actually returns!
I ended doing what Steve says in his answer and it solved the issue for me. I'm not very happy with runtime late binding, but it gets the job done!
for reference:
Try using Dim objWMIService as Object = GetObject("winmgmts:\.\root\cimv2") instead. Then you can use Dim objAccount as Object = objWMIService.Get("Win32_SID.SID='S-1-1-0'"). When doing late-binding, declare everything as an object. You can then step through the code in debug and sometimes see what the return is. Then search for the methods/properties/etc for that type and write your next line. Takes a little work but you don't need references to any dlls. Theres just an assumption that the dll are registered (COM) or in your path that .Net follows (CLR)
Related
Some Background:
I've been looking for a way to programmatically create a pdf from a collection of images. It’s possible to do 90% of what I need through Word automation, but the problem is you can’t disable JPEG conversion when exporting to a PDF. Originally, I had hoped there’d be a free command line utility out there, but that’s not the case.
The best thing I could find is the JavaScript library jsPDF. I know almost nothing about Javascript, but library seems easy enough to use from the documentation.
This page has an extremely basic example of using JavaScript with VBA. Sadly there’s very little information out there on doing this kind of thing.
The only relevant thing I could find on Stackoverflow is this one unresolved post. I attempted the same method here and not surprisingly, it didn’t work. I get an error stating saying “syntax error” on the add code line.
Sub PDF1()
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim script As String
script = fso.OpenTextFile("***\jsPDF-master\src\jspdf.js", 1, False).ReadAll
‘This requires a reference to Microsoft Script Control 1.0
Dim o As New ScriptControl
o.Language = "JScript"
With o
.AddCode script
End With
End Sub
I really doubt this is the right approach. The entire library is probably 20k+ lines of code. Is what I’m trying to do even possible?
Any help would be greatly appreciated. Any other suggestions of alternate methods creating PDFs would also be helpful.
I have learned how to create Javascript callback functions and I have a basic understanding of 'functional programming' since it seems easy enough. I am however, new to javascript and it's syntax and I can't find a good way to test said syntax while in my IntelliJ IDE.
What is it you're doing?
I'm creating a Selenium based tool to click on a webelement, wait for it to reload the page, become stale or wait for a timeout. The reason I'm doing this is to classify webelements into three categories: causes a page reload, becomes stale, doesn't change. To do this I've made a simple javascript script with the JavascriptExecutor that comes with Java. Most of my code is in java and that is the language I am proficient in. I want to learn how to use javascript with java to do the things I want with web pages.
Ok but what specifically is the problem?
I have a javascript callback function:
function test(callback) {callback();}
function Return() {SeleniumTest.isPageReloaded.JavascriptWorking}
window.addEventListener('onload', test(Return));
which is executed inside a Javascript Executor like so:
System.setProperty("webdriver.chrome.driver",
"C:\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
String script = "function test(callback) {callback();}" +
"function Return()" +
"{SeleniumTest.isPageReloaded.JavascriptWorking}" +
"window.addEventListener('onload', test(Return));";
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(script);
Which is basically the Javascript script from before, executing as a String. As you can see I am attempting to call a java class. SeleniumTest is my package, isPageReloaded is the current class and JavascriptWorking is a static method within that class. That static method looks like this:
public static void JavascriptWorking(){
System.out.println("Javascript ran here");
}
Its meant to be a simple way to get something from the javascript to my java code. The reason I tried it this way is because I read this:
https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/bpm-appdev/invoking-java-methods-in-javascript.html
But then I realized that it wouldn't work and I dug deeper. I read that Javascript and Java are seperated by server and client and I gained some insight from this question:
calling java methods in javascript code
However I'm not 100% sure this is accurate to my case since the Javascript I'm executing isn't coming from the webpage I'm testing, Rather I made it myself inside the java code as a String. Additionally I'm still highly confused on if the answer to that question actually applies to me. There is only one and it basically just says, 'install some stuff because java is clientside and javascript is serverside'. I (kindof) understand what those terms mean but I'm not sure that the javascript I made in my class would be considered 'server-side' in fact it would seem to not be that way. What I need is clarification on A: is the javascript I'm running/creating in my java code actually serverside?
B: if yes then can someone give me a basic rundown on how I would go about calling java code from the server? does this require permissions? I assume I have to communicate with said server so does that mean I use GET and POSt requests?
C: If the Javascript Isn't server side then it must be clientside and I should be able to call it pretty easily right? How do I do this?
Show us what exactly you want
I want to be able to run:
System.setProperty("webdriver.chrome.driver",
"C:\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
String script = "function test(callback) {callback();}" +
"function Return()" +
"{//insert callback code here}" +
"window.addEventListener('onload', test(Return));";
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript(script);
and get either a static java method ran, something printed to console, or some other means that links the javascript code to the javacode. So for example if I inserted the correct code to call my static method:
SeleniumTest.IsPageReloaded.JavascriptWorking
(which again looks like):
public static void JavascriptWorking(){
System.out.println("Javascript ran here");
}
Then I'd want to see "Javascript ran here" on my java console. The driver being used is interchangebale, I just used chrome first because its fast. All that this needs is an enclosing main class and It ((should)) be runnable but no promises.
The purpose is to get something in java that I can then use as a flag to know that my asynchronous javascript is done in java and I can continue on with program execution. I can get the async javascript part and I understand it, I just need a link back to my java code.
Possible Solutions
I've been told that the common way to provide a flag for your java code is to create a certain webelement on the page with javascript and test for it in java (hence the link). I don't feel like adding to the webpages I test because I want to test them without actually editing/changing them. I'm generally open to other simple solutions but the biggest thing I need is clarification on the whole clientside serverside issue because its specific to my setup (Selenium java -> javascript -> java) where most questions only cover (javascript -> java) or vice versa.
The link you mentioned about JS invoking Java is for a specific application, that is meant to do that. Not saying it is impossible (I wrote FF plugins based on similar principle), but it is not applicable in this case. It also requires special application support (by default Javascript executed in browser is heavily sandboxed - it can't access anything out of its own scope. Invoking other apps on its own is a big no.).
The scripts you are injecting are always client side, they are executed only in the browser, that is isolated from the java code itself. With that said nothing is impossible.
Would like to mention two interesting features of the Selenium library that can come handy for you.
You mention a magic term many times "async Javascript execution" - and as I can see you are implementing your own version of executeAsyncScript. Webdriver does provide this method out of the box, pretty much for the purpose you want to use it with.
When you use executeScript, it will return pretty much immediately once it finished - in your case it will just inject your listener with your code, and then it returns. Using executeAsyncScript you can get a callback - just what you are doing. When calling executeAsyncScript, a default callback method is added to your code as the last argument, that needs to be called by your JS code for the method to return.
A simple example:
String script = "var callback = arguments[arguments.length - 1];" + //the last argument is the callback function
"var classToCall = 'SeleniumTest.IsPageReloaded';" + //the classname you want to return to call from Java in case of success)
"window.addEventListener('onload', callback(classToCall));";
//you can give any supported return value to the callback function. Here I assume that you want to call a static method. This is the class name that can be used later.
try {
JavascriptExecutor js = (JavascriptExecutor)driver;
//classToCall has the value we passed to the callback function
String classToCall = js.executeAsyncScript(script);
} catch (ScriptTimeoutException e) {
System.err.println("Uhhh... this failed I guess");
e.printStackTrace();
}
The executeAsyncScript does not return until the callback is called - to avoid infinite hangs, you can set the WebDriver.Timeouts.setScriptTimeout property to control this. If the script takes longer, JavascriptExecutor will throw an exception. Once returned, you can instantiate the returned class, and print like
Class clazz = Class.forName(classToCall); //it is only necessary if the classname is dynamic. If it is the same always, you can just go ahead with that.
((IsPageReloaded)clazz.newInstance()).JavascriptWorking();
Of course you can return a more complex datastructure also from the JS where you specify the method name also, but using reflection is really offtopic here.
Take a look at EventFiringWebdriver. This is a useful class that makes use of WebDriverEventListener to create custom Webdriver wrappers, with hooks on many events, allowing you to execute custom code before/after clicking, before/after pageload... and beside some others more importantly before/after executing javascript in the webdriver. You could leverage this to always call the same code around javascript execution - just create your own WebDriverEventListener.
You can find more info on the js executor here, and on WebDriverEventListener here.
I've been serching the net for quite some time and maybe there is no solution for my problem but I hoped you might be able to help me. I'm currently trying to establish a connection to CatiaV5 via JavaScript. The connection itsself is working just fine. Basically it looks like this now:
var catia = new ActiveXObject('CATIA.Application');
var doc = catia.ActiveDocument;
But here's my problem. The returned object is a Collection in VB and there seems to be no DataType equivalent to this. So this is what i get when i try to read my variables. For example:
doc.Product
returns
[object] {};
So this seems to be empty. However if then I try to get
doc.Product.Name
which by that logic should be undefined, instead i get
"Part1"
so the correct name of my Part/Product is returned.
All the Catia stuff probably isn't that relevant for the question.
my question: Is there any way to somehow parse a VB-Collection on a JavaScript object or something similar, to get the contents of what is returned?
OK,
here's the thing. I found out, that you can't really browse throug ActiveXObjects directly in the console in general. In the IE-Dev-Tools i was however able to use the Locals-Watch to browse through the Object. I didn't find a nice way to Parse it onto a JSON-Object, however the manual way to create a new Object and add the Keys piece by piece works.
In our portlet, we are trying to access the language properties in our javascript files using Liferay.Language.get("key").
But Liferay.Language.get("key") returns the key instead of the associated value.
Did any one face similar issue?
We are using Liferay 6.1 EE. And have already seen the LPS-16513
The strangest part is it works on our local boxes but fails on server.
Any pointers other than using ext?
My best guess based on the information you give is that you're asking for a key that does not have a translation associated with it - for these returning the key is the default behaviour.
But then, this question is quite old, you might have already solved it. (If so, please let us know how - if you can remember the cause)
I also can't get it to retrieve a value for a valid key that's specified in a resource bundle in a portlet itself. It will retrieve values for keys in the default Liferay language bundles though. One hack is to add a liferay-hook.xml to your portlet and add something like the following to it:
<language-properties>Language.properties</language-properties>
When I do this it will now retrieve my custom/additional keys. The side effect is that your keys will also be available globally in Liferay.
This does not work for portlet level language.pro.
I have same problem with 6.2 EE too, as an alternative I went for below solution.
<script>
var test = "<liferay-ui:message key='test'/>";
console.log("This is working :: "+test)
</script>
Thank,
Sagar Vyas
You can also get the desired value with the following snippet:
var value='<%=LanguageUtil.get(pageContext, "key") %>';
So, I'm running these Selenium IDE tests against a site I'm working on. Everything about the tests themselves is running fine, except I would like to do a bit of clean-up once I'm done. In my MVC3 Razor based site, I have a JavaScript file with a function that gets a JsonResult from a Controller of mine. That Controller handles the database clean-up that Selenium IDE otherwise couldn't handle.
However, I'm having a hard time finding any sort of documentation on how to do this. I know I can do JavaScript{ myJavascriptGoesHere } as one of the Values for a line in the test, but I can't seem to find a way to tell it to go find my clean-up function.
Is it even possible for Selenium IDE to do this sort of thing?
If it comes down to it, I can just make a separate View to handle the clean-up, but I'd really like to avoid that if possible.
Thanks!
If you want to execute your own JavaScript function that exists in your test page from Selenium IDE, you need to make sure you access it via the window object. If you look at the reference for storeEval for instance, it says:
Note that, by default, the snippet will run in the context of the
"selenium" object itself, so this will refer to the Selenium object.
Use window to refer to the window of your application, e.g.
window.document.getElementById('foo')
So if you have your own function e.g. myFunc(). You need to refer to it as window.myFunc().
This can be very handy for exercising client-side validation without actually submitting the form, e.g. if you want to test a variety of invalid and valid form field values.
If you use runScript, that should already run in the window's context.
This works for me.
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
string title = (string)js.ExecuteScript("myJavascriptGoesHere");
Make sure your javascript works first before using it here!
Actually to access your page javascript space, you need to get the real window of your page : this.browserbot.getUserWindow()
See this statement to get the jQuery entry point in your page (if it has jQuery of course ^^ )
https://stackoverflow.com/a/54887281/2143734