【问题标题】:How to execute JavaScript function with C# in UWP without WebView如何在没有 WebView 的 UWP 中使用 C# 执行 JavaScript 函数
【发布时间】:2017-06-09 11:09:48
【问题描述】:

假设我们的 C# UWP App 项目中包含一个 *.js 文件,并且我们希望能够执行该文件中包含的函数。

示例 JS 函数:

function myFunction(p1, p2) {
return p1 * p2;              // The function returns the product of p1 and p2

}

示例 C# 代码:

public class SampleObject
{
    public SampleObject(int a, int b)
    {
        var evaluated = <<< do some magic and get myFuction(a,b) here >>>
    }
}

除了在加载我们的 JS 的情况下保留一些虚拟 WebView 并从中调用 myFunction 之外,还有其他方法吗? 我读过有关 Chakra 的文章,看起来应该可以解决问题,但我不知道如何以我想要的方式使用它。任何几行示例?

【问题讨论】:

  • 也许您可以在问题标题中添加您不想为此使用网络视图的问题。
  • 好点,改标题

标签: javascript c# uwp


【解决方案1】:
  1. 我会使用 cscript.exe 来运行您的 JavaScript - 有关这方面的信息,请参阅 https://technet.microsoft.com/en-us/library/bb490887.aspx
  2. 使用 System.Diagnostics.Process 对象调用 cscript.exe
  3. 使用 ProcessStartInfo 对象将路径传递给您的 JavaScript 文件。
  4. 设置事件以捕获来自 StandardOutput 和 StandardError 通道的输出。请注意,并非 StandardError 返回的所有内容都一定是错误。为了方便起见,我为 Process 类创建了一个包装器,称为 cManagedProcess:

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Text;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                string sScriptPath = @"C:\temp\test.js";
                File.WriteAllText(sScriptPath, @"
    //Your JavaScript goes here!
    WScript.Echo(myFunction(1, 2));
    
    function myFunction(p1, p2) {
        return p1 * p2; // The function returns the product of p1 and p2
    }
    ");
    
                var oManagedProcess = new cManagedProcess("cscript.exe", sScriptPath);
                int iExitCode = oManagedProcess.Start();
    
                Console.WriteLine("iExitCode = {0}\nStandardOutput: {1}\nStandardError: {2}\n", 
                    iExitCode, 
                    oManagedProcess.StandardOutput,
                    oManagedProcess.StandardError
                    );
    
                Console.WriteLine("Press any key...");
                Console.ReadLine();
            }
        }
    
        public class cManagedProcess
        {
            private Process moProcess;
    
            public ProcessStartInfo StartInfo;
    
            private StringBuilder moOutputStringBuilder;
            public string StandardOutput
            {
                get
                {
                    return moOutputStringBuilder.ToString();
                }
            }
    
            private StringBuilder moErrorStringBuilder;
            public string StandardError
            {
                get
                {
                    return moErrorStringBuilder.ToString();
                }
            }
    
            public int TimeOutMilliSeconds = 10000;
    
            public bool ThrowStandardErrorExceptions = true;
    
            public cManagedProcess(string sFileName, string sArguments)
            {
                Instantiate(sFileName, sArguments);
            }
    
            public cManagedProcess(string sFileName, string sFormat, params object[] sArguments)
            {
                Instantiate(sFileName, string.Format(sFormat, sArguments));
            }
    
            private void Instantiate(string sFileName, string sArguments)
            {
                this.StartInfo = new ProcessStartInfo()
                {
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    FileName = sFileName,
                    Arguments = sArguments
                };
            }
    
            private AutoResetEvent moOutputWaitHandle;
            private AutoResetEvent moErrorWaitHandle;
    
            /// <summary>
            /// Method to start the process and wait for it to terminate
            /// </summary>
            /// <returns>Exit Code</returns>
            public int Start()
            {
                moProcess = new Process();
                moProcess.StartInfo = this.StartInfo;
                moProcess.OutputDataReceived += cManagedProcess_OutputDataReceived;
                moProcess.ErrorDataReceived += cManagedProcess_ErrorDataReceived;
    
                moOutputWaitHandle = new AutoResetEvent(false);
                moOutputStringBuilder = new StringBuilder();
    
                moErrorWaitHandle = new AutoResetEvent(false);
                moErrorStringBuilder = new StringBuilder();
    
                bool bResourceIsStarted = moProcess.Start();
    
                moProcess.BeginOutputReadLine();
                moProcess.BeginErrorReadLine();
    
                if (
                    moProcess.WaitForExit(TimeOutMilliSeconds)
                    && moOutputWaitHandle.WaitOne(TimeOutMilliSeconds)
                    && moErrorWaitHandle.WaitOne(TimeOutMilliSeconds)
                    )
                {
                    if (mbStopping)
                    {
                        return 0;
                    }
    
                    if (moProcess.ExitCode != 0 && ThrowStandardErrorExceptions)
                    {
                        throw new Exception(this.StandardError);
                    }
                    return moProcess.ExitCode;
                }
                else
                {
                    throw new TimeoutException(string.Format("Timeout exceeded waiting for {0}", moProcess.StartInfo.FileName));
                }
            }
    
            private bool mbStopping = false;
            public void Stop()
            {
                mbStopping = true;
                moProcess.Close();
            }
    
    
            private void cManagedProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
            {
                DataRecieved(e, moOutputWaitHandle, moOutputStringBuilder);
            }
    
            private void cManagedProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
            {
                DataRecieved(e, moErrorWaitHandle, moErrorStringBuilder);
            }
    
            private void DataRecieved(DataReceivedEventArgs e, AutoResetEvent oAutoResetEvent, StringBuilder oStringBuilder)
            {
                if (e.Data == null)
                {
                    oAutoResetEvent.Set();
                }
                else
                {
                    oStringBuilder.AppendLine(e.Data);
                }
            }
        }
    }
    

【讨论】:

  • 这是 UWP - 使用官方 API,您将无法启动进程。
【解决方案2】:

您需要一个 javascript 解释器来运行 javascript。

我用 Jint: http://jint.codeplex.com/

获得了很好的体验

你可以让它像这个 untested sn-p:

JintEngine engine = new JintEngine();

engine.Run(@"
  myFunction(p1, p2) { 
    return p1 * p2;
  }";

Console.Write(engine.Run("myFunction(4,5);");

如果你想运行一个 js 文件,只需读取并运行它。

【讨论】:

  • 你用 UWP 试过了吗?我之所以问,是因为我在使用 nuget 安装过程中遇到了一些依赖项问题
猜你喜欢
  • 1970-01-01
  • 2011-02-25
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 2020-11-16
  • 2016-11-20
  • 2017-01-09
  • 2015-04-19
相关资源
最近更新 更多