WebMessageReceived 事件处理程序中的 SetVirtualHostName 不起作用
SetVirtualHostName within WebMessageReceived event handler doesn't work
我正在尝试使用从 WebView2 的包含应用程序传入的源在 WebView2 中动态创建图像。
源图像存在于文件系统的任意位置。为了允许 WebView2 访问图像,我使用 SetVirtualHostNameToFolderMapping,它将 Web 视图中的主机名映射到某个文件夹。
我希望仅在使用 postMessage
和 WebMessageReceived event, as described here.
从 webview 内部进行一些交互后才会发生这种情况
如果我在 WebMessageReceived 处理程序之外调用 SetVirtualHostNameToFolderMapping,即使我使用 HTML 导航到 HTML =15=], webview加载图片。
但是如果我在 WebMessageReceived 处理程序中调用 SetVirtualHostNameToFolderMapping:
webview.CoreWebView2.WebMessageReceived += (s, e) => {
webview.CoreWebView2.SetVirtualHostNameToFolderMapping(
"assets",
@"C:\path\to\folder",
CoreWebView2HostResourceAccessKind.Allow
);
webview.CoreWebView2.PostWebMessageAsString(@"breakpoint.bmp");
};
webview找不到图片;它失败了:
Failed to load resource: net::ERR_NAME_NOT_RESOLVED
我该如何调试呢?我可以使用其他替代方法来做类似的事情吗?
XAML:
<Window x:Class="_testWebviewDialogs.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wv="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf">
<wv:WebView2 x:Name="webview" />
</Window>
代码隐藏:
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.Web.WebView2.Core;
namespace _testWebviewDialogs;
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Loaded += async (s, e) => await initializeAsync();
}
private async Task initializeAsync() {
await webview.EnsureCoreWebView2Async();
webview.CoreWebView2.WebMessageReceived += (s, e) => {
webview.CoreWebView2.SetVirtualHostNameToFolderMapping(
"assets",
@"C:\path\to\folder",
CoreWebView2HostResourceAccessKind.Allow
);
webview.CoreWebView2.PostWebMessageAsString(@"breakpoint.bmp");
};
var html = await File.ReadAllTextAsync("container.html");
webview.NavigateToString(html);
}
}
container.html
:
<!DOCTYPE html>
<html>
<body>
<button id="button1">Click me</button>
<img id ="img1" src="" />
<script>
document.getElementById("button1").addEventListener('click', ev => {
chrome.webview.postMessage('source');
});
window.chrome.webview.addEventListener('message', event => {
document.getElementById('img1').src = `https://assets/${event.data}`;
});
</script>
</body>
</html>
我为此提交了 issue。根据响应,记录了此行为:
As the resource loaders for the current page might have already been created and running, changes to the mapping might not be applied to the current page and a reload of the page is needed to apply the new mapping. (source)
但是可以创建(和重新创建)符号 link 到不同的目标路径,并将虚拟主机名映射到该符号 link。虚拟主机映射使用当前 symlink 目标。
var symlinkPath =
Path.Combine(
Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location!
)!,
"assets"
);
Directory.CreateDirectory(symlinkPath);
webview.CoreWebView2.SetVirtualHostNameToFolderMapping(
"assets",
symlinkPath,
CoreWebView2HostResourceAccessKind.Allow
);
webview.CoreWebView2.WebMessageReceived += (s, e) => {
Directory.Delete(symlinkPath);
Directory.CreateSymbolicLink(symlinkPath, @"C:\path\to\target\directory");
webview.CoreWebView2.PostWebMessageAsString(@"breakpoint.bmp");
};
我正在尝试使用从 WebView2 的包含应用程序传入的源在 WebView2 中动态创建图像。
源图像存在于文件系统的任意位置。为了允许 WebView2 访问图像,我使用 SetVirtualHostNameToFolderMapping,它将 Web 视图中的主机名映射到某个文件夹。
我希望仅在使用 postMessage
和 WebMessageReceived event, as described here.
如果我在 WebMessageReceived 处理程序之外调用 SetVirtualHostNameToFolderMapping,即使我使用 HTML 导航到 HTML =15=], webview加载图片。
但是如果我在 WebMessageReceived 处理程序中调用 SetVirtualHostNameToFolderMapping:
webview.CoreWebView2.WebMessageReceived += (s, e) => {
webview.CoreWebView2.SetVirtualHostNameToFolderMapping(
"assets",
@"C:\path\to\folder",
CoreWebView2HostResourceAccessKind.Allow
);
webview.CoreWebView2.PostWebMessageAsString(@"breakpoint.bmp");
};
webview找不到图片;它失败了:
Failed to load resource: net::ERR_NAME_NOT_RESOLVED
我该如何调试呢?我可以使用其他替代方法来做类似的事情吗?
XAML:
<Window x:Class="_testWebviewDialogs.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wv="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf">
<wv:WebView2 x:Name="webview" />
</Window>
代码隐藏:
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.Web.WebView2.Core;
namespace _testWebviewDialogs;
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Loaded += async (s, e) => await initializeAsync();
}
private async Task initializeAsync() {
await webview.EnsureCoreWebView2Async();
webview.CoreWebView2.WebMessageReceived += (s, e) => {
webview.CoreWebView2.SetVirtualHostNameToFolderMapping(
"assets",
@"C:\path\to\folder",
CoreWebView2HostResourceAccessKind.Allow
);
webview.CoreWebView2.PostWebMessageAsString(@"breakpoint.bmp");
};
var html = await File.ReadAllTextAsync("container.html");
webview.NavigateToString(html);
}
}
container.html
:
<!DOCTYPE html>
<html>
<body>
<button id="button1">Click me</button>
<img id ="img1" src="" />
<script>
document.getElementById("button1").addEventListener('click', ev => {
chrome.webview.postMessage('source');
});
window.chrome.webview.addEventListener('message', event => {
document.getElementById('img1').src = `https://assets/${event.data}`;
});
</script>
</body>
</html>
我为此提交了 issue。根据响应,记录了此行为:
As the resource loaders for the current page might have already been created and running, changes to the mapping might not be applied to the current page and a reload of the page is needed to apply the new mapping. (source)
但是可以创建(和重新创建)符号 link 到不同的目标路径,并将虚拟主机名映射到该符号 link。虚拟主机映射使用当前 symlink 目标。
var symlinkPath =
Path.Combine(
Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location!
)!,
"assets"
);
Directory.CreateDirectory(symlinkPath);
webview.CoreWebView2.SetVirtualHostNameToFolderMapping(
"assets",
symlinkPath,
CoreWebView2HostResourceAccessKind.Allow
);
webview.CoreWebView2.WebMessageReceived += (s, e) => {
Directory.Delete(symlinkPath);
Directory.CreateSymbolicLink(symlinkPath, @"C:\path\to\target\directory");
webview.CoreWebView2.PostWebMessageAsString(@"breakpoint.bmp");
};