UWInfo Blog
發表新文章
[Join] | [忘記密碼] | [Login]
搜尋

搜尋意見
文章分類-#Author#
[所有文章分類]
所有文章分類
  • ASP.NET (48)
  • ASP.NET2.0 (15)
  • ASP.NET4.0 (34)
  • JavaScript (49)
  • jQuery (26)
  • FireFox (4)
  • UW系統設定 (3)
  • SQL (39)
  • SQL 2008 (25)
  • mirror (4)
  • SVN (4)
  • IE (9)
  • IIS (20)
  • IIS6 (1)
  • 閒聊 (7)
  • W3C (6)
  • 作業系統 (9)
  • C# (24)
  • CSS (12)
  • FileServer (1)
  • HTML 5 (11)
  • CKEditor (3)
  • UW.dll (13)
  • Visual Studio (16)
  • Browser (8)
  • SEO (1)
  • Google Apps (3)
  • 網站輔助系統 (4)
  • DNS (5)
  • SMTP (4)
  • 網管 (11)
  • 社群API (3)
  • SSL (4)
  • App_Inventor (1)
  • URLRewrite (2)
  • 開發工具 (6)
  • JSON (1)
  • Excel2007 (1)
  • 試題 (3)
  • LINQ (1)
  • bootstrap (0)
  • Vue (3)
  • IIS7 (3)
  • foodpanda (2)
  • 編碼 (2)
  • 資安 (3)
  • Sourcetree (1)
  • MAUI (1)
  • CMD (1)
  • my sql (1)
最新回應
  • Newtonsoft.Json.JsonConvert.DeserializeObject 失敗的情況
    test...more
  • dotnet ef dbcontext scaffold
    ...more
  • [ASP.NET] 利用 aspnet_regiis 加密 web.config
    ...more
  • IIS ARR (reverse proxy) 服務安裝
    ...more
  • [錯誤訊息] 請加入 ScriptResourceMapping 命名的 jquery (區分大小寫)
    ...more
  • 用 Javascript 跨網頁讀取 cookie (Cookie cross page, path of cookie)
    ...more
  • 線上客服 - MSN
    本人信箱被盜用以致資料外洩,是否可以請貴平台予以協助刪除該信箱之使用謝謝囉...more
  • 插入文字到游標或選取處
    aaaaa...more
  • IIS 配合 AD (Active Directory) 認証, 使用 .Net 6.0
    太感謝你了~~~你救了我被windows 認證卡了好幾天QQ...more
  • PostgreSQL 的 monitor trigger
    FOR EACH ROW 可能要改為 FOR EACH STATEMENT ...more
標籤
  • apeg
  • db
  • end
  • shopee
  • torto
  • amazo
  • svn
  • HTTP 錯誤 40
  • -1948
  • prop
  • Lucene .Ne
  • 204
  • aspnet_reg
  • 208
  • tim
  • EN
  • highlight
  • FB0
  • -2391 UNIO
  • FB
  • aspx
  • 918
  • utf8
  • sln
  • structure
  • SSl
  • expression
  • pG2rL0AN
  • tls
  • missor
  • vs
  • UW
  • vb
  • login
  • Rf
  • U2
  • JoBSPKYZ
  • Vue
  • ORM
  • async
  • web.config
  • amazone
  • Cache
  • enum
  • rc4
  • c
  • dictionary
  • profiler
  • CROS
  • innerhtml
頁數 1 / 6 下一頁
搜尋 試 結果:
Chrome 連接藍芽 BLE 印表機(出單機),使用 ESC / POS 列印繁體中文和 Qrcode
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>BLE Printer Test</title>
    <script src="https://cdn.jsdelivr.net/npm/iconv-lite-umd@0.6.10/lib/iconv-lite-umd.js"></script>
</head>
<body>
    <h1>BLE Printer Test 123</h1>
    <button id="printTestButton">Test Print</button>
    <button id="printAgain">Print Again</button>
    <pre id="log"></pre>
    <script>
        // Function to log messages on the page
        function logMessage(message) {
            const logElement = document.getElementById('log');
            logElement.textContent += message + '\n';
        }
        var device;
        var server;
        var service;
        var characteristic;
        var name = 'T58_6752'; // 藍芽設備的名稱
        var uuid = 0x1800; //service UUID (用 BLE Scanner 找到的)
        var characteristicUuid = 0x2A00; // characteristic UUID (用 BLE Scanner 找到的)
        // Function to connect to BLE printer and send test data

        async function connectAndTestPrint() {

            try {
                logMessage("Requesting Bluetooth device...");

                // Request the BLE device
                device = await navigator.bluetooth.requestDevice({
                    //acceptAllDevices: true,
                    filters: [
                        { name: name }
                    ],
                    optionalServices: [uuid] // Replace with the correct service UUID
                });

                logMessage(`Device selected: ${device.name}`);
                logMessage(`Device uuid: ${device.id}`);

                await printAgain();


            } catch (error) {
                logMessage(`Error: ${error.message}`);
            }
        }

        // 转码方法
        function stringToGbk(str) {
            const ranges = [
                [0xA1, 0xA9, 0xA1, 0xFE],
                [0xB0, 0xF7, 0xA1, 0xFE],
                [0x81, 0xA0, 0x40, 0xFE],
                [0xAA, 0xFE, 0x40, 0xA0],
                [0xA8, 0xA9, 0x40, 0xA0],
                [0xAA, 0xAF, 0xA1, 0xFE],
                [0xF8, 0xFE, 0xA1, 0xFE],
                [0xA1, 0xA7, 0x40, 0xA0],
            ]
            const codes = new Uint16Array(23940)
            let i = 0

            for (const [b1Begin, b1End, b2Begin, b2End] of ranges) {
                for (let b2 = b2Begin; b2 <= b2End; b2++) {
                    if (b2 !== 0x7F) {
                        for (let b1 = b1Begin; b1 <= b1End; b1++) {
                            codes[i++] = b2 << 8 | b1
                        }
                    }
                }
            }
            const cstr = new TextDecoder('gbk').decode(codes)

            // 编码表
            const table = new Uint16Array(65536)
            for (let i = 0; i < cstr.length; i++) {
                table[cstr.charCodeAt(i)] = codes[i]
            }
            const buf = new Uint8Array(str.length * 2)
            let n = 0

            for (let i = 0; i < str.length; i++) {
                const code = str.charCodeAt(i)
                if (code < 0x80) {
                    buf[n++] = code
                } else {
                    const gbk = table[code]
                    buf[n++] = gbk & 0xFF
                    buf[n++] = gbk >> 8
                }
            }
            u8buf = buf.subarray(0, n)
            // console.log(u8buf);
            return u8buf
        }

        async function printAgain() {
            // Connect to the GATT server
            server = await device.gatt.connect();
            logMessage("Connected to GATT server.");

            // Get the printer service
            service = await server.getPrimaryService(uuid); // Replace with your printer's service UUID
            logMessage("Printer service retrieved.");

            // Get the characteristic for writing data
            characteristic = await service.getCharacteristic(characteristicUuid); // Replace with the correct characteristic UUID
            logMessage("Printer characteristic retrieved.");

            // Prepare test print data
            const encoder = new TextEncoder();
            const testData = encoder.encode("TEST PRINT: Hello from Web Bluetooth!\n");
            const finalData = encoder.encode("--\n--\n \n \n");

            const setFontSize = new Uint8Array([0x1D, 0x21, 0x11]); // GS ! n
            const setFontSize2 = new Uint8Array([0x1D, 0x21, 0x22]); // GS ! n
            const setFontSize3 = new Uint8Array([0x1D, 0x21, 0x33]); // GS ! n

            // Write test data to the printer
            logMessage("Sending test data to printer...");

            await characteristic.writeValue(new Uint8Array([0x1D, 0x21, 0x00]));
            await characteristic.writeValue(encoder.encode("1x1!\n"));
            await characteristic.writeValue(setFontSize);
            await characteristic.writeValue(encoder.encode("2x2!\n"));
            await characteristic.writeValue(setFontSize2);
            await characteristic.writeValue(encoder.encode("3x3!\n"));
            await characteristic.writeValue(setFontSize3);
            await characteristic.writeValue(encoder.encode("4x4!\n"));


            const initPrinter = new Uint8Array([0x1B, 0x40]); // ESC @
            await characteristic.writeValue(initPrinter);

            // 3. 設置字符集為 GBK
            const setGBK = new Uint8Array([0x1B, 0x74, 0x11]); // ESC t 0x11 (GBK)
            await characteristic.writeValue(setGBK);

            const text = "繁體中文測試\n \n";
            const encodedText = stringToGbk(text);
            await characteristic.writeValue(encodedText);
            logMessage("Test data sent successfully!");

            // QrCode 列印
            const qrData = "https://example.com"; // Your QR code data
            const qrDataLength = qrData.length + 3;
            const pL = qrDataLength & 0xFF; // Low byte
            const pH = (qrDataLength >> 8) & 0xFF; // High byte

            const commands = [
                0x1B, 0x40, // Initialize printer
                0x1D, 0x28, 0x6B, pL, pH, 0x31, 0x50, 0x30, ...new TextEncoder().encode(qrData), // Store data
                0x1D, 0x28, 0x6B, 0x03, 0x00, 0x31, 0x51, 0x30 // Print QR code
            ];

            const buffer = new Uint8Array(commands);
            await characteristic.writeValue(buffer);
            logMessage("QrCode sent successfully!");

            await characteristic.writeValue(finalData);
            logMessage("finalData sent successfully!");

            // Disconnect the GATT server
            server.disconnect();
            logMessage("Disconnected from printer.");
        }

        // Bind the function to the button
        document.getElementById('printTestButton').addEventListener('click', connectAndTestPrint);
        document.getElementById('printAgain').addEventListener('click', printAgain);
    </script>
</body>
</html>
More...
Bike, 2025/1/2 下午 02:20:15
還原NuGet程序出錯 (Microsoft Visual Studio)
錯誤代碼 NETSDK1064
找不到套件 BouncyCastle.Cryptography,版本 2.3.0。該套件可能因 NuGet restore 還原而刪除,或是可能因為路徑長度上限的限制,而讓 NuGet restore 可能只有部分完成所致。

試了好久總算可以正常打開
工具>>NuGet套件管理員>>套件管理員設定


重起就可以正常跑了!!!
 
More...
hannah, 2024/5/31 上午 09:48:53
使用 Dependency Injection 的優缺點
優點:
1. 易於單元測試 
2. ??

缺點:
1. 所有的 function 必需先建立 Interface, 暫麻煩.
2. debug 時必需先 trace 到 interface 再 trace 到實際 implement 的 code.
More...
Bike, 2024/2/8 下午 04:38:17
ubuntu server安裝配置
ubuntu安裝時依照版本不同有些會需要先配置mirror site
mirror site的功用是提供下載套件與系統更新的站台
而要連網確認mirror site會需要配置網路接口,DNS與開放防火牆
17.10以後版本可前往 /etc/netplan 底下的.yaml文件內查看設置
相關參數說明↓
addresses: 對外ip (ex: 192.168.1.10/24)
gateway4: 網路關口, IPv4從本機連結網際網路的端口, 通常設定路由器的IP地址
nameservers: 底下的 addresses為DNS位置, 可設置 8.8.8.8 (google的公共服務器)
設置完後執行 sudo netplan apply變更配置
17.10以前的自己去問GPT, 配置差不多只是位置不一樣

輸入'systemd-resolve --status'查看配置
輸入'ping google.com'測試網路是否正常

以上配置完畢 防火牆有開ubuntu以後可以配置mirror site↓
ubuntu官方承認的Site清單
*注意!! 更新封包皆會從設定的Site取得, 雖是官方認證但是仍有風險, 有高度資安需求建議自行架設mirror site*
mirror site的配置於 /etc/apt/sources.list
'deb http://{domain}' 的皆需修改
可使用 ctrl + \ 來一次修改
完成後執行 'sudp apt-get update' 測試mirror site是否連通
More...
梨子, 2023/12/6 上午 10:39:22
AddPath優化
改寫成可輸入多參數,效能也比較好的版本。
以下為測試碼,請自行依照專案需求做修改。

var root = "C://wdqd/qwewq";
var addPath = @"//\\/fwef/qwf";
var addPath2 = @"5fwfef/qwf";
var addPath3 = @"//fwef/qwf";
var addPath4 = @"\\\fwef/qwf";
var addPath5 = @"\\\\\/fwef/qwf";


var result = root.AddPath(addPath, addPath2, addPath3, addPath4, addPath5);

Console.WriteLine(result);

public static class Helper
{
    public static string AddPath(this string value, params string[] addPaths)
    {
        if (string.IsNullOrEmpty(value))
        {
            throw new Exception("起始目錄不可以為空字串");
        }

        if (value.Contains("..") || addPaths.Any(x => x.Contains("..")))
        {
            throw new Exception($"value: {value}, addPaths: {addPaths.Where(x => x.Contains("..")).ToOneString()} 檔名與路徑不可包含 ..");
        }

        var paths = addPaths.Select(x => x.Substring(x.FindLastContinuousCharPosition('/', '\\') + 1).SafeFilename()).ToList();

        if (paths.Any(x => System.IO.Path.IsPathRooted(x)))
        {
            throw new Exception("不可併入完整路徑 ..");
        }

        paths.Insert(0, value.SafeFilename());

        return System.IO.Path.Combine(paths.ToArray());
    }

    public static string ToOneString<T>(this IEnumerable<T> list, string separator = ",")
    {
        var strList = list.Select(x => x.ToString());
        return string.Join(separator, strList);
    }

    public static int FindLastContinuousCharPosition(this string input, params char[] targets)
    {
        int lastPosition = -1;

        for (int i = 0; i < input.Length; i++)
        {
            if (targets.Contains(input[i]))
            {
                lastPosition = i;
            }
            else
            {
                break;
            }
        }

        return lastPosition;
    }

    public static string SafeFilename(this string value)
    {
        return GetValidFilename(value);
    }

    public static string GetValidFilename(string value)
    {
        string ValidFilenameCharacters = @"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\-_$.@:/# ";
        if (value.Contains(".."))
        {
            throw new Exception("路徑中不可包含 .. ");
        }

        string newUrl = "";
        for (int i = 0; i < value.Length; i++)
        {
            var c = value.Substring(i, 1);
            int k = ValidFilenameCharacters.IndexOf(c);
            if (k < 0)
            {
                throw new Exception($"檔名 '{value}' 中有非法的字元 '" + c + "'。");
            }
            newUrl += ValidFilenameCharacters.Substring(k, 1);
        }

        return newUrl;
    }
}
More...
梨子, 2023/8/28 上午 09:43:49
解決 jquery XSS問題,升級到 3.5 版以上之相關處理
最近因為資安公司要求,要把 jQuery 升級到最新版
網路查了一下,似乎 3.5 版以後, XSS 才算是改善很多

目前最新版本是 3.7.0,對於原本就使用 3 以上版本專案影響就不大,所有 function 沿用上沒有問題
但是有些舊專案使用 2.X 甚至 1.X 升級到 3.7.0 版之後就會有些功能掛掉

經測試,首當其衝的就是 $(window).load 不能使用,更精準一點應該是 .load() 不能使用
檢查 jquery 過期網頁 https://api.jquery.com/category/deprecated/
發現 .load() 是 1.8 版以後 deprecated,但我 2.2.4 用很久用爽爽
我想應該是 jquery 為了相容問題,一直到跨版本才真的拿掉
也就是 1.X 宣告 deprecated 的功能,到 3.X 才真的移除
(請看附圖)
所以我就鴕鳥的找 1.X  deprecated 然後可能會用的 function 處理
(若有 tag "Removed" 就是已移除,這樣找比較快)
.andSelf()
.live()
.die()
.error()
.load()
.unload()
.size()
.toggle()

大致上專案搜尋字串應該就能處理
但有些可能是其他第三方 jquery物件 例如 jquery-ui ,會用到以上功能
這時可能要去該物件看有無對應升級版
 
More...
darren, 2023/7/20 上午 11:08:33
Maui With SQLite
試了這兩個 Sample:

https://learn.microsoft.com/en-us/training/modules/store-local-data/4-exercise-store-data-locally-with-sqlite

和 

https://blazorhelpwebsite.com/ViewBlogPost/61

結果專案在 Windows 環境下都可以正常執行,但切換到 Android Emulator 就無法存檔。

在查了很多資料後,發現需要裝額外的 Package,需安裝的 Package 如下:

    <ItemGroup>
     <PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
     <PackageReference Include="SQLiteNetExtensions.Async" Version="2.1.0" />
     <PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.4" />
     <PackageReference Include="SQLitePCLRaw.core" Version="2.1.4" />
     <PackageReference Include="SQLitePCLRaw.lib.e_sqlite3" Version="2.1.4" />
     <PackageReference Include="SQLitePCLRaw.provider.dynamic_cdecl" Version="2.1.4" />
     <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
    </ItemGroup>



其它的發現為:
1. 雙點專案,就可以開啟 csproj 檔案。下方的 ItemGroup 就是已安裝的 package

2. 可以把 chrome 連接到 Android Emulator 的方法,在網址列輸入以下指令:
chrome://inspect/#devices
More...
Bike, 2023/2/12 下午 05:09:11
Postgres 中使用 Transaction (TransactionScope) 必需要自已實做重試的功能
在 Postgres 使用 TransactionScope 似乎很空易就會發生 Transaction Abort 的情況。所以必需自行實做 retry 的機制

            int tries = 0;
            while (tries < Su.PgSql.maxTransactionAborted)
            {
                try
                {
                    using (var scop = new System.Transactions.TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                    {
                        var context = ShopBandContext.Context;

                        updateCount = await context.UpdateAsync<MarketDiscount>(dto, Sc.ModifyInfo,
                            onlyColumns: "StartAt,EndAt,NewPrice,FrontEndMemo,BackEndMemo");

                        scop.Complete();
                        break; //這個 Break 很重要
                    }
                }
                catch (Exception ex)
                {
                    // 我發現因為是非同步模式,所以要檢查很多層的 InnerException
                    if (tries < Su.PgSql.maxTransactionAborted
                        && ((ex.InnerException != null && ex.InnerException is Npgsql.PostgresException && ((Npgsql.PostgresException)ex.InnerException).SqlState == "40001")
                            || (ex.InnerException.InnerException != null && ex.InnerException.InnerException is Npgsql.PostgresException && ((Npgsql.PostgresException)ex.InnerException.InnerException).SqlState == "40001")))
                    {
                        //隨機休息 10 ~ 20 ms, 等另一個 job 完工
                        System.Threading.Thread.Sleep(Su.MathUtil.Random.Next(10, 20));
                        tries++;
                    }
                    else
                    {
                        throw;
                    }
                }
            }
More...
Bike, 2022/8/25 上午 09:19:35
.Net MAUI 測試
使用 android device 時,遇到 "若要建立此專案,必須安裝下列工作負載: maccatalyst" 這個錯誤



In Terminal, install the latest public build of .NET MAUI:

dotnet workload install maui --source https://api.nuget.org/v3/index.json

dotnet workload install android

安裝後要重新啟動 Visual Studio
More...
Bike, 2022/7/30 下午 09:07:35
資料存取架構比較 Entity Framework, Data Table, Dapper
比較方式: 對相同的資料表讀取 1000 次,來比較速度。
資料庫為 MS SQL

這裡做了 4 個 Case:

Case 1: 
使用 Entity Framework,DbContext 為每次 new 一個。

Case 2:
使用 Entity Framework,使用同一個 DbContext。

Case 3:
用 DAO,轉為 Data Table 的格式 (使用 DtFromSql)。

Case 4:
使用 Dapper。

專案啟動時的記憶體使用量約為:  123 MB



測試一:
第一次讀取
Case 1, 時間: 3673.0303 ms, 記憶體: 566 MB

Case 2, 時間:  3889.9379 ms, 記憶體: 304 MB  (這個時間有時會測試到 3000 ms)

Case 3, 時間:  1665.7748 ms, 記憶體: 205 MB

Case 4, 時間:  1639.7211 ms, 記憶體: 193 MB

讀取五次
Case 1, 時間: 1984.6395, 記憶體: 544MB (有發生 GC)


Case 2, 時間:  2367.9792 ms, 記憶體: 627 MB (沒有發生 GC)


Case 3, 時間:  1395.1132 ms, 記憶體: 280 MB (有發生 GC)



Case 4, 時間:  1531.3555 ms, 記憶體: 271 MB


結果: Dapper 看來完勝,速度上和直接使用 DAO 轉進 Data Table 的速度相近。但 Dapper 傳回的結果已經轉換為物件 List, 操作上會更為方便。

Entity Framework 一如預期的較慢,且花費較多的記憶體。但和想像中最大的差異是,使用同一個 DbContext 比 new 1000 個 DbContext  的速度還要慢, 花費的記憶體在 GC 之後,差異不大。

所以不一定要用 DI 注入 DbContext, 在各 function 中一直傳遞 DbContext. 在 Static 的 function 中,可以安心的 new 一個 DbContext 出來使用吧,只是要記得用 using 哦,否則可能會有 connection 沒有關閉的問題。


 
More...
Bike, 2022/7/18 上午 09:46:34
|< 123456 >|
頁數 1 / 6 下一頁
~ Uwinfo ~