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 | .... | 29 | 30 | (Page 31) | 32 | 33 | .... | 115 | newer

    0 0

    I am using the Microsoft.ClearScript.Windows.VBScriptEngine object.

    I have it inside a large class. Everything runs just great until I call one of the class's functions with a backgroundworker.

    In that scenario when I try to ExecuteCommand I get this error


    "The calling thread cannot access this object because a different thread owns it."

    I saw where I can call the CheckAccess() function to keep it from the error but I really really need this to work same as if it was all on a single thread.

    this is how I am initiating the vb object
      WorkflowVBS = new Microsoft.ClearScript.Windows.VBScriptEngine("ALICE");
    
    added these lines but they don't seem to help at all.
      WorkflowVBS.VerifyAccess();
      WorkflowVBS.AllowReflection = true;
    
    There has to be a way out of this pickle. just has to be.

    0 0

    Had an aha moment and thought declaring WofkflowVBS static would save the day. No joy.

    0 0

    Hello notahack,

    Windows script engines (JScript/VBScript) have thread affinity; that is, each instance can only be accessed on the thread that created it.

    ClearScript supports this requirement by associating each WindowsScriptEngine instance with a Dispatcher that you can use to invoke operations on the appropriate thread.

    Depending on your application's architecture, such invocations may or may not have to be asynchronous. Here's an example of a synchronous one:
    engine.Dispatcher.Invoke(new Action(() => engine.Execute(scriptCode)));
    Good luck!

    0 0

    that worked but not for all situations.

    When I am running with in the ide or a compiled program with a visual interface that worked. Take the same code and put it into a windows application that I am running on the command line and it bombs, even with error trapping.

    public bool WF_Script_Run(int Index)
            {
    
                bool retval = true;
                string errmsg = "";
    
                WF.SO.cancel = false;
    
                if (WF.OK && WF.SCEvent[Index])
                {
                    try
                    {
                        if ((int)WF.RunVersion < -10)
                        {
                            WorkflowJS.ExecuteCommand(WF.SCEvent_Names[Index]);
                        }
                        else
                        {
                            if (WorkflowVBS.CheckAccess())
                            {
                                WorkflowVBS.ExecuteCommand(WF.SCEvent_Names[Index]);
                            }
                            else
                            {
                                WorkflowVBS.Dispatcher.Invoke(new Action(() => WorkflowVBS.ExecuteCommand(WF.SCEvent_Names[Index])));
                            }
                        }
                    }
                    catch (Microsoft.ClearScript.ScriptEngineException EX)
                    {
                        errmsg = EX.Message;
                    }
                    catch (Exception EX)
                    {
                        errmsg = EX.Message;    
    
                    }
    
    
    
                }
    
                return retval;
            }
    

    0 0

    Hi again,

    Can you elaborate on "it bombs"? If the target thread is waiting for keyboard input via System.Console.ReadLine() or something like that, then invoking through the dispatcher should block. If you're seeing an exception, what is it?

    In general, if the target thread isn't a message-pumping thread (e.g., a GUI thread), then invoking through the dispatcher isn't likely to work, and you'll have to come up with your own way to ensure that the script engine is accessed only on that thread.

    Cheers!

    0 0

    On second thought maybe it didn't "bomb", i.e. generate a run time error, since my error trapping didn't trap anything. Instead I think it ran the line

    WorkflowVBS.Dispatcher.Invoke(new Action(() => WorkflowVBS.ExecuteCommand(WF.SCEvent_Names[Index])));

    and just hanged. Is that possible?

    On the calling thread I used System.Threading.AutoResetEvent. WaitOne and Set to block until the background worker thread completed. Any other suggestion?

    I got past it by rewriting the windows program as a single thread since it runs from a command line. 90% of the time code calling scripting will be single thread and if not it will be called in a separate thread to keep the GUI alive. I will be using a lot of command line and service programs so I am very concerned that the scripting code will not run in those environments if I use multi threads.

    I will admit I am a noob to multithreading in C# or any other language. Your statement "you'll have to come up with your own way to ensure that the script engine is accessed only on that thread." may as well be in pig latin to my understanding. To my knowledge there are only 2 threads, the calling and the backgroundworker.

    I assume this scenario also applies to the microsoft javascript. Does it apply to the V8 engine also?

    Give me a clue and a homework assignment kind sir. I am appreciative of your assistance.

    0 0

    Hi,

    It seems that null characters in strings, that are valid in both .Net and JavaScript, are not passed between host and script in both directions.

    For example:
    class StringTest
        {
            public static int GetLength(string s)
            {
                return s.Length;
            }
        }
    
    ...
    
    engine.AddHostType("Console", typeof(Console));
    
    // Test JS string passed to host
    engine.AddHostType("StringTest", typeof(StringTest));
    
    engine.Execute(@"
    var jsString = 'ab\0cd';
    Console.WriteLine('JS length of jsString {0}', jsString.length);
    Console.WriteLine('Host length of jsString: {0}', StringTest.GetLength(jsString));
    "
    );
    
    // Test Host string passed to JS
    string hostString = "ef\0gh";
    Console.WriteLine("Host length of hostString: {0}", hostString.Length);
    engine.Execute("function jsLength(s) {Console.WriteLine('JS length of hostString: {0}', s.length);}");
    engine.Script.jsLength(hostString);
    The output I get is:

    JS length of jsString 5
    Host length of jsString: 2 <---- Wrong, should be 5
    Host length of hostString: 5
    JS length of hostString: 2 <---- Wrong, should be 5


    Thanks in advance,
    Ron

    0 0

    Hi ClearScript,

    I would like to work with dynamic .NET objects, i.e. the following way
        public class MyDynamicObject : DynamicObject
        {
            public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
            {
                if (binder.Name == "AnyMethod")
                    // do some stuff here
                    ;
    
                return true; // base.TryInvokeMember(binder, args, out result);
            }
        }
    
        // and the usage
        using (var engine = new V8ScriptEngine())
        {
            engine.AddHostObject("app", new MyDynamicObject());
                    
            engine.Execute("app.AnyMethod();");
        }
    
    I hoped that the call app.AnyMethod is landing at TryInvokeMember for doing some additional stuff here, but it doesn't. Instead I get the exception: TypeError: Object #<HostObject> has no method 'AnyMethod'. Of course, when I add AnyMethod to MyDynamicObject it works, but that's not what I want in this case. Does the calling works by reflection or/and do I have a chance to achieve the usage of dynamic objects?

    Best regards,
    Torsten

    0 0

    Hi notahack,

    and just hanged. Is that possible?

    Yes, absolutely. For synchronous invocation, the calling thread must wait until the target thread is done executing the call. In your case, the target thread is waiting for an event signal, so it is unavailable to execute the call, and you get deadlock.

    We can't help much without knowing your application's architecture. APIs provide various tools for achieving correctness and robustness in multithreaded programs; the dispatcher is just one such tool. The key to using it is that the target thread (the one that owns the dispatcher) must be coded a certain way; specifically, it must process the dispatch queue. Windows GUI threads typically do this, but custom threads can use methods such as Dispatcher.PushFrame().

    Check out the MSDN documentation in this area, but remember that the dispatcher is just one tool. The engine's only requirement is that you always access it on the thread that created it, and there are many ways to accomplish that.

    I assume this scenario also applies to the microsoft javascript. Does it apply to the V8 engine also?

    V8ScriptEngine instances don't have thread affinity, but they don't support concurrent access either. Each instance is protected by a lock, but there are still plenty of ways to get into trouble :)

    Good luck!

    0 0

    Hi Ron,

    You're right. A fix is on the way.

    Cheers!

    0 0

    Hello Torsten,

    For this to work, your class must implement DynamicObject.GetDynamicMemberNames(). For example:
    publicoverride IEnumerable<string> GetDynamicMemberNames()
    {
        yieldreturn"AnyMethod";
    }
    Good luck!

    0 0

    If a .NET or V8 string has an embedded null character, ClearScript truncates it during marshaling.

    0 0

    That works. Thanks a lot!

    Torsten

    0 0

    Hello ClearScript,

    is there any option for a bit more modularization? As far as I can see, Compile, Evaluate and Execute are additionaly so that with each call the JavaScript Code is a bit bigger. What I want is a bit more separation for pieces of code, like
    var compiledscript = engine.Compile(modulescript);
    ...
    engine.Execute(compiledscript, " some java script code");
    The second parameter relates to the compiled script and is only valid for that.

    I guess I may use another instance of the script engine to achive this, but it might be to expensive.

    Best regards,
    Torsten

    P.S. What does ExecuteCommand other then Execute or Evaluate? Is the return value the only difference?

    0 0

    Hi Torsten,

    You appear to be concerned about unrelated scripts leaving functions and other objects around, eventually leading to a cluttered and unpredictable execution environment for subsequent scripts. Is that correct?

    If so, then you should definitely use separate script engine instances. Creating a new script engine instance is the only way to guarantee a pristine execution environment. If concurrency is not a requirement, you can reduce costs by reusing the V8 runtime, which would allow you to reuse previously compiled scripts as well. Have a look at the V8Runtime class in the library reference.

    Oh, and yes, for JavaScript, ExecuteCommand() is just like Evaluate() except for its treatment of the execution result.

    Good luck!

    0 0

    Hi,

    Would it be possible to add a custom exception, so that when it is thrown by host it throws a script exception of the specified type and message.

    For example, in host code:

    ```
    throw new CustomScriptException("RangeError", "custom message");
    ```

    will cause script to execute:

    ```
    throw new RangeError('custom message');
    ```

    Specifically, for the example above I need the exception to be instanceof RangeError.

    Thanks again in advance,
    Ron



    0 0

    Hi,

    Would it be possible to add a custom exception, so that when it is thrown by host it throws a script exception of the specified type and message.

    For example, in host code:

    ```
    throw new CustomScriptException("RangeError", "custom message");
    ```

    will cause script to execute:

    ```
    throw new RangeError('custom message');
    ```

    Specifically, for the example above I need the exception to be instanceof RangeError.

    Thanks again in advance,
    Ron


    Comments: That's an interesting idea, but we'd prefer not to introduce language-specific API elements. Some script engines (e.g., JScript) don't have exception throwing APIs, and some others (e.g., VBScript) don't support exceptions at all. Instead, we recommend that you use script code to throw script exceptions. To facilitate that, you could set up a function that passes host exceptions to script code: ``` C# engine.Script.tryCatch = new Func<dynamic, object>(func => { try { return new { returnValue = func() }; } catch (Exception exception) { return new { exception }; } }); ``` You could then use this function to implement the required exception handling behavior: ``` JavaScript var result = tryCatch(function () { // invoke host methods/properties }); if (result.exception) { // convert host exception and throw throw toJavaScriptException(result.exception); } // use result.returnValue ```

    0 0

    Hi,

    Would it be possible to add a custom exception, so that when it is thrown by host it throws a script exception of the specified type and message.

    For example, in host code:

    ```
    throw new CustomScriptException("RangeError", "custom message");
    ```

    will cause script to execute:

    ```
    throw new RangeError('custom message');
    ```

    Specifically, for the example above I need the exception to be instanceof RangeError.

    Thanks again in advance,
    Ron



    0 0

    Hi,

    Would it be possible to add a custom exception, so that when it is thrown by host it throws a script exception of the specified type and message.

    For example, in host code:

    ```
    throw new CustomScriptException("RangeError", "custom message");
    ```

    will cause script to execute:

    ```
    throw new RangeError('custom message');
    ```

    Specifically, for the example above I need the exception to be instanceof RangeError.

    Thanks again in advance,
    Ron



    0 0

    Add the nuget package for Clearscript V8 to a solution, build solution this completes with no errors.
    Remove folder packages\ClearScript.V8.5.3.10.0, build solution this restores and completes with no errors.

    remove V8 and replace with Clearscript without V8 dependancies.
    Remove the folder packages\ClearScript.5.3.8, now the build solution fails because package restores fails:

    Unable to find version '5.3.8' of package 'ClearScript'

older | 1 | .... | 29 | 30 | (Page 31) | 32 | 33 | .... | 115 | newer