如何使用计时器在 WebView2 中自动运行 JavaScript

Jiale Xue - MSFT 46,956 信誉分 Microsoft 供应商
2024-03-28T07:43:18.7+00:00

您好: 对于我的项目,我必须每分钟在 WebView2 中自动运行一些 JavaScript。即使我可以手动单击按钮来运行 JavaScript 并获得结果,但我无法弄清楚如何使用计时器自动运行作业。

我做了以下操作: 我创建了一个 Windows 窗体应用程序 (.NET) 并将目标设置为 .NET 5.0;然后我安装 WebView2 Nuget 包:安装包 Microsoft.Web.WebView2 -版本 1.0.664.37

我没有使用 Windows 窗体设计器,但我手动编写了以下代码: 我使用 Visual Studio 2019 版本 16.8.4,我的操作系统是 Windows 10(版本 20H2)

用于应用程序的 Visual Basic

using Microsoft.Web.WebView2.WinForms;  
using System;  
using System.Diagnostics;  
using System.Drawing;  
using System.Threading.Tasks;  
using System.Windows.Forms;  
using Timer = System.Timers.Timer;    

namespace WebView2Buttons    
{    
    public partial class Form1 : Form  
    {  
        private readonly WebView2 BingWebView = new WebView2();  
        private readonly Button MinuteButton = new Button();  
        private readonly Button Button1 = new Button();  
        private static Timer MinuteTimer;  
    

    private async void MinuteTimerElapsedAsync(Object source, System.Timers.ElapsedEventArgs e)  
    {  
        try  
        {  
            MinuteButton.PerformClick();  
        }  
        catch (TimeoutException ex)  
        {  
            Debug.WriteLine("[MinuteTimerElapsedAsync]: " + ex.Message);  
            await Task.Delay(1);  
        }  
    }  

    private async void MinuteButton_Click(object sender, EventArgs e)  
    {  
        string xhr_request =  
            @"function reqXHR() { let r = new XMLHttpRequest();   
              r.open('GET', 'https://www.bing.com/', false);   
              r.send(); var reply = r.responseText; return reply;}; reqXHR(); ";  
        string raw_data =  
            await BingWebView.CoreWebView2.ExecuteScriptAsync(xhr_request);  
        Debug.WriteLine(raw_data);  
    }  

    private async void Button1_Click(object sender, EventArgs e)  
    {  
        string xhr_request =  
            @"function reqXHR() { let r = new XMLHttpRequest();   
              r.open('GET', 'https://www.bing.com/', false);   
              r.send(); var reply = r.responseText; return reply;}; reqXHR(); ";  
        string raw_data =  
            await BingWebView.CoreWebView2.ExecuteScriptAsync(xhr_request);  
        Debug.WriteLine(raw_data);  
    }  

    public Form1()  
    {  
        InitializeComponent();  
        Control.CheckForIllegalCrossThreadCalls = false;  
        BingWebView.CreationProperties = null;  
        BingWebView.Location = new Point(10, 65);  
        BingWebView.Name = "BingWebView";  
        BingWebView.Size = new Size(1750, 780);  
        BingWebView.Source = new Uri("https://www.bing.com/", UriKind.Absolute);  
        BingWebView.TabIndex = 0;  
        BingWebView.Text = "BingWebView";  
        BingWebView.ZoomFactor = 1D;  
        BingWebView.Visible = true;  
        this.SuspendLayout();  
        MinuteButton.Location = new Point(1500, 10);  
        MinuteButton.Name = "MinuteButton";  
        MinuteButton.Size = new Size(250, 50);  
        MinuteButton.TabIndex = 1;  
        MinuteButton.Text = "MinuteButton";  
        MinuteButton.UseVisualStyleBackColor = true;  
        MinuteButton.Click += new EventHandler(MinuteButton_Click);  
        Button1.Location = new Point(50, 10);  
        Button1.Name = "Button1";  
        Button1.Size = new Size(250, 50);  
        Button1.TabIndex = 2;  
        Button1.Text = "Button1";  
        Button1.UseVisualStyleBackColor = true;  
        Button1.Click += new EventHandler(Button1_Click);  
        ClientSize = new Size(1800, 800);  
        Controls.Add(BingWebView);  
        Controls.Add(MinuteButton);  
        Controls.Add(Button1);  
        Name = "Form1";  
        Text = "Form1";  
        Load += new EventHandler(Form1_Load);  
        ResumeLayout(false);  
    }  

    private void Form1_Load(object sender, EventArgs e)  
    {  
        MinuteTimer = new Timer(60000);  
        MinuteTimer.Elapsed += MinuteTimerElapsedAsync;  
        MinuteTimer.AutoReset = true;  
        MinuteTimer.Enabled = true;  
        MinuteTimer.Start();  
    }  
}  
}

如果我单击“Button1”或“MinuteButton”的任一按钮,我的代码就可以工作。但是在分钟计时器中自动单击“MinuteButton”不起作用。 我看到错误:

System.InvalidCastException    
  HResult=0x80004002    
  Message=Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Controller'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{4D00C0D1-9434-4EB6-8078-8697A560334F}' failed due to the following error: No such interface supported (0x80004002 (E_NOINTERFACE)).    
  Source=System.Private.CoreLib    
  StackTrace:    
   at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease)    
   at Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Controller.get_CoreWebView2()    
   at Microsoft.Web.WebView2.Core.CoreWebView2Controller.get_CoreWebView2()    
   at Microsoft.Web.WebView2.WinForms.WebView2.get_CoreWebView2()    
   at WebView2Buttons.Form1.<MinuteButton_Click>d__5.MoveNext() in C:\WebView2Buttons\WebView2Buttons\Form1.cs:line 37    

我不明白我用鼠标单击按钮和语句 MinuteButton.PerformClick() 之间的区别 让我知道我是否可以这样做。 顺便说一句,我不一定必须使用单击按钮代码,但我认为我必须使用计时器,因为我必须每分钟运行一些 JavaScript 代码。 谢谢 59170-timerclickbuttonissue.png

Note:此问题总结整理于: How to use timer to automatically run JavaScript in WebView2.

C#
C#
一种面向对象的类型安全的编程语言,它起源于 C 语言系列,包括对面向组件的编程的支持。
191 个问题
Visual Studio 调试
Visual Studio 调试
Visual Studio: 一系列 Microsoft 集成开发工具套件,用于生成适用于 Windows、Web 和移动设备的应用程序。调试: 检测、查找和更正程序中的逻辑或语法错误或硬件故障的行为或过程。 在硬件上下文中,术语“故障排除”是更频繁使用的术语,尤其是在问题严重的情况下。
17 个问题
0 个注释 无注释
{count} 票

接受的答案
  1. Hui Liu-MSFT 48,576 信誉分 Microsoft 供应商
    2024-03-28T09:01:15.1933333+00:00

    此错误与 PerformClick() 无关,而是因为代码正在尝试跨线程操作。 System.Timers.Timer 将使用一个新线程,当您尝试调用此线程时,将发生此错误。 请尝试以下代码:MinuteButton.PerformClick();

                try  
                {  
                    MinuteButton.Invoke((MethodInvoker)delegate { MinuteButton.PerformClick(); });  
                }  
    

    如果回复有帮助,请点击“接受答案”并点赞。 注意:如果您想接收此线程的相关电子邮件通知,请按照我们文档中的步骤启用电子邮件通知。

    1 个人认为此答案很有帮助。
    0 个注释 无注释

0 个其他答案

排序依据: 非常有帮助

你的答案

问题作者可以将答案标记为“接受的答案”,这有助于用户了解已解决作者问题的答案。