如何删除 C# WPF 应用程序中的 WebView2 UserDataFolder,BrowserProcessExited 事件不会触发

2023-12-19

我的 C# 应用程序使用 WebView2。

要求多个实例同时打开,且不共享会话。根据这个WebView2流程​​模型解释 https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/process-model,这是通过使用不同的用户数据文件夹 https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/user-data-folders,在创建 CoreWebView2Environment 时传递。

该应用程序当前是从只读网络共享加载的,因此与 exe 一起创建用户数据文件夹的默认设置不符合条件,因此我的实现在用户临时目录中创建了不同的 UserDataFolders。

为了清理,我想在应用程序关闭时删除创建的目录。 该文档建议浏览器进程退出 https://learn.microsoft.com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2environment.browserprocessexited?view=webview2-dotnet-1.0.1072.54当 WebView2 占用的所有资源都被释放时应该调用的事件。

But the BrowserProcessExited 事件永远不会被调用.

在使用 WebView2 的页面中,我这样做:

public void MyApp_Closing(object sender, CancelEventArgs e)
{
    glucoTabWebcontrol2.CoreWebView2.Environment.BrowserProcessExited += Environment_BrowserProcessExited;
}

// This is never called
private void Environment_BrowserProcessExited(object sender, CoreWebView2BrowserProcessExitedEventArgs e)
{
    try
    {
        System.IO.Directory.Delete(((CoreWebView2Environment)sender).UserDataFolder);
    } catch (Exception ex)
    {
        ... handle exception
    }
}

我的猜测是应用程序在事件触发之前关闭。 要实现这一目标需要什么BrowserProcessExited事件已收到?


您必须等待进程退出才能关闭应用程序。来自docs https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/user-data-folder?tabs=win32:

要删除用户数据文件夹 (UDF),您必须首先结束 WebView2 会话。如果 WebView2 会话当前处于活动状态,则无法删除 UDF。

如果 WebView2 主机应用程序关闭后文件仍在使用中,请等待浏览器进程退出,然后再删除用户数据文件夹 (UDF)。

WebView2 应用程序关闭后,UDF 中的文件可能仍在使用中。在这种情况下,请等待浏览器进程和所有子进程退出后再删除UDF。要监视进程以等待它们退出,请使用 WebView2 应用实例的 BrowserProcessId 属性检索浏览器进程的进程 ID。

我是这样做的,与 CFou 的答案类似:

Application.Current.Exit += OnAppExit;
private void OnAppExit(object sender, ExitEventArgs e)
{
    try
    {
        // Delete WebView2 user data before application exits
        string? webViewCacheDir = Browser.CoreWebView2.Environment.UserDataFolder;
        var webViewProcessId = Convert.ToInt32(Browser.CoreWebView2.BrowserProcessId);
        var webViewProcess = Process.GetProcessById(webViewProcessId);

        // Shutdown browser with Dispose, and wait for process to exit
        Browser.Dispose();
        webViewProcess.WaitForExit(3000);

        Directory.Delete(webViewCacheDir, true);
    }
    catch (Exception ex)
    {
        // log warning
    }
}

我将超时设置为 3 秒,这应该足够了。请注意不要使用 WaitForExit 的异步版本,因为无法等待 async void 方法,因此 WPF 会很高兴地继续关闭应用程序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何删除 C# WPF 应用程序中的 WebView2 UserDataFolder,BrowserProcessExited 事件不会触发 的相关文章

  • .NET Windows 服务中调用 C# 的 wait 的 I/O 回调是否可以不阻塞?

    我知道在 ASP NET 中 当使用 wait 时工作线程会返回到池中 而 I O 发生在后台 这对于可扩展性非常有用 我的 Windows 服务是一个套接字服务器 它使用 Begin End 样式的异步套接字 I O 混合我的魔法 我知道
  • 在 MVC 类上创建主键字段

    我是 MVC 和 C 新手 我只是偶然发现它并发现它很有趣 我遇到了一个不允许我继续的问题 这是我的代码 using System using System Collections Generic using System Linq usi
  • WPF - 按多列排序时使用自定义比较器

    我有一个 ListView GridView 我想按 2 列排序 因此如果第 1 列中有 2 个以上的项目具有相同的值 它将按第 2 列排序 非常简单 但是在对 A Z 进行排序时 空字符串会出现在顶部 我想把它们移到底部 我制作了一个比较
  • 浏览器收集哪些值作为回发数据?

    当页面被发送回服务器时 浏览器收集每个控件的当前值并将其粘贴到一个字符串中 然后 该回发数据通过 HTTP POST 发送回服务器 Q1 除了控件的 Text 属性和 SelectedIndexchanged 因此除了用户输入数据 之外 控
  • 如何检查 .NET 4.0 中的泛型参数是否是动态的

    我有课ObjectMapper
  • 将占位符文本添加到文本框

    我正在寻找一种将占位符文本添加到文本框的方法 就像在 html5 中使用文本框一样 IE 如果文本框没有文本 则会添加文本Enter some text here 当用户单击它时 占位符文本消失并允许用户输入自己的文本 如果文本框失去焦点并
  • C++ 模板参数类型推断

    我有一个这样的C 模板 template
  • Windows 程序如何临时更改其时区?

    我写了一个函数来返回time t与给定日期的午夜相对应的值 当给定日期没有午夜时 它返回最早可用的时间 例如 当埃及进入夏令时时 这种情况就可能发生 今年 时间更改于 4 月 29 日晚上午夜生效 因此时钟直接从 23 59 转到 01 0
  • 使用 Microsoft Graph 创建用户

    如何使用 Microsoft graph 创建用户 因为我在保存过程中遇到了权限失败的问题 我确实有几个问题 在图中调用创建用户 API 将在哪里创建用户 是在 Azure AD 还是其他地方 我尝试通过传递 json 和必需的标头来调用创
  • C++ 析构函数:何时释放内存?

    如果我删除一个导致其析构函数被调用的对象 那么内存是在析构函数完成函数中的任何操作之前还是之后被释放 仅当最小派生类子对象被销毁后才会释放内存 所以如果你有 class Base class Derived public Base publ
  • 从 ef core 的子集合中删除一些项目

    我有一个父表和子表 其中父表与子表具有一对多关系 我想删除一些子项 并且希望父项的子集合反映该更改 如果我使用删除选定的子项RemoveRange 那么子集合不会更新 如果我使用Remove从子集合中删除子集合然后 显然 它不如使用效率高R
  • 使用对象列表构建树

    我有一个带有属性 id 和parent id 的对象列表 我想建造一棵树来连接那些孩子和父母 1 个父对象可以有多个子对象 并且有一个对象将成为所有对象的祖先 实现该功能最快的算法是什么 我使用 C 作为编程语言 但其他语言也可以 像这样的
  • AspNetCore.SignalR:无法启动未处于初始状态的连接

    我无法让 ASP NET Core SignalR 应用程序正常运行 我有这个服务器端代码 public class PopcornHub Hub private int Users public async Task BroadcastN
  • 函数模板重载解析期间的 MSVC 与 Clang/GCC 错误,其中一个函数模板包含参数包

    当我使用参数包时 我注意到这样一种情况 如下所示 在 gcc 和 clang 中编译得很好 但在 msvc 中却不行 template
  • 语义问题 Qt Creator:命名空间“std”中没有名为“cout”的成员

    我开始使用 Qt Creator 编写代码 对于 C 文件 我遇到很多语义问题 99 是 命名空间 yyy 中没有名为 xxx 的成员cpp文件构建 编译和输出没有问题 如果我点击例如cout 我已链接到 iostream 我是否需要在 Q
  • Intel 和 AMD 处理器有相同的汇编程序吗?

    C语言被用来编写Unix以实现可移植性 使用不同编译器编译的同一个C语言程序会产生不同的机器指令 为什么 Windows 操作系统能够在两者上运行Intel https en wikipedia org wiki Intel and AMD
  • 无效的模板相关成员函数模板推导 - 认为我正在尝试使用 std::set

    我有一个继承自基类模板的类模板 基类模板有一个数据成员和一个成员函数模板 我想从我的超类中调用它 我知道为了消除对成员函数模板的调用的歧义 我必须使用template关键字 我必须明确引用this在超级班里 this gt base mem
  • C 中的静态和动态绑定(严格来说是 C,而不是 C++)是什么?

    我最初对发布这个问题感到担忧 以免它重复 但即使在谷歌搜索了许多关键字之后 我在 StackOverflow 上找不到任何解释 C 的静态和动态绑定的链接 尽管有 C 的问题和答案 但是都涉及classes以及显然不适合 C 的东西 Sta
  • 如何设置 Swashbuckle 与 Microsoft.AspNetCore.Mvc.Versioning

    我们有asp net core webapi 我们添加了Microsoft AspNetCore Mvc Versioning and Swashbuckle拥有招摇的用户界面 我们将控制器指定为 ApiVersion 1 0 Route
  • 如何获取通过网络驱动器访问的文件的 UNC 路径?

    我正在 VC 中开发一个应用程序 其中网络驱动器用于访问文件 驱动器由用户手动分配 然后在应用程序中选择驱动器 这会导致驱动器并不总是映射到相同的服务器 我该如何获取此类文件的 UNC 路径 这主要是为了识别目的 这是我用来将普通路径转换为

随机推荐