In my classic ASP site I need to call COM object function.
Here is the COM component definition:
interface IMyComponent : IDispatch
{
HRESULT GetVersion([in] int, [out] double*, [out] BSTR*);
}
In server side I create component object and try to call 'GetVersion' function:
<%
Dim app
Set app = CreateObject("MyComponent")
Dim someUsefulValue
Dim version
app.GetVersion 1, someUsefulValue, version
%>
But this code fails with error "Type mismatch".
How I should call this function?
first of all, keep in mind that no other browser supports ActiveX rather than Internet Explorer, so I would re-think if you shouldn't get other approach to the problem, maybe using other component that is more open to other browsers...
like Microsoft Silverlight (if you are going the .NET way), Adobe Flash, Shockwave, Air...
in HTML
Your ASP page needs to have the <object> code of your ActiveX
<OBJECT ID="myActiveX "
CLASSID="clsid: yourControlId">
</OBJECT>
then you just act as a normal DOM object
var myActiveX = document.getElementById("myObject");
alert( myActiveX.GetVersion(...) );
Change the type of first parameter of the COM method to long, rather than int. Long translates to the variant type VT_I4, while int translates to VT_INT. If memory serves me right, VBScript doesn't recognize VT_INT as it's not an "automation compatible type" (the size of int may not be fixed across compilers/platforms!)
Try:
<%
Dim app
Set app = Server.CreateObject("MyComponent")
Dim someUsefulValue
Dim version
app.GetVersion 1, someUsefulValue, version
%>
On the server side you should use Server.CreateObject, not just CreateObject as it is normally used for client side VBScript.
Make sure the COM object has been installed and registered using regsvr32 MyComponent.dll
Related
I have a Xamarin.Forms app. It includes a button like this:
<Button x:Name="Buy_Button" Text="Satın Al" FontAttributes="Bold" TextColor="#e2e2e2" BackgroundColor="#2A52BE" FontFamily="Segoe UI" Grid.Column="2" Grid.ColumnSpan="1" Grid.RowSpan="1" CornerRadius="5" VerticalOptions="Start" HorizontalOptions="Center" FontSize="15.667" Grid.Row="0" Margin="0,10,10,0" Clicked="Buy_Button_ClickedAsync" CommandParameter="{Binding Buy_URL}" />
I'm sending a URL link to click event for opening specific web page. Code is:
private async void Buy_Button_ClickedAsync(object sender, EventArgs e)
{
Button btn = (Button)sender; // Coming button from click event handler.
var buylink = btn.CommandParameter.ToString(); // Get the CommandParameter.
// await DisplayAlert("Satın alma linki", buylink, "Anladım"); // Show the link.
try // Uwp & iOS & Android
{
await Browser.OpenAsync(new Uri(buylink), BrowserLaunchMode.SystemPreferred); // Open url in-app browser for iOS & Android- native in UWP
}
catch (NotImplementedInReferenceAssemblyException ex) //Wasm falls here because lack of Xamarin.Essentials.
{
// await DisplayAlert("Hata", ex.Message, "Anladım"); // Show the info about exception.
// Jint - nt is a Javascript interpreter for .NET which provides full ECMA 5.1 compliance and can run on any .NET platform.
//Because it doesn't generate any .NET bytecode nor use the DLR it runs relatively small scripts faster.
//https://github.com/sebastienros/jint
var engine = new Engine();
engine.SetValue("log", new Action<object>(Console.WriteLine));
engine.Execute(#"function openurl() { log('" + buylink + "'); }; openurl(); ");
}
}
In UWP, Xamarin.iOS and Xamarin. Android this code is running via Xamarin.Esssentials:
await Browser.OpenAsync(new Uri(buylink), BrowserLaunchMode.SystemPreferred); // Open url in-app browser for iOS & Android- native in UWP
However, my Xamarin.Forms app projected to WebAssembly code with Uno Platform, so this code block not running. As a result. I install Jint to Xamarin.Forms app. This catch block prints the link to Browser console, but no window.open function track in API reference:
catch (NotImplementedInReferenceAssemblyException ex) //Wasm falls here because lack of Xamarin.Essentials.
{
// await DisplayAlert("Hata", ex.Message, "Anladım"); // Show the info about exception.
// Jint - nt is a Javascript interpreter for .NET which provides full ECMA 5.1 compliance and can run on any .NET platform.
//Because it doesn't generate any .NET bytecode nor use the DLR it runs relatively small scripts faster.
//https://github.com/sebastienros/jint
var engine = new Engine();
engine.SetValue("log", new Action<object>(Console.WriteLine));
engine.Execute(#"function openurl() { log('" + buylink + "'); }; openurl(); ");
}
}
How can I open WebBrowser page on WASM via Javascript form Xamarin.Forms C# code? Thanks.
2 things:
1. Use the browser!
On Wasm, you're running in a webassembly environment, which is running in a javascript virtual machine (that's not totally accurate, but close enough for my point). That means you can directly invoke the javascript of the running environment (browser).
Making a call to native javascript...
WebAssemblyRuntime
.InvokeJS("(function(){location.href=\"https://www.wikipedia.com/\";})();");
In your case, since you want to open a browser window, it's required to use this approach, because Jint can't access anything from the browser itself.
2. You can still call Jint anyway (but not to open a new window)
If you still want to call code using Jint (because you can!!), you need to exclude the Jint.dll assembly from the linking process. Probably because it's using reflection to operate. Again, it won't work to open a window as you're asking, but if you need to call Jint for any other reason, it will work as on other platforms!
Add this to your LinkerConfig.xml (in the Wasm project):
<assembly fullname="Jint" />
Also... You gave me an idea and I did something cool with Jint...
I put the entire solution there: https://github.com/carldebilly/TestJint
It works, even on Wasm:
Interesting code:
https://github.com/carldebilly/TestJint/blob/master/TestJint/TestJint.Shared/MainPage.xaml.cs#L18-L40
private void BtnClick(object sender, RoutedEventArgs e)
{
void Log(object o)
{
output.Text = o?.ToString() ?? "<null>";
}
var engine = new Engine()
.SetValue("log", new Action<object>(Log));
engine.Execute(#"
function hello() {
log('Hello World ' + new Date());
};
hello();
");
#if __WASM__
output2.Text =
WebAssemblyRuntime.InvokeJS("(function(){return 'Hello World ' + new Date();})();");
#else
output2.Text = "Not supported on this platform.";
#endif
}
Final Note
On UWP/WinUI XAML, you can directly put a <Hyperlink /> in your XAML. I'm not familiar enough with Xamarin Forms to know if there's an equivalent.
I am using Device.OpenUri and it works in WASM with Xamarin.Forms
Device.OpenUri(new Uri("https://www.bing.com"));
I have testing environment which is perfectly working with chrome driver in desktop mode. I am using some javascript injections (everything works) f.e.:
public static void ForceFillInput(this Driver driver, string selector, string value)
{
var javaScriptExecutor = (IJavaScriptExecutor)driver.webDriver;
javaScriptExecutor.ExecuteScript($"$(\"{selector}\").val(\"{value}\")");
}
but when i want to run it in headless mode
AddArguments("--headless")
it will just fail on
"$ is not defined"
Can somebody help me how to inject js/jquery into headless solution?
M.
your Javascript snippet used jQuery api. In modern web development, we put Javascript at the end of HTML page to let browser to load javascript at last, so that static resources (like picture/image/text content) can display earlier as possible, withing this way to improve user experience when user open website.
I think your page also put jQuery at the end to load, try add some wait/sleep before ExecuteScript to wait browser complete load jQuery.
It looks like the shorthand for JQuery is not yet created at the time your script is executed.
Use a waiter to wait for JQuery and for the selector to be found:
public static void ForceFillInput(this Driver driver, string selector, string value)
{
string JS_SET_VALUE =
"var e; return !!window.$ && (e = window.$(arguments[0])).length > 0 && (e.val(arguments[1]), true);";
new WebDriverWait(driver, TimeSpan.FromSeconds(60))
.until(ctx => (bool)((IJavaScriptExecutor)ctx).ExecuteScript(JS_SET_VALUE, selector, value));
}
I am a iOS Developer, am new to javascript.
I wants to create a communication between Javascript to Objective C and Objective C to Javascript.
How to pass a variable from javascript to objective C and Objective C to Javasctipt in ios.
If any one have references please let us know about this?
I program JavaScript when using Parse CloudCode. In my case, I use CloudCode to call the Stripe API.
For example:
Objective-C
NSDictionary *parameters = #{
#"customerId": stripeCustomerId,
#"amount": #(100),
};
[PFCloud callFunctionInBackground:#"chargeCustomer" withParameters:parameters block:block];
JavaScript
Parse.Cloud.define("chargeCustomer", function(request, response) {
Stripe.Charges.create({
amount: request.params.amount, // in cents
currency: "usd",
customer: request.params.customerId,
},{
success: function (httpResponse) {
console.log(httpResponse);
response.success(httpResponse);
},
error: function (httpResponse) {
console.error(httpResponse.message);
response.error(httpResponse.message);
}
});
});
As you can see, to pass on the variable from objective-c to javascript in this case, you use request.params.
If you are targeting iOS8, you could consider to use WKWebView rather than UIWebView, which has considerably improved in this regard. Good starting points are the the WKWebView reference docs and this NSHipster article.
You can use native iOS objects to do this.
From Obj-C to JS
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
It injects or calls pre-existing method/object in the page loaded in the UIWebview. It returns the value that JS return to you
UIWebView Class Reference
From JS to Obj-C
Implementing UIWebView protocol you can handle the request before it will start:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest (NSURLRequest *)request navigationType (UIWebViewNavigationType)navigationType
So, from JS you have to call a URL with a custom schema http such as test://. Then you will parse the request in the delegate method I wrote before.
Given the rise of Javascript in Windows 8, does Windows 8 / .Net 4.5 / VS 2012 provide a mechanism to embed the Chakra javascript engine in application to enable scripting? If so, is there documentation for this somewhere?
There is no mechanism to do this that has been released or talked about. For now, it is available only in IE and to Metro style apps. There isn't even a Windows Scripting Host style exposure of it.
What is it about Chakra that you want in your scripting?
Doesn't IE ActiveX use the same JavaScript engine as IE standalone?
You can simply embed Internet Explorer ActiveX frame and keep it hidden.
Yes, exists.
See: https://github.com/Microsoft/ChakraCore/wiki/Embedding-ChakraCore
using System;
using System.Runtime.InteropServices;
using ChakraHost.Hosting;
public class HelloWorld
{
static void Main() {
JavaScriptRuntime runtime;
JavaScriptContext context;
JavaScriptSourceContext currentSourceContext = JavaScriptSourceContext.FromIntPtr(IntPtr.Zero);
JavaScriptValue result;
// Your script, try replace the basic hello world with something else
string script = "(()=>{return \'Hello world!\';})()";
// Create a runtime.
Native.JsCreateRuntime(JavaScriptRuntimeAttributes.None, null, out runtime);
// Create an execution context.
Native.JsCreateContext(runtime, out context);
// Now set the execution context as being the current one on this thread.
Native.JsSetCurrentContext(context);
// Run the script.
Native.JsRunScript(script, currentSourceContext++, "", out result);
// Convert your script result to String in JavaScript; redundant if your script returns a String
JavaScriptValue resultJSString;
Native.JsConvertValueToString(result, out resultJSString);
// Project script result in JS back to C#.
IntPtr resultPtr;
UIntPtr stringLength;
Native.JsStringToPointer(resultJSString, out resultPtr, out stringLength);
string resultString = Marshal.PtrToStringUni(resultPtr);
Console.WriteLine(resultString);
Console.ReadLine();
// Dispose runtime
Native.JsSetCurrentContext(JavaScriptContext.Invalid);
Native.JsDisposeRuntime(runtime);
}
}
I am trying to use Apple's UIAutomation to write unit tests for an iOS Application that has a server-side component. In order to setup the test server in various states (as well as simulate two clients communicating through my server), I would like to issue HTTP get requests from within my javascript-based test.
Can anyone provide an example of how to either issue HTTP GET requests directly from within UIAutomation javascript tests, or how to invoke a shell script from within my UIAutomation javascript tests?
FWIW, most of the core objects made available by all browsers are missing within the UIAutomation runtime. Try to use XMLHTTPRequest for example and you will get an exception reporting that it cannot find the variable.
Thanks!
Folks,
I was able to work around this by sending HTTP requests to the iOS client to process and return the results in a UIAlertView. Note that all iOS code modifications are wrapped in #if DEBUG conditional compilation directives.
First, setup your client to send out notifications in the event of a device shake. Read this post for more information.
Next, in your iOS main app delegate add this code:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(deviceShakenShowDebug:)
name:#"DeviceShaken"
object:nil];
Then add a method that looks something like this:
- (void) deviceShakenShowDebug:(id)sender
{
if (!self.textFieldEnterDebugArgs)
{
self.textFieldEnterDebugArgs = [[[UITextField alloc] initWithFrame:CGRectMake(0, 0, 260.0, 25.0)] autorelease];
self.textFieldEnterDebugArgs.accessibilityLabel = #"AlertDebugArgsField";
self.textFieldEnterDebugArgs.isAccessibilityElement = YES;
[self.textFieldEnterDebugArgs setBackgroundColor:[UIColor whiteColor]];
[self.tabBarController.selectedViewController.view addSubview:self.textFieldEnterDebugArgs];
[self.tabBarController.selectedViewController.view bringSubviewToFront:self.textFieldEnterDebugArgs];
}
else
{
if ([self.textFieldEnterDebugArgs.text length] > 0)
{
if ([self.textFieldEnterDebugArgs.text hasPrefix:#"http://"])
{
[self doDebugHttpRequest:self.textFieldEnterDebugArgs.text];
}
}
}
}
- (void)requestDidFinishLoad:(TTURLRequest*)request
{
NSString *response = [[[NSString alloc] initWithData:((TTURLDataResponse*)request.response).data
encoding:NSUTF8StringEncoding] autorelease];
UIAlertView *resultAlert =
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Request Loaded",#"")
message:response
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK",#"")
otherButtonTitles:nil] autorelease];
resultAlert.accessibilityLabel = #"AlertDebugResult";
[resultAlert show];
}
This code will add a UITextField to the very top view controller after a shake, slapped right above any navigation bar or other UI element. UIAutomation, or you the user, can manually enter a URL into this UITextField. When you shake the device again, if the text begins with "http" it will issue an HTTP request in code (exercise for the reader to implement doDebugHttpRequest).
Then, in my UIAutomation JavaScript file, I have defined the following two functions:
function httpGet(url, delayInSec) {
if (!delayInSec) delay = 1;
var alertDebugResultSeen = false;
var httpResponseValue = null;
UIATarget.onAlert = function onAlert(alert) {
httpResponseValue = alert.staticTexts().toArray()[1].name();
alert.buttons()[0].tap();
alertDebugResultSeen = true;
}
var target = UIATarget.localTarget();
var application = target.frontMostApp();
target.shake(); // bring up the input field
application.mainWindow().textFields()["AlertDebugArgsField"].setValue(url);
target.shake(); // send back to be processed
target.delay(delayInSec);
assertTrue(alertDebugResultSeen);
return httpResponseValue;
}
function httpGetJSON(url, delayInSec) {
var response = httpGet(url, delayInSec);
return eval('(' + response + ')');
}
Now, in my javascript file, I can call
httpGet('http://localhost:3000/do_something')
and it will execute an HTTP request. If I want JSON data back from the server, I call
var jsonResponse = httpGetJSON('http://localhost:3000/do_something')
If I know it is going to be a long-running call, I call
var jsonResponse = httpGetJSON('http://localhost:3000/do_something', 10 /* timeout */)
I've been using this approach successfully now for several weeks.
Try performTaskWithPathArgumentsTimeout
UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", "http://google.com", 30);
Just a small correction. The answer that suggests using UIATarget.host().performTaskWithPathArgumentsTimeout is an easy way to make a request on a URL in iOS 5.0+, but the syntax of the example is incorrect. Here is the correct way to make this call:
UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", ["http://google.com"], 30);
The "[" around the "args" param is important, and the test will die with an exception similar to the following if you forget the brackets:
Error: -[__NSCFString count]: unrecognized selector sent to instance
Here is a fully working example that hits google.com and logs all the output:
var result = UIATarget.host().performTaskWithPathArgumentsTimeout("/usr/bin/curl", ["http://www.google.com"], 30);
UIALogger.logDebug("exitCode: " + result.exitCode);
UIALogger.logDebug("stdout: " + result.stdout);
UIALogger.logDebug("stderr: " + result.stderr);
+1 for creative use of "shake()". However, that's not an option for some projects, especially those that actually use the shake feature.
Think outside the box. Do the fetching with something else (Python, Ruby, node.js, bash+wget, etc). Then, you can use the pre-canned response and auto-generate the ui-test.js on the fly by including that dynamically generated json payload as the "sample data" into the test. Then you simply execute the test.
In my opinion, the test is the test, leave that alone. The test data you are using, if it's that dynamic, it ought to be separated from the test itself. By doing it this way of fetching / generating JSON, and referencing it from the test, you can update that JSON however often you like, either immediately right before every test, or on a set interval like when you know the server has been updated. I'm not sure you would want to generate it while the test is running, that seems like it would create problems. Taking it to the next level, you could get fancy and use functions that calculate what values ought to be based on other values, and expose them as "dynamic properties" of the data, rather than that math being inside the test, but at that point I think the discussion is more of an academic one rather than the practical one of how.
Apple has recently updated UIAutomation to include a new UIAHost element for performing a task on the Host that is running the instance of Instruments that is executing the tests.