2026年8月3日 星期一

Chrome 允許特定網站發出聲音

最近初初再學習日文,在查詢 Forvo 網站的單字發音時,發現每個單字通常都有多位網友提供的音檔。如果需要一個一個手動點擊聆聽,實在缺乏效率且沒有耐心。

剛好試試網頁自動化的工具: 油猴 (篡改猴) ,寫完的 JS先在 Chrome 的 F12 Console 中測試,當時一切正常,音檔能夠一個接一個順利播放。但是從油猴執行時,腳本卻卡住不動。直到手動按下其中一個 Play 按鈕後才會開始啟動。

原來是近年 Chrome 為了防止網站載入時自動播放影音而影響使用者體驗,預設會阻擋未經手動互動的自動播放行為。

經過測試,從網路上找到最簡單的解法是直接將網站加入 Chrome 的音效白名單中。設定方式如下:

  • 功能路徑: 在網址列輸入 chrome://settings/content/sound,即可將目標網站指定加入允許發出聲音的白名單中。



-  參考資料  Chrome 自動播放政策

-  自動撥發所有 forvo 音檔 / Gemini 產生 JS
// ==UserScript==
// @name         forvoAllPlay
// @namespace    http://tampermonkey.net/
// @version      2026-08-04a
// @description  Click all "Play" in the page
// @author       E1 Taiwan
// @include      https://zh.forvo.com/word/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=forvo.com
// @grant        none
// ==/UserScript==

function anchorclick(node)
{
    var evt = document.createEvent("MouseEvents");
    evt.initMouseEvent("click", true, true, window,
                       0, 0, 0, 0, 0, false, false, false, false, 0, null);
    var allowDefault = node.dispatchEvent(evt);
}


(function() {
    'use strict';

    // 詢問是否執行
    if (!confirm('是否要開始自動點擊播放按鈕?')) {
        console.log('使用者已取消執行。');
        return;
    }

    console.log('將在 3 秒後開始執行...2');

    // 等待網頁完全載入(含外部 JS 載入完成)
    window.addEventListener('load', () => {
        // 延遲 1.5 秒執行,確保 Forvo 官方的 Play 函數與音訊組件已完全初始化
        setTimeout(async () => {
            // 選擇頁面上所有發音按鈕
            const playButtons = document.querySelectorAll('.play');

            if (playButtons.length === 0) {
                console.log("[Forvo Player] 網頁載入完成,但未找到任何發音按鈕。");
                return;
            }

            console.log(`[Forvo Player] 偵測到 ${playButtons.length} 個發音,準備依序自動播放...`);
            console.log("[Forvo Player] 提示:如果語音沒聲音,請滑鼠點擊網頁任意處以解除瀏覽器自動播放限制。");

            // 依序播放每個發音
            for (let i = 0; i < playButtons.length; i++) {
                const btn = playButtons[i];

                // 擷取並清洗 onclick 內的 JavaScript
                let rawCode = btn.getAttribute('onclick');
                if (!rawCode) continue;

                let cleanCode = rawCode.replace(/return\s+false;?\s*$/, '');

                console.log(`[Forvo Player] 正在播放 (${i + 1}/${playButtons.length})`);

                try {
                    // 執行 Forvo 原生的播放函數
                    new Function(cleanCode)();
                } catch (e) {
                    console.error("[Forvo Player] 播放執行失敗:", e);
                }

                // 每個發音間隔 4 秒,避免語音重疊(可根據需求調整此數值)
                await new Promise(resolve => setTimeout(resolve, 3000));
            }

            console.log("[Forvo Player] 所有發音已播放完畢。");
        }, 1500);
    });
})();

2026年7月29日 星期三

內部 IIS 設定 SSL

Chrome 及大部份的瀏覽器對於沒有安裝HTTPS 的網站,都會出現警告甚至想連進去都要半強迫連線。對於一些小網站或是沒有資安考量的資料分享網站的確是件麻煩事,重點是得花錢買SSL憑証,這種類似過路費的方式我覺得又是商人的手法。

平常公司內部,只開放內網連線網站也要安裝SSL倒是有點畫蛇添足,中小企業內部使用的網站通常會用IP直連,例: http://192.168.0.1/erp,或是直接用主機名稱連線 http://server/erp,這時連線內部網站就出現沒有 HTTPS的警告,只能找些簡單的方式,不花錢的方式設定SSL憑證。此次就試著設定IIS+HTTPS的步驟作個記錄。

 1 設定 DNS 新增網址

設定 DNS 新增網址


2 設定 IIS HTTPS 網站




3 執行 win-acme 安裝 Let’s Encrypt 憑證

憑證有效日期是三個月,可以手動更新或是建立 schedule task 自動更新。

4 設定 router NAT RTF8207W-E



參考資料:  https://ithelp.ithome.com.tw/articles/10260641 

2026年4月24日 星期五

Vue 引用錯誤: Missing ref owner context. ref cannot be used on hoisted vnodes.

- 錯誤訊息
[Vue warn]: Missing ref owner context. ref cannot be used on hoisted vnodes. A vnode with ref must be created inside the render function. 

  - 引用前端插件 
Vue: v3 
chart.js: v4+ 
vue-chartjs: v5+ 

  - 說明 
此測試程式是 CDN 方式,以輕前端方式開發,所以手動引用 plug-in。初期猜測是程式中的語法造成此錯誤,但多方 try-error 加上網路上資料後仍不得解。 有中國網友 PO 文提到這個問題,但說明不太清楚還是卡在這個錯誤無法產生圖表。最後心血來潮將 vue-chartjs 引用 ESM 改為一般的 JS 檔案,順利解決。 



    


- 參考資料 
解决vue-chartjs在ESM模块导入时出现的引用错误问题 https://blog.gitcode.com/8eb95d906b3286a46aee671826e0d9f8.html

2020年5月13日 星期三

WeMos D1 測試 OUTPUT 錯誤

最近測試一塊WeMos D1 WiFi Arduino UNO 開發板ESP8266,測試輸出時總是失敗,一下懷疑板子問題,一下懷疑電源問題。總算找到這個微不足道的解法:配合接腳號由 4 改為 D4。

2018年11月18日 星期日

VS2017 打包安裝檔問題–管理者權限

Win10 的安全性比較嚴謹,自行開發的程式安裝後執行會出現漏斗轉個幾下就停止了,這個況狀還不是出現程式無回應就是 Win10 直接就結束程式。最簡單的解決方式是在圖示上按右鍵選擇:以系統管理員身份執行
image
不過要請使用者每回都要選擇”以系統管理員身份執行”,的確是有些麻煩。經過網路找解法,試過 app.manifest 中設定 requireAdministrator,但程式仍直接被 Win10 關閉。最後找到直接寫 code 提示使用者需要系統管理員權限的題示畫面,但使用者只要按下 “是” 就可以執行。
image

以下 sample code 來源: https://dotblogs.com.tw/alexwang/2016/09/21/234628
 [STAThread]
        static void Main()
        {
            var wi = WindowsIdentity.GetCurrent();
            var wp = new WindowsPrincipal(wi);

            if (!wp.IsInRole(WindowsBuiltInRole.Administrator))
            {
                var processInfo = new ProcessStartInfo();
                // The following properties run the new process as administrator
                processInfo.UseShellExecute = true;
                processInfo.FileName = Application.ExecutablePath;
                processInfo.Verb = "runas";

                // Start the new process
                try
                {
                    Process.Start(processInfo);
                }
                catch (Exception ex)
                {
                    // The user did not allow the application to run as administrator
                    MessageBox.Show("Sorry, this application must be run as Administrator.\n" + ex.Message);
                }

            }
            else
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form2());
            }
        }

2018年8月14日 星期二

C# 小撇步

C# 6.0 dictionary 初始化的新寫法

var dict = new Dictionary<string, int>
{
    ["one"] = 1,
    ["two"] = 2,
    ["three"] = 3
};

2018年7月31日 星期二

.NET MapHttpRoute 與 MapPageRoute

需求: URL 輸入 http://xxxx/yyy 轉成 http://xxxx/yyy.html

最近趕流行,用 vue 寫了一個 SAP(Single application page),html網頁在 MVC 的架構下可成功執行,但我就是想讓使用者操作上更方便,只要輸入網址 route 就直接跳轉到此 html 頁面。如果照原本 MapHttpRoute的方式會造成 .NET 出現找不到 Controller 的問題。最後發現不用 MapHttpRoute 去解此問題,使用MapPageRoute才是正解。

            // Web API routes
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );


以下增加於 Global.asax.cs  

    public class Global : HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            // Code that runs on application startup
            GlobalConfiguration.Configure(WebApiConfig.Register);
            // 新增加以下 route 
            RegisterRoutes(RouteTable.Routes);
        }
        void RegisterRoutes(RouteCollection routes)
        {
            routes.MapPageRoute("",
                        "yyy", "~/yyy.html");
        }
    }

Web.Config 加上對應的 extension
<compilation debug="true" targetFramework="4.5.2">
<buildProviders >
<add extension=".html" type="System.Web.Compilation.PageBuildProvider"/>
<add extension=".htm" type="System.Web.Compilation.PageBuildProvider" />
</buildProviders >
</compilation>