『DotNetBrowser』.Net的浏览器嵌入组件,该选择DotNetBrowser 还是 CefSharp?

news2024/11/25 18:50:26

请添加图片描述
请添加图片描述
📣读完这篇文章里你能收获到

  • 全方位对比DotNetBrowserCefSharp的优缺点

请添加图片描述

文章目录

  • 一、引言
  • 二、引擎
  • 三、架构
    • 1. CefSharp架构
    • 2. DotNetBrowser架构
  • 四、对比
    • 1. 稳定性和内存使用
    • 2. 应用程序域
    • 3. AnyCPU
    • 4. H.264, AAC
    • 5. 安全
    • 6. Visual Studio设计器
    • 7. 嵌入应用程序 UI
    • 8. 高DPI
    • 9. 异步
    • 10. API和功能
      • 10.1 DOM访问
      • 10.2 与JavaScript交互
      • 10.3 从JavaScript调用.NET
      • 10.4 截屏
    • 11. 分发和部署
    • 12. 支持和更新
  • 五、总结

请添加图片描述

一、引言

将浏览器嵌入 .NET 应用程序中:DotNetBrowser 还是 CefSharp
image.png
为 WPF 或 WinForms 应用程序选择浏览器组件,对于那些搜索基于Chrome的解决方案的人来说,, DotNetBrowser和CefSharp是最明显的选择。
本文是在考虑其项目的开源库和商业库时提出的最常见比较点的汇总。

请添加图片描述

二、引擎

  • CefSharp 实际上是Chromium Embedded
    Framework (CEF) 的 .NET 包装器。包装通过C++/CLI 完成。
  • DotNetBrowser 在底层不使用 CEF 或 C++/CLI。相反,它采用了自己的方法直接与 Chromium 集成。它启动一个功能齐全的 Chromium 引擎,并通过进程间通信 (IPC) 与其进行通信。

请添加图片描述

三、架构

1. CefSharp架构

CefSharp 中,Chromium 引擎直接在.NET进程中初始化。初始化和关闭都必须在主应用程序线程(通常是 UI 线程)中执行。在不同的线程中调用它们通常会导致冻结。
此外,每个进程可以执行一次初始化和关闭。这个限制来自 CEF 本身。在执行关闭后尝试重新初始化 CefSharp 将导致错误。以下为CefSharp的架构图:
image.png

2. DotNetBrowser架构

DotNetBrowser 中,Chromium 引擎在单独的本机进程中进行初始化。不需要在主 UI 线程上执行此操作——即使在工作线程中也可以执行此操作。
可以同时初始化和使用具有不同配置的多个 Chromium 引擎,这在 CefSharp 中是不可能的。可以在不再需要 Chromium 时将其关闭并随时重新初始化。
DotNetBrowser架构图如下:
image.png

请添加图片描述

四、对比

1. 稳定性和内存使用

在单独的进程中运行 Chromium 有更多优点:

  1. 在这种情况下,内存消耗要低得多,这对于 32 位应用程序来说十分关键。
  2. CefSharp 中,如果 CEF 或 C++/CLI 绑定内部出现问题,这将导致整个 .NET 应用程序崩溃而无法处理这种情况。因为 .NET 应用程序可能会丢失或损坏用户的数据。
  3. 对于 DotNetBrowser,Chromium 内部的错误不会导致 .NET 应用程序崩溃。此外,甚至可以在托管代码中正确检测和处理这一切。例如,如果发生这种情况,那么可以重新初始化 Chromium 并恢复用户会话。

2. 应用程序域

由于架构原因,CefSharp不能在非默认AppDomain中使用。

  • 因此,CefSharp 不能用于通过 VSTO 插件或 Excel-DNA 将 Chromium 嵌入到 Office 应用程序中。 Office VSTO 将加载项加载到单独的AppDomain中以进行隔离。
  • DotNetBrowser 在非默认 AppDomain 中运行。可以在不同的 AppDomain 中创建多个 Chromium 引擎并同时使用它们。因此,DotNetBrowser 可用于创建 VSTO 加载项。

3. AnyCPU

在针对 AnyCPU 的应用程序中

  • 使用 CefSharp 时,你会发现它在这些应用程序的 64 位环境中无法正常工作。这儿有几个选项可以解决这个问题。其中之一是让你的应用程序始终在 32 位模式下运行,另一个更复杂,需要修改项目文件(.csproj或.vbproj)和代码。
  • DotNetBrowser 中,AnyCPU 支持开箱即用。因此,不需要类似的调整。

4. H.264, AAC

视频和音频通常使用专有编解码器进行编码,例如 H.264 和 AAC。

  • 此媒体无法在 CefSharp 中播放。要在 CefSharp 中启用这些编解码器,需要在启用专有编解码器的情况下自行重建 CEF。这是一项相当复杂的任务,可能需要长达一个月的时间。
  • DotNetBrowser 中默认禁用专有编解码器。可以通过编程方式启用它们,而无需重建库。
IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
    ProprietaryFeatures = ProprietaryFeatures.H264 | ProprietaryFeatures.Aac
}.Build());

5. 安全

Chromium 通过利用操作系统为它们提供的安全性来限制其渲染器和实用程序进程。此功能称为Chromium沙箱。其主要目的是防止第三方代码对计算机进行持久更改或访问机密信息。

  • CefSharp 不支持Chromium沙箱。这个限制来自 CEF 本身。
  • DotNetBrowser 支持沙箱并默认启用。如有必要,可以在初始化期间将其禁用。

而关于Chromium 中的漏洞

  • CefSharp 在 .NET 进程中启动 Chromium。这使你的应用程序容易受到 CEF 和 Chromium 中的漏洞的影响。如果恶意软件获得了对 Chromium 内存的访问权,它也会获得对 .NET 内存的访问权。
  • DotNetBrowser 在单独的进程中启动 Chromium。 Chromium 漏洞保留在 Chromium 中。

6. Visual Studio设计器

现代 WPF 和 Windows 窗体应用程序通常是在设计器的帮助下在 Visual Studio 中创建的。这种方法总体上简化了 UI 创建并节省了大量时间和精力。

  • CefSharp 提供有限的设计器支持。如果应用程序本身以 x86 为目标,则其控件将在设计器中正确处理。 AnyCPU 可能会工作,但尚未经过彻底测试。
  • DotNetBrowser 控件是纯 UI 控件,它们在代码中显式初始化。可以在设计器中不受任何限制地使用它们。安装 NuGet 包或 VSIX 扩展后,BrowserView 控件出现在工具箱中。它可以像任何其他常规 UI 控件一样被拖到窗体或窗口上。

7. 嵌入应用程序 UI

  • CefSharp 提供 WPF 和 Windows 窗体支持。但是,它的 WPF 实现只能在离屏渲染模式下工作。此实现具有有限的触摸屏和IME支持。
  • DotNetBrowser 在两种渲染模式下同时支持 WPF 和 Windows 窗体。在硬件加速模式下,触摸、手势和 IME 由 Chromium 自行处理,因此它们开箱即用。在离屏模式下,存在一些已知的限制。

以下是将 CefSharp 嵌入 WPF 窗口的方法:

<Window x:Class="CefSharpWpf.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
            <wpf:ChromiumWebBrowser Address="https://www.google.com"/>
    </Grid>
</Window>
  • 就是这样,在最简单的情况下,不再需要编写代码。但是,在这种情况下,CefSharp 初始化和关闭是隐式执行的,很难确定它是否已经在某个点初始化。

DotNetBrowser 嵌入 WPF 窗口的过程需要额外的步骤。例如:
MainWindow.xaml:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WPF="clr-namespace:DotNetBrowser.Wpf;assembly=DotNetBrowser.Wpf"
    x:Class="Embedding.Wpf.MainWindow"
    Title="MainWindow" Height="480" Width="800" Closed="Window_Closed">
    <Grid>
            <WPF:BrowserView Name="browserView" />
    </Grid>
</Window>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    private const string Url = "https://www.google.com";
    private readonly IBrowser browser;
    private readonly IEngine engine;

    public MainWindow()
    {
        // Create and initialize the IEngine instance.
        EngineOptions engineOptions = new EngineOptions.Builder
        {
            RenderingMode = RenderingMode.HardwareAccelerated
        }.Build();
        engine = EngineFactory.Create(engineOptions);

        // Create the IBrowser instance.
        browser = engine.CreateBrowser();

        InitializeComponent();

        // Initialize the WPF BrowserView control.
        browserView.InitializeFrom(browser);
        browser.Navigation.LoadUrl(Url);
    }

    private void Window_Closed(object sender, EventArgs e)
    {
        browser?.Dispose();
        engine?.Dispose();
    }
}

在这里,大部分代码都与 Chromium 实例和IBrowser 实例的显式初始化和关闭有关。 UI 控件初始化是通过调用InitializeFrom()显式执行的。这种方法可以更好地控制初始化和关闭过程,并且更容易自定义初始 Chromium 配置。

8. 高DPI

  • CefSharp 中,浏览器子进程的默认 DPI 感知是 Per-Monitor。因此,桌面应用程序应具备DPI感知功能,才能在高 DPI 显示器(DPI 比例设置大于 100% 的显示器)上正确运行。在其他情况下,浏览器内容可能无法正确呈现,例如:

image.png

  • DotNetBrowser 以不同的方式支持高 DPI。在初始化过程中,它会检查当前进程的 DPI 感知,并为相应的 Chromium 引擎设置匹配的 DPI 感知。因此,无需让应用程序显式识别 DPI 以避免在高 DPI 显示上呈现伪影。

image.png

9. 异步

DotNetBrowser 和 CefSharp 都可以在没有 UI 的应用程序中使用。

  • CefSharp 中,CefSharp.OffScreen.ChromiumWebBrowser用于此目的。初始化过程通常保持不变。但是,如果代码使用 async/await 模式,则需要使用同步上下文来确保在主线程上而不是在不同的工作线程上执行初始化和关闭。
  • 要在没有 UI 的应用程序中使用 DotNetBrowser,需要像往常一样执行初始化。在这种情况下,没有需要初始化的BrowserView。即使代码使用async/await模式,也无需创建和使用同步上下文。

10. API和功能

这两种产品都有许多可用的功能。在本文中,我将比较几个最重要的,以展示 API 的不同之处。

10.1 DOM访问

  • CefSharp 中,只能通过执行 JavaScript 调用来访问 DOM。
var script = @"
    document.getElementsByName('question')[0].value = 'CefSharp Example';
    document.getElementsByName('btn')[0].click();
";
browser.ExecuteScriptAsync(script);
  • DotNetBrowser 提供了丰富的 DOM API,可用于直接从 .NET 执行以下操作:
IDocument document = browser.MainFrame.Document;
(document.GetElementByName("question") as IInputElement).Value = "DotNetBrowser Example";
document.GetElementByName("btn").Click();
  • 访问和修改 DOM 树
  • 更改 HTML 元素属性
  • 订阅 DOM 事件并从 .NET 代码中调度它们

因此,在 DotNetBrowser 中与网页执行复杂的交互要方便得多。无需编写难以调试和支持的复杂 JavaScript 代码。 DotNetBrowser 中的 DOM API 不是一组 JavaScript 调用的包装器。它直接对 Blink 引擎进行 IPC 调用。

10.2 与JavaScript交互

执行JavaScript并处理结果

  • CefSharp 和 DotNetBrowser 都提供了在网页上执行 JavaScript 的能力。在 CefSharp 中,有两种方法可用于此目的,ExecuteJavaScriptAsync和EvaluateScriptAsync。两者都可用于浏览器本身(通过扩展方法)或其中的一个框架:
// Execute JavaScript without returning a result. The method returns 
// before the script has actually been executed.
browser.ExecuteJavaScriptAsync("alert('All Resources Have Loaded');");

// Evaluate some Javascript code. The script will be executed asynchronously 
// and the method returns a Task encapsulating the response from the 
// JavaScript.
JavascriptResponse response = await browser.EvaluateScriptAsync(script);

然后使用JavascriptResponse.Result获取执行结果。可能的结果类型有 bool, int, long, double, string, List, IDictionary<string, object>, 和IJavascriptCallback。这里的集合是 JavaScript 集合的快照表示,而IJavascriptCallback是一种 JavaScript 函数表示,可用于从 .NET 端执行它。

  • DotNetBrowser 中,有 IFrame.ExecuteJavaScript()用于此目的。此方法的通用版本可用于显式指定预期的返回类型:
string title = await browser.MainFrame.ExecuteJavaScript<string>("document.title");
IJsObject window = await browser.MainFrame.ExecuteJavaScript<IJsObject>("window");
IElement body = await browser.MainFrame.ExecuteJavaScript<IElement>("document.body");

这里的主要区别是可以将 JavaScript 对象表示为IJsObject。使用此接口,可以访问和修改 JavaScript 对象的属性并调用其方法。在 .NET 端对IJsObject所做的所有更改都将立即反映在 JavaScript 端。此外,ExecuteJavaScript调用可以返回一个IElement,这是一个 DOM 元素的表示,可以使用它来访问和修改 DOM 属性或订阅 DOM 事件。

10.3 从JavaScript调用.NET

CefSharp 和 DotNetBrowser 都可以使网页上的 JavaScript 可以访问 .NET 对象,但是,CefSharp 存在一些特定的限制。

  • CefSharp JavaScript 绑定可用于 JavaScript 和 .NET 之间的通信。但是,CefSharp 不允许将Form, Window或任何Control注入 JavaScript。另外,CefSharp 只支持调用注入对象的方法。如果需要设置属性,则必须修改类并创建 Get/Set 方法。
  • DotNetBrowser 中,可以将任何对象注入 JavaScript,包括 Form, Window和Control对象。执行注入后,可以访问注入的 .NET 对象的公共字段、属性和方法。此外,DotNetBrowser 支持从 JavaScript 访问索引属性(使用字符串或数字索引器)。如果需要从 JavaScript 访问 .NET 集合,这会很有帮助。

10.4 截屏

两种解决方案都支持在浏览器不可见时进行截屏。但是,API 有明显不同。以下是代码片段:
在CefSharp中截图:

// Take a screenshot
var bitmapAsByteArray = await browser.CaptureScreenshotAsync();

// Save the screenshot as PNG
var screenshotPath = Path.GetFullPath("screenshot.png");
File.WriteAllBytes(screenshotPath, bitmapAsByteArray);

在DotNetBrowser中截图:

// Take a screenshot
DotNetBrowser.Ui.Bitmap image = browser.TakeImage();

// Convert the screenshot to System.Drawing.Bitmap and save it as PNG
System.Drawing.Bitmap bitmap = image.ToBitmap();
bitmap.Save("screenshot.png", ImageFormat.Png);

主要的 DotNetBrowser DLL 不使用System.Drawing中的类型,因为它的限制,因此,它提供了自己的类型。然后可以通过DotNetBrowser.Wpf或DotNetBrowser.WinForms中提供的扩展方法将此类型转换为常规System.Drawing.Bitmap。

11. 分发和部署

  • CefSharp 需要Microsoft Visual C++运行时存在于环境中。 Visual C++ 2015 是最低版本,但所需的确切版本取决于 Chromium 版本。因此,需要在希望运行基于 CefSharp 的应用程序的每台机器上预安装 Microsoft Visual C++ Redistributable Package,将其设置为安装程序的依赖项,或将其 DLL 打包为应用程序的一部分,并确保 CefSharp 正确找到它们。
  • DotNetBrowser 中,所有必需的 Chromium 二进制文件和 DLL 都已打包到 DotNetBrowser DLL 中,并且可以在执行期间自动提取。无需预先安装 Microsoft Visual C++ Runtime 即可使用 DotNetBrowser。

12. 支持和更新

  • CefSharp 是一个开源项目。如果发现错误或缺少功能,可以提出建议。
  • DotNetBrowser是为使用.NET开发软件的商业公司设计和创建的商业产品,对集成第三方解决方案的质量和支持有很高的要求。自 2015 年以来,TeamDev 开发并支持 DotNetBrowser。

所有已订阅有效标准支持的客户都可免费使用所有DotNetBrowser 新版本并获得技术支持。如果发现错误或缺少功能,提交反馈即可。
几乎每个月都会发布一个新版本的 DotNetBrowser。会在 Chromium 正式发布后的 3-4 周内将 Chromium 升级到最新的稳定版本(带有最新的安全补丁和修复的漏洞)。

请添加图片描述

五、总结

因为开源和免费,CefSharp 被广泛使用。它很容易为基本案例进行配置,并且拥有广泛的文档和活跃的开源开发者社区。
但是,它具有来自其设计和架构的限制。缺少沙盒支持使其安全性降低,并且进程内方法会影响稳定性并增加应用程序的内存使用量。
它也不能用于暗示在单独的 AppDomain(如 VSTO)中运行代码的环境。对于其他一些情况,例如播放使用专有编解码器编码的内容,必须自己构建、更新和维护 CEF。这需要大量额外的工作和基础设施。
与加载的网页的复杂交互会通过 JavaScript 注入执行,这使得生成的代码更难调试和支持。
DotNetBrowser 简化了所有这些案例的开发过程——由于它的进程外架构,它可以用于创建更稳定和安全的解决方案。使用 DotNetBrowser,可以与需要在单独的 AppDomain 中运行代码的应用程序集成,并在网页上执行复杂的操作,而无需进行大量的 JavaScript 注入。
除此之外,如果你觉得缺少某样功能、发现某些问题或有其他疑问,你可以随时与DotNetBrowser团队联系并获得帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/722792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过DAPLink和STLink使用RTT输出日志

前提 阅读此文章的前提是已经移植好SEGGER RTT&#xff0c;如未移植请参考我的另一篇博客 《基于J-Link RTT Viewer输出日志(适用于JLink DAPLink STLink)》 由于SEGGER RTT 自带的 JLinkRTTViewer.exe 只支持自家的J-Link&#xff0c;所以使用DAPLink和STLink我们得另辟蹊径…

【设计模式】第二十一章:命令模式详解及应用案例

系列文章 【设计模式】七大设计原则 【设计模式】第一章&#xff1a;单例模式 【设计模式】第二章&#xff1a;工厂模式 【设计模式】第三章&#xff1a;建造者模式 【设计模式】第四章&#xff1a;原型模式 【设计模式】第五章&#xff1a;适配器模式 【设计模式】第六章&…

shiro系列vulhub所有漏洞复现CVE-2020-1957、CVE-2016-4437、CVE-2010-3863、shiro-721 代码执行

文章目录 Apache Shiro 认证绕过漏洞&#xff08;CVE-2020-1957&#xff09;漏洞详情&#xff1a;复现&#xff1a; Apache Shiro 1.2.4反序列化漏洞&#xff08;CVE-2016-4437&#xff09;漏洞详情&#xff1a;复现: Apache Shiro 认证绕过漏洞&#xff08;CVE-2010-3863&…

实验二(OSPF+PPP+hub-spoke)7 5

1.合理划分IP地址&#xff1a; R1&#xff1a; R2&#xff1a; R3&#xff1a; R4&#xff1a; R5&#xff1a; R6&#xff1a; 2.启用OSPF单区域&#xff1a; R1及路由表&#xff1a; [r1]display ip routing-table protocol ospf R2及路由表&#xff1a; R3及路由表&#…

Atlassian Jira Software 9.9.1 特别版

敏捷团队首选的软件开发工具&#xff0c;Atlassian Jira Software 专为软件团队中的每位成员构建&#xff0c;可用于规划、跟踪和发布卓越的软件。 Scrum 板 利用可自定义的 Scrum 板&#xff0c;敏捷团队可集中精力尽可能迅速地交付迭代和增量价值。 看板 借助灵活的看板图&am…

【MySQL】在Linux下删除和安装MySQL

文章目录 一、前言二、检查、卸载内置环境三、获取mysql官方yum源四、正式安装MySQL服务五、登录MySQL配置my.cnf设置开机启动 一、前言 大家好久不见&#xff0c;今天开始分享关系型数据库Mysql的一些知识。 二、检查、卸载内置环境 2.1 首先使用命令查询当前mysql的运行状…

解决dbeaver查询结果乱码问题

问题描述&#xff1a; 通过dbeaver查询informinx 查询结果数据集是乱码 解决方案 &#xff1a; 右键编辑连接 在驱动属性里面新增 用户属性 NEWCODESET 值为 GBK,8859-1,819 解决数据库本身就是GBK编码&#xff0c;但是查询结果集编码不一致难题

Python+CNN 手写公式识别计算系统

系统&#xff1a;Win10 环境&#xff1a;Pycharm/Vscode Python3.7 效果图&#xff1a; 部分代码如下&#xff1a; import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchvision import datasets,transforms#定义…

5.8.9 TCP拥塞控制

5.8.9 TCP拥塞控制 我们先来说一个生活中的例子&#xff0c;在节假日到来的时候&#xff0c;由于高速公路免费通行&#xff0c;大量汽车涌上高速公路&#xff0c;最终造成交通拥堵&#xff0c;类似的情况也有可能出现在网络中&#xff0c;由于核心的交换设备在存储、带宽、速率…

ReentrantReadWriteLock读写锁

1、锁的分类 2、读写锁 读锁&#xff1a;共享锁 写锁&#xff1a;独占锁 3、代码01 class MyCache{private volatile Map<String,Object> map new HashMap<>();private ReadWriteLock rwLock new ReentrantReadWriteLock();public void put(String key,Obje…

Windows 如何打开和编辑.lnk文件

文章目录 一、背景二、查看/修改.lnk文件内容方案1&#xff1a;用type命令查看方案2&#xff1a;更改.lnk文件后缀为.txt再查看方案3&#xff1a;用记事本或NodePad打开方案4&#xff1a;使用HxD hex editor十六进制编辑器方案5&#xff1a;使用第三方库查看或编辑1. Matmaus/L…

GO语言中Protocol buffer简介

Protocol buffer 一、Protobuf简介 1.1、RPC 通信 对于单独部署&#xff0c;独立运行的微服务实例而言&#xff0c;在业务需要时&#xff0c;需要与其他服务进行通信&#xff0c;这种通信方式是进程之间的通讯方式&#xff08;inter-process communication&#xff0c;简称I…

机器学习 day23(激活函数的作用,线性激活函数的不足)

线性激活函数的局限性 如果我们将神经网络模型中的所有激活函数都设为线性激活函数&#xff0c;那整个神经网络模型就跟线性回归模型极其相似&#xff0c;且它无法拟合比线性回归模型更复杂的关系 激活函数全设为线性回归激活函数的例子 若把a带入a&#xff0c;则a可简化为…

Unity包体积优化实践

目录 简述优化前优化中assets目录资源ab包动态下发资源大小优化dll大小优化场景模型动态下载和加载优化assets目录后大小 lib目录优化目标架构裁剪代码优化代码和引用 其他优化项Shader优化Release模式编译选项 优化后 简述 在移动端App混合Unity开发的项目中&#xff0c;Unit…

VSCode配置C/C++环境(极简版)

预期结果&#xff1a; 首先安装扩展&#xff1a; 然后按照下面readme.txt中即可 链接&#xff1a;https://pan.baidu.com/s/16OV5Kr82i0gWCc4bvKs42g 提取码&#xff1a;zxcv

【模式识别目标检测】——模式识别技术车牌检测应用

目录 引入 一、模式识别主要方法 1、统计模式识别 2、基于隐马尔可夫模型识别 3、模糊模式识别 4、人工神经网络模式识别 总结 二、模式识别应用 1、车牌定位 2、车牌识别 参考文献&#xff1a; 引入 人在观察事物或现象时&#xff0c;常寻找它与其他事物或现象不同…

江苏某农商行稳健发展,软件安全推动金融服务新气象

​江苏某农商银行是全国最早成立的农商行之一。面对复杂严峻的内外部形势&#xff0c;该农商行在坚守服务“三农”与小微市场的同时&#xff0c;紧跟改革脚步&#xff0c;不断探索业务创新与数字化转型&#xff0c;实现经营稳健发展。 打造多维度数字化体系 驱动农商行创新发展…

QT之一种notifiation使用

简介 使用Qt5实现的消息提醒功能。 本文借助消息通知开源框架实现消息通知功能&#xff0c;软件包在上面。 使用说明 在pro工程中包含qtnotify2.pri 使用举例 include($$PWD/../src/qtnotify2.pri)// 包含头文件 #include "notifymanager.h"// 可建立全局实例 N…

深入理解MySQL数据库存储引擎及数据授权

深入理解MySQL数据库存储引擎及数据授权 一、MySQL数据库存储引擎的概述1.InnoDB引擎2.MyISAM引擎3.Memory引擎 二、MySQL数据授权问题1.用户管理2.数据库级授权3.表级授权4.列级授权5.收回权限 引言&#xff1a; MySQL是一款广泛应用的关系型数据库管理系统&#xff0c;为了满…

Linux常用命令——exportfs命令

在线Linux命令查询工具 exportfs 管理NFS共享文件系统列表 补充说明 exportfs 命令用来管理当前NFS共享的文件系统列表。 参数&#xff1a; -a 打开或取消所有目录共享。 -o options,...指定一列共享选项&#xff0c;与 exports(5) 中讲到的类似。 -i 忽略 /etc/exports 文…