Quantcast
Are you the publisher? Claim or contact us about this channel


Embed this content in your HTML

Search

Report adult content:

click to rate:

Account: (login)

More Channels


Showcase


Channel Catalog



Channel Description:

ClearScript is a library that makes it easy to add scripting to your .NET applications. It currently supports JavaScript (via V8 and JScript) and VBScript.

older | 1 | .... | 19 | 20 | (Page 21) | 22 | 23 | .... | 115 | newer

    0 0
  • 01/29/14--08:06: Updated Wiki: Home
  • Description

    ClearScript is a library that makes it easy to add scripting to your .NET applications. It currently supports JavaScript (via V8 and JScript) and VBScript.

    Features

    • Simple usage; create a script engine, add your objects and/or types, run scripts
    • Support for several script engines: Google's V8, Microsoft's JScript and VBScript
    • Exposed resources require no modification, decoration, or special coding of any kind
    • Scripts get simple access to most of the features of exposed objects and types:
      • Methods, properties, fields, events
      • (Objects) Indexers, extension methods, conversion operators, explicitly implemented interfaces
      • (Types) Constructors, nested types
    • Full support for generic types and methods, including C#-like type inference and explicit type arguments
    • Scripts can invoke methods with output parameters, optional parameters, and parameter arrays
    • Script delegates enable callbacks into script code
    • Support for exposing all the types defined in one or more assemblies in one step
    • Optional support for importing types and assemblies from script code
    • The host can invoke script functions and access script objects directly
    • Full support for script debugging

    Examples

    using System;
    using Microsoft.ClearScript;
    using Microsoft.ClearScript.V8;
    
    // create a script engineusing (var engine = new V8ScriptEngine())
    {
        // expose a host type
        engine.AddHostType("Console", typeof(Console));
        engine.Execute("Console.WriteLine('{0} is an interesting number.', Math.PI)");
    
        // expose a host object
        engine.AddHostObject("random", new Random());
        engine.Execute("Console.WriteLine(random.NextDouble())");
    
        // expose entire assemblies
        engine.AddHostObject("lib", new HostTypeCollection("mscorlib", "System.Core"));
        engine.Execute("Console.WriteLine(lib.System.DateTime.Now)");
    
        // create a host object from script
        engine.Execute(@"
            birthday = new lib.System.DateTime(2007, 5, 22);
            Console.WriteLine(birthday.ToLongDateString());
        ");
    
        // use a generic class from script
        engine.Execute(@"
            Dictionary = lib.System.Collections.Generic.Dictionary;
            dict = new Dictionary(lib.System.String, lib.System.Int32);
            dict.Add('foo', 123);
        ");
    
        // call a host method with an output parameter
        engine.AddHostObject("host", new HostFunctions());
        engine.Execute(@"
            intVar = host.newVar(lib.System.Int32);
            found = dict.TryGetValue('foo', intVar.out);
            Console.WriteLine('{0} {1}', found, intVar);
        ");
    
        // create and populate a host array
        engine.Execute(@"
            numbers = host.newArr(lib.System.Int32, 20);
            for (var i = 0; i < numbers.Length; i++) { numbers[i] = i; }
            Console.WriteLine(lib.System.String.Join(', ', numbers));
        ");
    
        // create a script delegate
        engine.Execute(@"
            Filter = lib.System.Func(lib.System.Int32, lib.System.Boolean);
            oddFilter = new Filter(function(value) {
                return (value & 1) ? true : false;
            });
        ");
    
        // use LINQ from script
        engine.Execute(@"
            oddNumbers = numbers.Where(oddFilter);
            Console.WriteLine(lib.System.String.Join(', ', oddNumbers));
        ");
    
        // use a dynamic host object
        engine.Execute(@"
            expando = new lib.System.Dynamic.ExpandoObject();
            expando.foo = 123;
            expando.bar = 'qux';
            delete expando.foo;
        ");
    
        // call a script function
        engine.Execute("function print(x) { Console.WriteLine(x); }");
        engine.Script.print(DateTime.Now.DayOfWeek);
    
        // examine a script object
        engine.Execute("person = { name: 'Fred', age: 5 }");
        Console.WriteLine(engine.Script.person.name);
    }

    0 0

    I would like to expose an open method on my c# object that I am exposing to ClearScript. The open method signature would look like this
        public void open(string address, Action<dynamic> callback)
        {
            if (callback != null)
            {
                callback("success");
            }
        }
    
    And calling it from script like this
    page.open('http://www.cnn.com', function(status) { 
        // do somthing here with status
    });

    0 0

    Hello!

    On the .NET side you can access JavaScript objects, including functions, using the dynamic keyword. For example, you can define your class like this:
    publicclass Page {
        publicvoid open(string address, dynamic callback) {
            if (callback != null) {
                callback("success");
            }
        }
    }
    and then use it like this:
    engine.AddHostObject("page", new Page());
    engine.AddHostType("Console", typeof(Console));
    engine.Execute(@"
        page.open('http://www.cnn.com', function(status) {
            Console.WriteLine(status);
        });
    ");
    You can also set up a .NET delegate that calls a script function. This makes it possible to plug script code into an existing API that doesn't use dynamic. For example, if your class is already defined like this:
    publicclass Page {
        publicvoid open(string address, Action<string> callback) {
            if (callback != null) {
                callback("success");
            }
        }
    }
    you can use it from script code like this:
    engine.AddHostObject("page", new Page());
    engine.AddHostType("Console", typeof(Console));
    engine.AddHostType("OpenCallback", typeof(Action<string>));
    engine.Execute(@"
        page.open('http://www.cnn.com', new OpenCallback(function(status) {
            Console.WriteLine(status);
        }));
    ");
    Thanks for your question, and good luck!

    0 0

    Perfect. That did the trick. Thanks

    0 0

    We are building a bridge between CEF and C#. The C# console app is driven by javascript code. Used to basically drive a headless browser. So far clerscript has been a great tool. I was wondering if it is possible to pull the string content of a passed in JavaScript function...so I can then inject that back into the headless browser.

    For example in my C# class I would have this code
        public void execute(dynamic function)
        {
            //Parse function into string and inject back into CEF Browser frame
        }
    
    And the script driving all this looks like this
    ...
    ...
        page.open(address, function(status) { 
    
          if(status != "success")
          {
            console.log("Load failed");
            chromejs.exit(2);
          }
    
          // TRYING TO MAKE THIS PART WORK
          page.execute(function() {
            return document.title;
          });
    
          page.render("test.png");
          chromejs.exit();  
        });

    0 0

    I have code that executes fine on my machine with Visual Studio installed but have passed the code (compiled) including ClearScript.DLL to someone else who is getting an error when the script runs. I have tracked it down that if I remove the EnableDebugging I do not see the crash. But I need this option to get Column and Line numbers for errors in user scripts.

    Is this crash caused by a lack of VS on the other machine? If so how do I work around this? I ONLY have the debug option enabled for line and column numbers (running v5.3.9 - not yet tried v5.3.11 as I cannot reproduce so need my colleague to run with latest DLL!)

    Stack Trace Info below
    at System.Activator.CreateInstance(Type type, Boolean nonPublic)
    at Microsoft.ClearScript.Windows.ProcessDebugManagerWrapper32..ctor()
    at Microsoft.ClearScript.Windows.ProcessDebugManagerWrapper.Create()
    at Microsoft.ClearScript.Windows.WindowsScriptEngine.<>c__DisplayClass2.<.ctor>b__0()
    at Microsoft.ClearScript.ScriptEngine.ScriptInvoke[T](Func`1 func)
    at Microsoft.ClearScript.Windows.WindowsScriptEngine..ctor(String progID, String name, WindowsScriptEngineFlags flags)
    at Microsoft.ClearScript.Windows.VBScriptEngine..ctor(String progID, String name, WindowsScriptEngineFlags flags)
    at Microsoft.ClearScript.Windows.VBScriptEngine..ctor(String name, WindowsScriptEngineFlags flags)
    MY ENTRY POINT -> at Configurator.ScriptProcessor.EnableAPI(API api)


    Comments: I ran into this today, too. > We do feel that ClearScript should transition gracefully into non-debug mode when a debugger is not present Agreed. But figuring out a way to get error information (line number, etc) without a debugger present would be better. Even some information (not necessarily stack info) would be nice.

    0 0

    Greetings!

    I was wondering if it is possible to pull the string content of a passed in JavaScript function

    Do you mean the function's JavaScript source code? If so, then you can use JavaScript's Function.prototype.toString():
    publicvoid execute(dynamic function) {
        string sourceCode = function.toString();
        Console.WriteLine(sourceCode);
    }
    Cheers!

    0 0

    I am looking to access the variables within the local scope of a script frame (on the stack?). I haven't found a way to do this with ClearScript yet. Does anyone know if this is possible?

    For ClearScript devs, here is a post on possibly how to implement it:
    http://stackoverflow.com/questions/13007838/google-v8-access-local-variables-in-c

    Thanks a bunch!

    0 0

    I have code that executes fine on my machine with Visual Studio installed but have passed the code (compiled) including ClearScript.DLL to someone else who is getting an error when the script runs. I have tracked it down that if I remove the EnableDebugging I do not see the crash. But I need this option to get Column and Line numbers for errors in user scripts.

    Is this crash caused by a lack of VS on the other machine? If so how do I work around this? I ONLY have the debug option enabled for line and column numbers (running v5.3.9 - not yet tried v5.3.11 as I cannot reproduce so need my colleague to run with latest DLL!)

    Stack Trace Info below
    at System.Activator.CreateInstance(Type type, Boolean nonPublic)
    at Microsoft.ClearScript.Windows.ProcessDebugManagerWrapper32..ctor()
    at Microsoft.ClearScript.Windows.ProcessDebugManagerWrapper.Create()
    at Microsoft.ClearScript.Windows.WindowsScriptEngine.<>c__DisplayClass2.<.ctor>b__0()
    at Microsoft.ClearScript.ScriptEngine.ScriptInvoke[T](Func`1 func)
    at Microsoft.ClearScript.Windows.WindowsScriptEngine..ctor(String progID, String name, WindowsScriptEngineFlags flags)
    at Microsoft.ClearScript.Windows.VBScriptEngine..ctor(String progID, String name, WindowsScriptEngineFlags flags)
    at Microsoft.ClearScript.Windows.VBScriptEngine..ctor(String name, WindowsScriptEngineFlags flags)
    MY ENTRY POINT -> at Configurator.ScriptProcessor.EnableAPI(API api)


    Comments: Unfortunately, as far as we can tell, JScript and VBScript report only error messages when debugging is disabled. They report no further details, and the stack collection APIs simply fail. We'll keep looking, but if the only solution is to develop a script debugger, then it would make little sense for us to do so, since mature and powerful freeware debuggers are available.

    0 0

    Hi joshrmt,

    This is currently not possible and is rather unlikely as V8 has no public APIs that would enable it (the code on StackOverflow uses internal interfaces), but just in case, can you describe your scenario? Are you developing a debugger?

    Thanks!

    0 0

    Hi,

    I may be missing something obvious, but this call fails on a V8ScriptEngine:
    engine.AddHostObject("test", "hello");
    Feeling like a noob... :)
    Thanks for your help!

    0 0

    Hello!

    That's correct; ScriptEngine.AddHostObject() does not work with simple values like strings and numbers.

    Instead, you can do any of the following:
    engine.Script.test = "hello";
    engine.Script["test"] = "hello";
    engine.Execute("test = 'hello'");
    Cheers!

    0 0
  • 02/05/14--21:12: New Post: Date marshalling
  • Hi again,

    Based on my tests, it seems that the Date type, which is one of the few core JS types, is not marshalled across the JS/.NET boundary.
    It would be very convenient if ClearScript could marshal it from & to the DateTime .NET type. Is this something you would consider?

    Thanks
    Thomas

    0 0

    Im sure this will sound strange, but I wanted to be able to capture the current 'state' in order to transfer the closure/context to a different scripting environment. The alternate context is not necessarily a v8 engine, but a running browser. I am using this technique to 'sandbox' certain code in a secondary process but then 'inject' code into the browser.

    0 0
  • 02/06/14--08:03: New Post: Date marshalling
  • Hi Thomas,

    In general, ClearScript favors seamless access over data conversion. We believe that this approach maximizes flexibility. There are exceptions, of course. If ClearScript didn't convert strings and numbers, for example, using it would be very painful :)

    Instead of converting JavaScript dates to DateTime structures, ClearScript makes it easy for hosts to use JavaScript dates directly and convert them to DateTime structures if necessary:
    dynamic date = engine.Evaluate("new Date()");
    Console.WriteLine(date.toString());
    
    var dateTime = new DateTime(
        date.getFullYear(),
        date.getMonth() + 1,
        date.getDate(),
        date.getHours(),
        date.getMinutes(),
        date.getSeconds(),
        date.getMilliseconds()
    );
    Console.WriteLine(dateTime);
    ClearScript also makes it easy to deal with DateTime structures in script code:
    engine.AddHostType("DateTime", typeof(DateTime));
    engine.AddHostType("Console", typeof(Console));
    engine.Execute(@"
        var dateTime = DateTime.Now;
        Console.WriteLine(dateTime);
    
        var date = new Date(0);
        date.setFullYear(dateTime.Year, dateTime.Month - 1, dateTime.Day);
        date.setHours(dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
        Console.WriteLine(date.toString());
    ");
    You could of course come up with more efficient conversion routines, but this is just an example.

    Good luck!

    0 0
  • 02/06/14--20:28: New Post: Date marshalling
  • Thanks for your reply.
    I kind of forgot that it was indeed possible to call methods of JS objects from the .NET side.

    Cheers
    Thomas

    0 0

    I'm having some trouble passing large numbers from .NET to the JScriptEngine. Here is what I'm trying to do:
            JScriptEngine engine = new JScriptEngine();
    
            engine.AddHostObject( "bigNumber", (long)1400000000000 );
            var result = engine.Evaluate( "'BigNumber: ' + bigNumber" );
    
            Console.WriteLine( "Result: " + result.ToString() );
    
    I'm getting an error on the AddHostObject call. Is it possible to pass long/Int64 data types from .NET to the JScript engine?

    Thanks,

    Jamin

    0 0
  • 02/07/14--17:11: New Post: Date marshalling
  • I'm having some trouble with date marshaling as well. In my scenario I'm using JavaScript as a hook into how the application performs certain actions. I would like to expose a clean interface that leverages the native functionality in JavaScript including Date. This is important because I'm prioritizing the JavaScript syntax over the work it would take to accomplish it on the .NET side.

    Here is my ideal script:
            JScriptEngine engine = new JScriptEngine();
    
            DateTime yesterday = DateTime.Now.AddDays( -1 );
            DateTime tomorrow = DateTime.Now.AddDays( 1 );
    
            engine.AddHostObject( "yesterday", yesterday );
            engine.AddHostObject( "tomorrow", tomorrow );
    
            StringBuilder scriptBuilder = new StringBuilder();
            scriptBuilder.AppendLine( "var now = new Date();" );
            scriptBuilder.AppendLine( "var todayAfterYesterday = now > yesterday;" );
            scriptBuilder.AppendLine( "var todayAfterTomorrow = now > tomorrow;" );
    
            engine.Execute( scriptBuilder.ToString() );
    
            Console.WriteLine( "TodayAfterYesterday: " + engine.Script.todayAfterYesterday );
            Console.WriteLine( "TodayAfterTomorrow: " + engine.Script.todayAfterTomorrow );
    
    This example returns false for both outputs.

    Even if I use a .NET DateTime.Now to compare my DateTime variables I still get false on both outputs.
            JScriptEngine engine = new JScriptEngine();
    
            DateTime yesterday = DateTime.Now.AddDays( -1 );
            DateTime tomorrow = DateTime.Now.AddDays( 1 );
    
            engine.AddHostObject( "yesterday", yesterday );
            engine.AddHostObject( "tomorrow", tomorrow );
            engine.AddHostObject( "now", DateTime.Now );
    
            StringBuilder scriptBuilder = new StringBuilder();
            scriptBuilder.AppendLine( "var todayAfterYesterday = now > yesterday;" );
            scriptBuilder.AppendLine( "var todayAfterTomorrow = now > tomorrow;" );
    
            engine.Execute( scriptBuilder.ToString() );
    
            Console.WriteLine( "TodayAfterYesterday: " + engine.Script.todayAfterYesterday );
            Console.WriteLine( "TodayAfterTomorrow: " + engine.Script.todayAfterTomorrow );
    
    This returns false to both outputs as well.

    The only solution I've found is to use method to compare the dates.
            JScriptEngine engine = new JScriptEngine();
    
            DateTime yesterday = DateTime.Now.AddDays( -1 );
            DateTime tomorrow = DateTime.Now.AddDays( 1 );
    
            engine.AddHostObject( "DateTimeComparer", new DateTimeComparer() );
    
            engine.AddHostObject( "yesterday", yesterday );
            engine.AddHostObject( "tomorrow", tomorrow );
            engine.AddHostObject( "now", DateTime.Now );
    
            StringBuilder scriptBuilder = new StringBuilder();
            scriptBuilder.AppendLine( "var todayAfterYesterday = DateTimeComparer.DifferenceInDays( now, yesterday );" );
            scriptBuilder.AppendLine( "var todayAfterTomorrow = DateTimeComparer.DifferenceInDays( now, tomorrow );" );
    
            engine.Execute( scriptBuilder.ToString() );
    
            Console.WriteLine( "TodayAfterYesterday: " + engine.Script.todayAfterYesterday );
            Console.WriteLine( "TodayAfterTomorrow: " + engine.Script.todayAfterTomorrow );
    
    This example does return 1 and -1.

    Has anyone else run into this? Why doesn't the compare operations work with both objects are .NET DateTime objects? Any better solutions? Any ideas, thoughts, insights would be much appreciated.

    Regards,

    Jamin

    0 0

    Hi Jamin,

    I'm getting an error on the AddHostObject call.

    That's correct. That method can't be used with simple values that are automatically converted to native script language datatypes, such as strings and numbers.

    I also tried replacing the engine.AddHostObject() with engine.Script reference

    That's the correct approach, but you've found an odd case. JavaScript (the language) doesn't support 64-bit integers; its only numeric datatype is 64-bit floating point. On the other hand, JScript (the engine) is implemented as a COM automation component and should therefore be able to handle 64-bit integer arguments.

    This is where JScript appears to have a bug; instead of converting 64-bit integers to floating point, it imports them directly and treats them as "unrecognized data". In your example, typeof bigNumber evaluates to "unknown", which isn't even legal JavaScript. Very strange!

    For now all we can recommend is that you avoid this situation. Convert 64-bit integers to double before passing them to JScript. We'll investigate this issue and consider making this conversion automatic in a future release.

    Thanks for bringing this to our attention!

    0 0
  • 02/08/14--11:03: New Post: Date marshalling
  • Greetings Jamin!

    I would like to expose a clean interface that leverages the native functionality in JavaScript including Date. This is important because I'm prioritizing the JavaScript syntax over the work it would take to accomplish it on the .NET side.

    That makes a lot of sense, and as we demonstrated above, ClearScript makes it easy to expose an interface that directly supports JavaScript dates. Your implementation can use them directly or convert them internally to DateTime structures if necessary.

    Regarding your code examples, the first two can't be made to work because JavaScript comparisons can't be redefined or overloaded to operate meaningfully on host objects.

    Your third example can be simplified because DateTime already has a comparison method:
    // JavaScriptvar todayAfterYesterday = now.CompareTo(yesterday) > 0;
    var todayAfterTomorrow = now.CompareTo(tomorrow) > 0;
    Cheers!

older | 1 | .... | 19 | 20 | (Page 21) | 22 | 23 | .... | 115 | newer