BlazorHybrid 透過Blazor簡單呼叫本機功能

AlexChow發表於2024-06-09

簡單呼叫本機功能,例如列印,獲取硬體資訊,獲取本機使用者名稱,攔截JS功能,攔截錯誤資訊等等..

廢話不多說先來截圖

使用 JsBridge

JsBridge不科普了,同學們自行百度一下

BlazorWebView.cs

using Microsoft.AspNetCore.Components.WebView;
using Microsoft.AspNetCore.Components.WebView.WindowsForms;
using Microsoft.VisualBasic.ApplicationServices;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
using System.Runtime.InteropServices;
using WebView2Control = Microsoft.Web.WebView2.WinForms.WebView2;

public partial class InitBlazorWebView
{
    BlazorWebView _blazorWebView;

    public InitBlazorWebView(BlazorWebView blazorWebView)
    {
        _blazorWebView = blazorWebView;
        _blazorWebView.BlazorWebViewInitialized += BlazorWebViewInitialized;
    }

    void BlazorWebViewInitialized(object sender, BlazorWebViewInitializedEventArgs e)
    {
        //使用 JsBridge
        InitializeBridgeAsync(e.WebView);
    }

    #region JsBridge

    static BridgeObject obj = new BridgeObject();

    /// <summary>
    /// 自定義宿主類,用於向網頁註冊C#物件,供JS呼叫
    /// </summary>
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ComVisible(true)]
    public class Bridge
    {
        public string Func(string param) => $"Func返回 {param} {obj.MacAdress}";
        public string Print(object param) => $"Print返回 {param}";
        public void PrintDemo(object param) => MessageBox.Show($"Print {param}");
        public void Alert(string param) => MessageBox.Show(param);
        public string GetUserName() => Environment.MachineName + "/" + Environment.UserDomainName + "/" + System.Windows.Forms.SystemInformation.UserName  ;

    }

    public class BridgeObject
    {
        public string MacAdress => $"{DateTime.Now:G}";
    }

    async void InitializeBridgeAsync(WebView2Control webView)
    {
        webView.CoreWebView2.AddHostObjectToScript("bridge", new Bridge());
        await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var bridge= window.chrome.webview.hostObjects.bridge;");
        await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync($"localStorage.setItem('macAdress', '{obj.MacAdress}')");

    }

    #endregion
}

Blazor測試元件

Tips: 不一定要在win端執行,在遠端部署也可以的.

JsBridge.razor

@using BootstrapBlazor.Components

<GroupBox Title="Bridge">
    <Button Text="GetMacAdress" OnClick="GetMacAdress" IsDisabled="!BridgeEnabled" />
    <Button Text="Print" OnClick="OnPrint" IsDisabled="!BridgeEnabled" />
    <Button Text="使用者名稱" OnClick="GetUserName" IsDisabled="!BridgeEnabled" />
</GroupBox>

<GroupBox Title="攔截JS">
    <button class="btn btn-primary" role="button" onclick="alert('來自Blazor的alert警告框')">Alert</button>
    <button class="btn btn-primary" role="button" onclick="console.error('You made a mistake')">console.error</button>

    <button class="btn btn-primary" role="button" onclick="print('來自Blazor的print')">Print</button>
</GroupBox>
<pre> 
@message
</pre>

JsBridge.razor.cs

public partial class JsBridge
{
    string? message;
    bool BridgeEnabled;

    [Inject, NotNull]
    IJSRuntime? JS { get; set; }

    [Inject, NotNull]
    ToastService? ToastService { get; set; }
    [Inject, NotNull]
    IJSRuntime? JS { get; set; }

    [Inject, NotNull]
    ToastService? ToastService { get; set; }

    //private IJSObjectReference? module;

    async Task GetMacAdress()
    {
        //message = await module!.InvokeAsync<string>("GetMacAdress");
        //await ToastService.Information("JS方式 macAdress", message);

        message = await JS!.InvokeAsync<string>("eval", $"localStorage.getItem('macAdress');");
        await ToastService.Information("eval macAdress", message);

        message = await JS!.InvokeAsync<string>("eval", "bridge.Func('測試')");
        await ToastService.Information("eval bridge.Func", message);
    }
    async Task OnPrint()
    {
        message = await JS!.InvokeAsync<string>("eval", $"bridge.Print('列印文字123456789')");
        await ToastService.Information("eval bridge.Print", message);

        message = await JS!.InvokeAsync<string>("eval", $"bridge.Print({ItemsPrint.ObjectToJson()})");
        await ToastService.Information("eval bridge.Print object", message);

    }
    async Task GetUserName()
    {
        message = await JS!.InvokeAsync<string>("eval", $"bridge.GetUserName()");
        await ToastService.Information("eval bridge.GetUserName", message);

    }

    string[] ItemsPrint = ["Item1", "Item2", "Item3"];

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        try
        {
            if (firstRender)
            {
                BridgeEnabled = await JS!.InvokeAsync<bool>("eval", $"typeof bridge != 'undefined'");
                message = await JS!.InvokeAsync<string>("eval", $"localStorage.getItem('macAdress');");
            }
        }
        catch (Exception e)
        {
            message = e.Message;
        }
        StateHasChanged();
    }

}

win端js攔截方式

BlazorHybrid.Win/wwwroot/jsbridge.js

function alert(message) {
    console.info(message);

    if (bridge != null) {
        //呼叫C#方法
        bridge.Alert(message);
    }
} 

var oldPrintFunction = window.print;
var oldConsoleErrorFunction = console.error;

window.print = function (e) {
    console.log('Gonna do some special stuff');
    if (bridge != null) {
        //呼叫C#方法
        bridge.PrintDemo('列印物件示例: '+e);
    } else {
        oldPrintFunction();
    }
};
console.error = function (e) {
    if (bridge != null) {
        //呼叫C#方法
        bridge.Alert(e);
    } else {
        oldConsoleErrorFunction(e);
    }
};

function beforePrint() {
    console.log('Do something special before print');
}

function afterPrint() {
    console.log('Do something after print');
}

if (window.matchMedia) {
    window.matchMedia('print').addListener(function (mql) {
        if (mql.matches) {
            beforePrint();
        }
        else {
            afterPrint();
        }
    });
}

// For IE, does not attach in browsers that do not support these events
window.addEventListener('beforeprint', beforePrint, false);
window.addEventListener('afterprint', afterPrint, false);

BlazorHybrid.Win/wwwroot/index.html

    <script src="jsbridge.js"></script>

歡迎大佬加入Maui Blazor 中文社群QQ群 645660665 ,感謝star 相關開源專案

群專案快速入門
https://github.com/densen2014/BlazorHybrid/blob/master/快速上手.md?wt.mc_id=DT-MVP-5005078

相關文章