You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PowerShell中配置WebView2 Core的NewWindowRequested以阻止新窗口

问题描述

编写PowerShell脚本使用WebView2控件加载Speedtest.net,需求是禁止用户导航离开当前页面或点击链接打开新窗口。目前已通过SourceChanged事件检测地址变化并强制跳转回目标URL,但页面中部分链接会触发新窗口打开,无法阻止。尝试直接实例化Microsoft.Web.Webview2.Core.CoreWebView2对象时报错:找不到构造函数。无法找到适用于类型Microsoft.Web.Webview2.Core.CoreWebView2的合适构造函数。

现有代码如下:

$ScriptPath = [System.AppDomain]::CurrentDomain.BaseDirectory.TrimEnd('\\')
[xml]$XAML = @"
<Window x:Class="WPF_Getting_Started.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:local="clr-namespace:WpfTest"
      xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
      mc:Ignorable="d"
      Title="Internet Speed Test `$ScriptVersion"
      Height="450"
      Width="800"
>
    <DockPanel>
        <wv2:WebView2 Name="webView"
                  Source="http://www.speedtest.net"
   >
            <wv2:WebView2.CreationProperties>
                <wv2:CoreWebView2CreationProperties BrowserExecutableFolder="" UserDataFolder="`$ENV:TEMP"/>
            </wv2:WebView2.CreationProperties>
        </wv2:WebView2>
    </DockPanel>
</Window>
"@
#
# Assembly
#
    [void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
    [void][reflection.assembly]::LoadFile("$ScriptPath\\Microsoft.Web.WebView2.Core.dll")
    [void][reflection.assembly]::LoadFile("$ScriptPath\\Microsoft.Web.WebView2.WinForms.dll")
    [void][reflection.assembly]::LoadFile("$ScriptPath\\Microsoft.Web.WebView2.Wpf.dll")
#
# Execution
#
    $XAML.Window.RemoveAttribute("x:Class")
    $XAML.Window.RemoveAttribute("mc:Ignorable")
    $Reader=(New-Object System.Xml.XmlNodeReader $XAML)
    $Form=[Windows.Markup.XamlReader]::Load($Reader)
    $XAML.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]")  | ForEach-Object {  
        New-Variable  -Name `$_.Name -Value `$Form.FindName(`$_.Name) -Force  
    }
    # Webview
    $webview_SourceChanged={
        `$webView.Source = "http://www.speedtest.net"
    }
    `$webView.add_SourceChanged(`$webview_SourceChanged)
    # Other form properties
    `$Screens = [System.Windows.Forms.Screen]::AllScreens
    `$Screen = `$Screens | Where {`$_.Primary -eq "True"}
    `$script:Bounds = `$Screen.Bounds
    `$Form.Left = `$Bounds.Left
    `$Form.Top = `$Bounds.Top
    `$Form.Height = `$Bounds.Height
    `$Form.Width = `$Bounds.Width
    [void]`$Form.ShowDialog()
解决方案

不能直接实例化CoreWebView2对象,需等待WebView2控件的CoreWebView2Ready事件触发后,再绑定NewWindowRequested事件来阻止新窗口打开,同时修正SourceChanged的逻辑避免无限循环。

关键修改点:

  1. 移除无限循环的SourceChanged绑定:原代码每次Source变化都强制跳转,会导致循环触发事件,需添加判断仅当地址不是目标URL时才跳转。
  2. 绑定CoreWebView2Ready事件:在该事件中获取已初始化的CoreWebView2实例,然后绑定NewWindowRequested事件,设置Handled = $true即可阻止新窗口打开。
  3. 处理NewWindowRequested事件:当触发新窗口请求时,标记事件已处理,阻止系统打开新窗口。

修改后的完整代码:

$ScriptPath = [System.AppDomain]::CurrentDomain.BaseDirectory.TrimEnd('\\')
$TargetUrl = "http://www.speedtest.net"

[xml]$XAML = @"
<Window x:Class="WPF_Getting_Started.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:local="clr-namespace:WpfTest"
      xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
      mc:Ignorable="d"
      Title="Internet Speed Test `$ScriptVersion"
      Height="450"
      Width="800"
>
    <DockPanel>
        <wv2:WebView2 Name="webView"
                  Source="$TargetUrl"
   >
            <wv2:WebView2.CreationProperties>
                <wv2:CoreWebView2CreationProperties BrowserExecutableFolder="" UserDataFolder="`$ENV:TEMP"/>
            </wv2:WebView2.CreationProperties>
        </wv2:WebView2>
    </DockPanel>
</Window>
"@

# Load Assemblies
[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework')
[void][reflection.assembly]::LoadFile("$ScriptPath\\Microsoft.Web.WebView2.Core.dll")
[void][reflection.assembly]::LoadFile("$ScriptPath\\Microsoft.Web.WebView2.WinForms.dll")
[void][reflection.assembly]::LoadFile("$ScriptPath\\Microsoft.Web.WebView2.Wpf.dll")

# Parse XAML
$XAML.Window.RemoveAttribute("x:Class")
$XAML.Window.RemoveAttribute("mc:Ignorable")
$Reader=(New-Object System.Xml.XmlNodeReader $XAML)
$Form=[Windows.Markup.XamlReader]::Load($Reader)
$XAML.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]")  | ForEach-Object {  
    New-Variable  -Name $_.Name -Value $Form.FindName($_.Name) -Force  
}

# Handle CoreWebView2 Ready Event
$webView_CoreWebView2Ready = {
    # Bind NewWindowRequested to block new windows
    $webView.CoreWebView2.add_NewWindowRequested({
        param($sender, $e)
        # Mark the request as handled to prevent new window
        $e.Handled = $true
        # Optional: Redirect to target URL in current window instead
        # $webView.Source = $TargetUrl
    })
}

# Bind CoreWebView2Ready event
$webView.add_CoreWebView2Ready($webView_CoreWebView2Ready)

# Fix SourceChanged logic to avoid infinite loop
$webview_SourceChanged={
    if ($webView.Source.AbsoluteUri -ne $TargetUrl) {
        $webView.Source = $TargetUrl
    }
}
$webView.add_SourceChanged($webview_SourceChanged)

# Set window to full screen on primary monitor
$Screens = [System.Windows.Forms.Screen]::AllScreens
$Screen = $Screens | Where { $_.Primary -eq $true }
$script:Bounds = $Screen.Bounds
$Form.Left = $Bounds.Left
$Form.Top = $Bounds.Top
$Form.Height = $Bounds.Height
$Form.Width = $Bounds.Width

[void]$Form.ShowDialog()

代码说明:

  • CoreWebView2Ready事件:WebView2控件初始化完成后才会触发该事件,此时CoreWebView2实例已可用,无需手动创建。
  • NewWindowRequested事件处理:通过设置$e.Handled = $true,告诉WebView2控件我们已经处理了这个请求,不会打开新窗口。也可以根据需求,将请求的URL重定向到当前窗口的目标地址。
  • 修正SourceChanged逻辑:添加地址判断,只有当当前地址不是目标URL时才跳转,避免无限触发SourceChanged事件。

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:50:24