如何在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的逻辑避免无限循环。
关键修改点:
- 移除无限循环的SourceChanged绑定:原代码每次Source变化都强制跳转,会导致循环触发事件,需添加判断仅当地址不是目标URL时才跳转。
- 绑定CoreWebView2Ready事件:在该事件中获取已初始化的CoreWebView2实例,然后绑定
NewWindowRequested事件,设置Handled = $true即可阻止新窗口打开。 - 处理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
相关产品推荐
相关产品推荐

