هل WebView2 خليفة مناسبة لوضع IE؟ ── قيد عدم عمل ActiveX وتصميم واقعيّ للانتقال

· آخر تحديث: · · WebView2, Windows, .NET, WPF, Windows Forms, وضع IE, ActiveX, الانتقال من الأنظمة القديمة, الأنظمة الداخليّة, الاستشارات التقنيّة

في المقال السابق «كيف نُطيل عمر نظام ويب داخليّ معتمِد على وضع IE، وكيف نخرج منه» كتبنا أنّ وضع IE ليس سوى إجراء إطالة عمر مؤقّت ذي أجل محدود، وأنّه ينبغي تصميم «مخرج» له بالتوازي. وعند تلقّي استشارات حول هذا «المخرج»، يظهر WebView2 بتواتر عالٍ. «نريد عرض نظام الويب الداخليّ داخل تطبيق مخصَّص»، «نريد بناء جزء من شاشات تطبيق سطح المكتب بتقنيّة الويب فقط»، «سمعنا أنّ Electron ثقيل، فهل يوجد بديل؟» ── في كلّ هذه الحالات يبرز WebView2 كخيار.

في المقابل، لدى WebView2 خصائص ينبغي معرفتها قبل اعتماده: كيف توزَّع بيئة التشغيل (runtime)، وأين يوضَع مجلد بيانات المستخدم، وكيف نجعل الجانب الأصليّ (Native) وجانب الويب يتحاوران. والأهمّ من كلّ ذلك، ActiveX الذي كان يعمل في وضع IE لا يعمل في WebView2، وهو قيد يمسّ جوهر خطّة الانتقال. في هذا المقال، نرتّب الأمر بدءاً من البنية الأساسيّة لـ WebView2 مروراً بالتوزيع والتصميم والأمان، وصولاً إلى طريقة الجمع الواقعيّة بينه وبين الخروج من وضع IE.

1. الخلاصة أوّلاً

  • WebView2 هو عنصر تحكّم يُضمِّن Microsoft Edge القائم على Chromium داخل تطبيقات Windows. يمكن استخدامه من WinForms / WPF / WinUI / Win32 C++، وهو مناسب لإضافة «واجهة ويب لجزء فقط» إلى تطبيق سطح مكتب قائم.1
  • المبدأ هو استخدام Evergreen (بيئة تشغيل مشتركة تُحدَّث تلقائيّاً). مدمجة افتراضيّاً في Windows 11، لكن التوصية الرسميّة هي عدم افتراض «أنّها مثبَّتة حتماً»، بل دمج فحص الوجود وbootstrap في المُثبِّت.2
  • للبيئات غير المتّصلة بالإنترنت أو خطوط المصانع/الإنتاج التي تريد تجميد تهيئة مُتحقَّق منها، توجد Fixed Version (مُرفَقة مع التطبيق)، لكنّ حجم المُرفَقات يتجاوز 250 ميغابايت، وتتحمَّل مسؤوليّة توزيع تحديثات الأمان بنفسها. لا تختَرها باستخفاف.3
  • أوّل مطبّ يُصادَف هو مجلد بيانات المستخدم (UDF). يُنشَأ افتراضيّاً بجوار ملفّ الـ exe، لذا يفشل التشغيل في التطبيقات المُثبَّتة تحت Program Files. اجعل تحديد موقع صريح تحت %LOCALAPPDATA% قاعدة ثابتة.4
  • التكامل بين الجزء الأصليّ والويب يقوم أساساً على تبادل الرسائل عبر PostWebMessageAsJson / WebMessageReceived، وتُقصَر AddHostObjectToScript (كشف كائنات COM) على المحتوى الموثوق فقط.1
  • لا يعمل ActiveX داخل WebView2. لا يمكن الاكتفاء بـ«نقل الصفحات المعتمِدة على وضع IE والمتضمِّنة ActiveX إلى WebView2» فحسب، بل يلزم تصميم لنقل المعالجات التي كان يتولّاها ActiveX إلى الجانب الأصليّ. هذه هي جوهر خطّة الخروج من وضع IE.5

2. البنية الأساسيّة لـ WebView2

يتكوّن WebView2 من عنصرين: «SDK (واجهة برمجة تُدمَج في التطبيق)» و«بيئة التشغيل (runtime بيئة تنفيذ قائمة على Edge تُثبَّت على جهاز العميل)». والبنية مماثلة لبيئة تشغيل Visual C++ أو بيئة تشغيل .NET: يُبنى التطبيق بالإشارة إلى حزمة NuGet باسم Microsoft.Web.WebView2، وعند التنفيذ يعمل باستخدام بيئة التشغيل الموجودة على جهاز العميل.3

المنصّات المدعومة واسعة، إذ يمكن استخدامه من WinForms وWPF القائمين على .NET Framework 4.6.2 فما بعده / .NET Core 3.1 فما بعده، ومن WinUI، ومن Win32 C++. القدرة على استخدام أسلوب تدريجيّ، كتحويل شاشة واحدة فقط من تطبيق أعمال قائم بُني بـ WinForms إلى WebView2، ميزة كبيرة مقارنةً بأساليب الانتقال إلى إطار عمل مختلف بالكامل (كـ Electron مثلاً). راجع أيضاً «جدول اختيار WinForms / WPF / WinUI» بخصوص اختيار إطار عمل واجهة المستخدم نفسه.

الحدّ الأدنى للدمج يكون بكودٍ كالتالي (الفكرة مشتركة بين WPF/WinForms).

var env = await CoreWebView2Environment.CreateAsync(
    browserExecutableFolder: null,   // استخدام بيئة تشغيل Evergreen
    userDataFolder: Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
        "KomuraSoft", "MyApp", "WebView2"));
await webView.EnsureCoreWebView2Async(env);
webView.CoreWebView2.Navigate("https://internal.example.co.jp/app/");

النقطة المهمّة هنا هي إنشاء CoreWebView2Environment بأنفسنا بدل الاعتماد على القيمة الافتراضيّة. سنشرح السبب في الفصلين التاليَين.

خطوات الاعتماد نفسها بسيطة، وبالنسبة لـ WinForms / WPF يكون التسلسل كالتالي.

  1. إضافة Microsoft.Web.WebView2 إلى المشروع عبر NuGet (يظهر عنصر تحكّم WebView2 أيضاً في صندوق أدوات المصمِّم)
  2. وضع عنصر التحكّم في النموذج (Form) أو النافذة
  3. التهيئة عبر EnsureCoreWebView2Async كما في الكود أعلاه، ثمّ استدعاء Navigate

هناك تنبيه واحد بخصوص الواجهة البرمجيّة (API) يجب الانتباه إليه أوّلاً بلا استثناء: webView.CoreWebView2 تبقى null حتّى تكتمل التهيئة. محاولة الاشتراك في حدث كـ CoreWebView2.WebMessageReceived += ... داخل باني (constructor) النموذج تنتج NullReferenceException، وهذا مطبّ شائع، لذا الشكل الأساسيّ هو تجميع معالجة ما بعد التهيئة في «بعد await الخاصّ بـ EnsureCoreWebView2Async». الإسناد إلى الخاصّيّة Source يبدأ التهيئة ضمنيّاً، لكن في التطبيقات التي تريد تحديد البيئة (كموقع UDF)، يكون توحيد البنية على استدعاء EnsureCoreWebView2Async(env) صراحةً أوّلاً أكثر أماناً من الحوادث.

كما أنّ جميع أحداث WebView2 تُطلَق على خيط واجهة المستخدم (UI thread). كتابة معالجة ثقيلة (كالوصول إلى الأجهزة أو إدخال/إخراج الملفّات) مباشرةً داخل WebMessageReceived يجمِّد حتّى إحساس التشغيل في جانب الويب، لذا اجعل معالجة الجانب الأصليّ تهرب عبر async/await. المبادئ المشروحة في «خيط واجهة المستخدم وasync/await في WPF/WinForms» تنطبق هنا كما هي.

3. توزيع بيئة التشغيل ── Evergreen وFixed Version

3.1 Evergreen (موصى به)

Evergreen هو أسلوب تستخدم فيه جميع تطبيقات WebView2 بيئة تشغيل مشتركة مثبَّتة على جهاز العميل، وتُحدَّث بيئة التشغيل تلقائيّاً. توصي بها الجهة الرسميّة بوضوح لأنّ تصحيحات الأمان تُطبَّق تلقائيّاً واستهلاك القرص صغير.6

توجد ثلاث نقاط يجب الانتباه إليها في العمل الفعليّ.

  • نفِّذ فحص الوجود. مدمجة افتراضيّاً في Windows 11، وموزَّعة على نطاق واسع في Windows 10 أيضاً، لكن مع ذلك توجد «أجهزة لم تُثبَّت فيها». في .NET يمكن التحقّق عبر CoreWebView2Environment.GetAvailableBrowserVersionString()، لكن في البيئات التي لم تُثبَّت فيها بيئة التشغيل، يفشل هذا الاستدعاء نفسه باستثناء (WebView2RuntimeNotFoundException)، لذا أحِط الاستدعاء بـ try/catch واعتبر «الاستثناء = عدم التثبيت»، وادمج في الإعداد الانتقال إلى تشغيل bootstrap (مُثبِّت صغير عبر الإنترنت) أو مُثبِّت مستقلّ (standalone).2
  • صمِّم لمتابعة تحديثات بيئة التشغيل. حتّى إن تحدَّثت بيئة التشغيل، يستمرّ التطبيق قيد التنفيذ في استخدام الإصدار القديم. الأسلوب الموصى به هو التقاط حدث NewBrowserVersionAvailable وإعداد مسار «تنعكس التحديثات عند إعادة التشغيل».2
  • حقِّق الاتّساق مع ضوابط التحديث الداخليّة. سياسة تحديث متصفّح Edge وسياسة تحديث بيئة تشغيل WebView2 أمران منفصلان. في البيئات التي توقف فيها سياسة المجموعة (Group Policy) تحديث بيئة التشغيل، ينهار افتراض Evergreen (أنّ الأحدث مثبَّت)، لذا أضِف كشف الميزات (feature detection) عند استخدام واجهات برمجيّة أحدث.6

3.2 Fixed Version (استخدام محدود)

Fixed Version هو أسلوب يُرفِق إصداراً محدَّداً من بيئة التشغيل مع التطبيق. بما أنّه يمكن تجميد تهيئة مُتحقَّق من عملها، فهو خيار معقول لأجهزة التصنيع غير المتّصلة بالإنترنت أو البيئات ذات إدارة التغيير الصارمة. غير أنّ ثمن ذلك ثقيل:

  • يتجاوز الملفّ الثنائيّ المُرفَق 250 ميغابايت، فيكبر حجم المُوزَّع بمقدار ذلك2
  • بما أنّ بيئة التشغيل لا تُحدَّث تلقائيّاً، تتحمَّل مسؤوليّة توزيع إصلاحات ثغرات محرّك المتصفّح عبر إصداراتها الخاصّة
  • إهمال التحديث يُبقي «تطبيق أعمال يحمل نسخة Chromium قديمة» داخل الشركة باستمرار

اختَره فقط عندما يكون المحتوى المعروض مغلقاً بالكامل وتديره الشركة نفسها، ويوجد نظام قادر على دمج تحديث بيئة التشغيل ضمن دورة الإصدارات.

4. أوّل مطبّ يُصادَف ── مجلد بيانات المستخدم

يحفظ WebView2 الكوكيز والتخزين المؤقّت والصلاحيّات وما شابه في مجلد بيانات المستخدم (UDF). إن لم يُحدَّد موقع UDF، يحاول إنشاءه في الموقع الافتراضيّ (بجوار موقع الـ exe نفسه في معظم التهيئات)، لذا تفشل الكتابة في التطبيقات المُثبَّتة تحت Program Files ويحدث خطأ في التهيئة. هذا عطل نموذجيّ من نوع «لا يُكتشَف إلا بعد التوزيع»: يعمل على جهاز التطوير (تشغيل تصحيح الأخطاء، مجلد قابل للكتابة) لكن يتوقّف فور التثبيت.4

الحلّ بسيط: تحديد مجلد مخصّص للتطبيق تحت %LOCALAPPDATA% صراحةً دوماً كما في مثال الكود السابق. وأدرِج أيضاً ما يلي في التصميم:

  • افصل UDF لكلّ مستخدم ولكلّ تطبيق (لا تُشارِكه بين عدّة تطبيقات)
  • لا تضعه على قرص شبكيّ (يسبِّب بطئاً وتلفاً وفقداناً للبيانات)4
  • حدِّد مسبقاً إجراءً لحذف UDF عند إلغاء التثبيت أو عبر ميزة «مسح معلومات تسجيل الدخول» (فإن لم يعرف المشغِّل أنّه الموقع الذي تبقى فيه الكوكيز وبيانات الموقع، قد يُغفَل ذلك عند تنظيف أجهزة الموظّفين المغادرين)

اعتبر هذا نسخة WebView2 من مبدأ «لا تكتب بجوار الـ exe» الذي كتبناه في المقال السابق «حفظ البيانات المحليّة في تطبيقات Windows للأعمال».

5. تصميم التكامل بين الجزء الأصليّ والويب

ما يجعل WebView2 أكثر من مجرّد «إطار متصفّح» هو التكامل المتبادل بين الكود الأصليّ ومحتوى الويب. توجد وسيلتان رئيسيّتان لذلك.1

5.1 رسائل الويب (الشكل الأساسيّ)

يرسل الجانب الأصليّ JSON عبر PostWebMessageAsJson، ويستقبله جانب الويب عبر window.chrome.webview.addEventListener("message", ...). أمّا الاتّجاه المعاكس فعبر window.chrome.webview.postMessage(...) وحدث WebMessageReceived. بما أنّه ترابط فضفاض (loosely coupled) ويمكن فحص العمليّات المكشوفة في مكان واحد، اجعل هذا وسيلة التكامل الافتراضيّة أوّلاً.

// من الجانب الأصليّ إلى الويب
webView.CoreWebView2.PostWebMessageAsJson(
    JsonSerializer.Serialize(new { type = "deviceStatus", connected = true }));

// من الويب إلى الجانب الأصليّ
webView.CoreWebView2.WebMessageReceived += (s, e) =>
{
    // لا تعالج الرسائل القادمة من غير المصدر (Origin) المتوقَّع (كأن يكون قد انتقل إلى موقع خارجيّ مثلاً)
    if (!e.Source.StartsWith("https://internal.example.co.jp/", StringComparison.Ordinal))
        return;

    AppMessage? msg;
    try { msg = JsonSerializer.Deserialize<AppMessage>(e.WebMessageAsJson); }
    catch (JsonException) { msg = null; }
    if (msg?.Type is null)
        return;  // تجاهل الشكل غير الصحيح هنا (سجِّله إن لزم الأمر)

    // نفِّذ فقط العمليّات المسموح بها لكلّ type
};

يستقبلها جانب الويب (JavaScript) هكذا. لا حاجة لأيّة مكتبة خاصّة، يكفي استخدام الكائن window.chrome.webview الذي يحقنه WebView2.

// استقبال رسالة من الجانب الأصليّ
window.chrome.webview.addEventListener("message", (e) => {
    if (e.data.type === "deviceStatus") {
        updateStatusBadge(e.data.connected);
    }
});

// إرسال طلب إلى الجانب الأصليّ
document.getElementById("print-label").addEventListener("click", () => {
    window.chrome.webview.postMessage({ type: "printLabel", copies: 2 });
});

في جانب الاستقبال، كما في الكود أعلاه، افحص أوّلاً e.Source (عنوان URI للصفحة التي أرسلت الرسالة)، ثمّ التزم بـ«فحص type الرسالة عبر قائمة سماح، وتجاهل غير المتوقَّع مع تسجيله في السجلّ (log)». بما أنّ جانب الويب قد ينتقل إلى موقع خارجيّ بمجرّد رابط واحد أو إعادة توجيه واحدة، لا تُغفِل فحص المصدر بافتراض أنّ «الصفحة المعروضة حاليّاً هي بالتأكيد صفحتنا». وفي المقابل، إضافة حالة احتياطيّة (fallback) في جانب الويب لعدم وجود window.chrome.webview (عند الفتح في متصفّح عاديّ) تتيح تصحيح أخطاء جزء واجهة الويب بمفرده في متصفّح عاديّ، ما يرفع كفاءة التطوير.

5.2 كشف كائن المضيف (Host Object) (قويّ لكن محدود الاستخدام)

استخدام AddHostObjectToScript يتيح استدعاء كائنات .NET/COM مباشرةً من JavaScript. الآليّة الداخليّة قائمة على COM، ومن اللافت أنّ تقنيّة COM التي تتعامل معها شركتنا منذ زمن طويل لا تزال فاعلة في مكان كهذا، لكنّ منح محتوى الويب قبضة مباشرة على كائن أصليّ يعني أنّ أثر اختراق تلك الصفحة يكبر بالقدر نفسه. اقصر الكشف على المحتوى الذي تديره الشركة نفسها، وقلِّص الطرق (methods) المكشوفة إلى الحدّ الأدنى الضروريّ. المبدأ هو عدم التسجيل في أيّ WebView قد يعرض صفحة غير موثوقة.

5.3 تحميل المحتوى المحليّ

عند إرفاق HTML/JS مع التطبيق وعرضها، القاعدة الثابتة هي تعيين مجلد إلى اسم مضيف افتراضيّ عبر SetVirtualHostNameToFolderMapping بدل القراءة المباشرة عبر file://. بما أنّ المحتوى يحصل على أصل (origin) مثل https://appassets.example/، تعمل واجهات برمجة الويب المعتمِدة على الأصل مثل localStorage بشكل طبيعيّ، ويمكن أيضاً تحديد مستوى السماح بالوصول عبر الأصول (cross-origin). استخدم نطاقاً محجوزاً لا يمكن أن يكون موجوداً فعليّاً (كـ .example) لاسم المضيف، وابدأ بنوع وصول عند الحدّ الأدنى الضروريّ (DenyCors أوّلاً).7

6. الخروج من وضع IE وWebView2 ── ActiveX لا يعمل

هذا هو أهمّ قسم في هذا المقال. سبب إمكانيّة إطالة عمر وضع IE هو أنّ IE11 الحقيقيّ (محرّك Trident) يعمل داخل Edge، لذا يعمل ActiveX وكائنات مساعد المتصفّح (Browser Helper Objects) كما هي.5 أمّا WebView2 فهو Chromium ولا يملك آليّة لاستضافة ActiveX. بعبارة أخرى:

«نقل نظام داخليّ يعمل في وضع IE إلى غلاف (shell) مبنيّ بـ WebView2» لا يتحقّق إلّا للشاشات غير المعتمِدة على ActiveX.

ويلزم بناء خطّة الانتقال انطلاقاً من هذا القيد. الترتيب الواقعيّ للانتقال يكون كالتالي.

  1. الجرد: تصنيف الصفحات المعتمِدة على وضع IE إلى «شاشات تستخدم تقنيّات خاصّة بـ IE مثل ActiveX» و«شاشات ذات بناء قديم فقط لا أكثر» (يمكن استخدام جرد قائمة المواقع من مقال وضع IE كما هو).
  2. الشاشات غير الخاصّة بـ IE: عدِّلها لتدعم المتصفّحات الحديثة واعرضها في Edge نفسه، أو ضعها في غلاف WebView2 إن أردت دمجها في تطبيق طرفيّ للأعمال.
  3. الشاشات المعتمِدة على ActiveX: أعِد تصميم الوظائف التي كان يتولّاها ActiveX (كالاتّصال التسلسليّ، والوصول إلى الملفّات، والتحكّم بالأجهزة المخصَّصة) بحيث تُنقَل إلى الجانب الأصليّ (تطبيق WebView2 المضيف) وتُستدعى عبر رسائل الويب. تخيَّل الأمر كقلب «ActiveX داخل المتصفّح» إلى «واجهة ويب داخل التطبيق + معالجة أصليّة».
  4. القرار بشأن الإبقاء على ActiveX نفسه أو تغليفه (wrap) أو استبداله يمكن تطبيقه مباشرةً وفق معايير «جدول قرار الإبقاء على ActiveX/OCX أو تغليفه أو استبداله».

إعادة التصميم في البند 3 هي بالضبط حجم العمل الفعليّ لاعتماد WebView2، ويلزم في مرحلة التخطيط ضبط التوقّعات بأنّ الأمر ليس بهذه البساطة: «إدخال WebView2 يعني الخروج من وضع IE». وبالمقابل، إذا اكتمل تصميم نقل وظائف ActiveX إلى التطبيق المضيف، يصبح بالإمكان الحصول على الفائدتين معاً: واجهة مستخدم يسهل بناؤها داخليّاً وصيانتها بتقنيّة الويب، وتوزيع يمكن ضبطه كتطبيق سطح مكتب.

7. مسائل التنفيذ التي تُطرَح دائماً في الأنظمة الداخليّة

عند التفكير في اعتماد WebView2، تظهر دوماً بعض الأسئلة من جانب العمل. نرتّبها هنا استباقيّاً.

7.1 الطباعة والتقارير

المتطلّب «في زمن IE كان زرّ الطباعة يُخرِج التقرير» يمكن تلبيته في WebView2 عبر مسارين.

  • طباعة الشاشة كما هي: إظهار مربّع حوار الطباعة عبر CoreWebView2.ShowPrintUI()، أو طباعة بلا تدخّل بشريّ عبر PrintAsync. بما أنّها معادِلة لطباعة المتصفّح، تعمل توجيهات طباعة CSS (@media print) كما هي.
  • الإخراج بصيغة PDF: يمكن إسقاط الصفحة المعروضة حاليّاً إلى ملفّ PDF عبر PrintToPdfAsync. لتدفّق عمل من نوع «احفظ التقرير كـ PDF إلى مجلد مشترَك»، هذا الخيار أنسب لأنّه يتيح للجانب الأصليّ ضبط اسم الملفّ ومكان الحفظ.1

بالنسبة للتقارير التي تتطلّب محاذاة بدقّة البكسل مثل الفواتير متعدّدة النسخ، ادرُس أيضاً خيار الاتّجاه نحو إخراج التقارير من الجانب الأصليّ (الطريقة المشروحة في «كيفيّة إنشاء تقارير Excel») بدل محاولة ضبطها عبر طباعة الويب.

7.2 تنزيل الملفّات ورفعها

التنزيل يعمل افتراضيّاً كما في المتصفّح، لكن القاعدة الثابتة في تطبيقات الأعمال هي التدخّل عبر حدث DownloadStarting. يمكن فرض ضوابط مثل تثبيت موقع الحفظ، والسماح أو الرفض حسب الامتداد، وإخفاء واجهة التنزيل الافتراضيّة واستبدالها بإشعار من جانب التطبيق.1 أمّا الرفع (<input type="file">) فيفتح مربّع حوار اختيار ملفّات نظام التشغيل دون أيّ تنفيذ خاصّ.

7.3 المصادقة وتسجيل الدخول الموحّد (SSO)

إن كان النظام الداخليّ على الويب يستخدم المصادقة الموحَّدة لـ Windows (NTLM/Kerberos)، فإنّها تمرّ في WebView2 أيضاً بشكل مشابه للمتصفّح تقريباً. أمّا الأنظمة القديمة التي تستخدم المصادقة الأساسيّة (Basic)، فيمكن تزويدها ببيانات الاعتماد عبر حدث BasicAuthenticationRequested، ما يتيح الاستغناء عن إظهار شاشة تسجيل الدخول ── لكنّ مكان حفظ بيانات الاعتماد تلك هو بالضبط ما كتبناه في مقال DPAPI. إن أردتَ تمرير تسجيل الدخول الموحّد (SSO) الخاصّ بـ Microsoft Entra ID (المعروف سابقاً بـ Azure AD) عبر معلومات تسجيل دخول نظام التشغيل، فادرُس تفعيل خيار البيئة AllowSingleSignOnUsingOSPrimaryAccount.

بما أنّ الكوكيز تُحفَظ في UDF، تبقى حالة تسجيل الدخول محفوظة حتّى بعد إعادة تشغيل التطبيق. إن أردتَ «حذف الجلسة بشكل مؤكّد عبر وظيفة تسجيل الخروج»، أضِف تنفيذاً يحذفها صراحةً عبر CookieManager.

7.4 تصحيح الأخطاء أثناء التطوير

بما أنّ محتوى WebView2 هو Chromium، يمكن استخدام DevTools بـ F12 كما هي أثناء التطوير (CoreWebView2Settings.AreDevToolsEnabled مفعَّلة افتراضيّاً). وكما ذُكر سابقاً، إذا بُني جانب واجهة الويب بحيث «يعمل في متصفّح مستقلّ أيضاً»، يمكن تقسيم العمل بحيث يُدار تطوير وتصحيح واجهة المستخدم كتطوير ويب عاديّ، ويُتحقَّق فقط من التكامل الأصليّ على WebView2. هذا يعني أنّه حتّى مع حصر أصول الويب داخل التطبيق، تبقى تجربة التطوير كتجربة ويب.

8. نقاط أساسيّة في تصميم الأمان

تطبيق WebView2 هو «تطبيق يحتوي متصفّحاً داخليّاً»، لذا فكِّر فيه بنموذج تهديد معادِل للمتصفّح.

  • قيِّد المحتوى المعروض: افحص الوجهة عبر NavigationStarting بقائمة سماح لنطاقات الشركة الداخليّة، ووجِّه عناوين URL غير المتوقَّعة إلى المتصفّح الافتراضيّ (عالِج NewWindowRequested بالطريقة نفسها).
  • قلِّص الوظائف العابرة لحدود الثقة: اجعل نطاق كشف كائنات المضيف والعمليّات المسموح بها عبر رسائل الويب عند الحدّ الأدنى. من المفيد أيضاً فصل WebView الذي قد يعرض مواقع خارجيّة عن WebView الذي يملك تكاملاً أصليّاً.
  • اضبط الوظائف الموجَّهة للمستخدمين حسب البيئة: يمكن عبر CoreWebView2Settings الإبقاء على «طابع المتصفّح» بالقدر الضروريّ فقط. تقليصه في أجهزة الأكشاك (kiosk) أو الأجهزة الميدانيّة يقلِّل الحوادث.
  • تحمَّل مسؤوليّة خطّة التحديث إن استُخدمت Fixed Version: كما ذُكر سابقاً، يصبح توزيع إصلاحات الثغرات مسؤوليّة التطبيق نفسه.6

نذكر هنا العناصر التي يُضبَط عليها التعديل غالباً في CoreWebView2Settings. يُنصَح بإدراج كيفيّة ضبطها في بنية الإصدار النهائيّ ضمن قائمة تحقّق ما قبل الإصدار.

الإعداد الافتراضيّ النموذجيّ في الأجهزة الميدانيّة/الإنتاج
AreDevToolsEnabled (أدوات المطوّر F12) مفعَّل يُعطَّل في الإنتاج
AreDefaultContextMenusEnabled (قائمة النقر بالزرّ الأيمن) مفعَّل يُعطَّل في الشاشات التي لا يُراد فيها استخدام «رجوع»/«إعادة التحميل»
AreBrowserAcceleratorKeysEnabled (اختصارات مثل Ctrl+F5) مفعَّل يُعطَّل في استخدامات أجهزة الأكشاك
IsStatusBarEnabled (عرض وجهة الرابط) مفعَّل حسب التفضيل
IsZoomControlEnabled (تكبير Ctrl+عجلة الفأرة) مفعَّل يُعطَّل في شاشات الأعمال التي ينكسر تخطيطها
AreHostObjectsAllowed (كائنات المضيف) مفعَّل يُعطَّل إن لم تُستخدَم

كلّ هذه الإعدادات أدوات لـ«إغلاق المداخل غير المقصودة كتطبيق» أكثر منها «التعطيل يعني الأمان». راجع أيضاً «القائمة الدنيا لأمان تطبيقات Windows» لرفع مستوى الأمان في تطبيقات Windows عموماً.

9. ترتيب قرار الاعتماد

البنية الموقف المناسب نقاط الانتباه
العرض في Edge (المتصفّح) نظام ويب داخليّ عاديّ لا يمكن دمجه بتطبيق أو تكامله أصليّاً
تطبيق قائم + WebView2 لجزء من واجهة الويب تحديث شاشة بشاشة، وإعادة استخدام أصول الويب UDF وتوزيع بيئة التشغيل وتصميم التكامل (موضوع هذا المقال)
غلاف WebView2 + نقل الوظائف الأصليّة مخرج لأصول وضع IE المعتمِدة على ActiveX إعادة تنفيذ وظائف ActiveX هي جوهر العمل
Electron وما شابه عند ضرورة تعدّد المنصّات ثقيل إن كان الاستخدام مقتصراً على Windows. زيادة في حجم التوزيع والذاكرة
إعادة البناء بالكامل بأسلوب أصليّ (كـ WPF) لا توجد أصول ويب / افتراض عدم الاتّصال يتطلّب موازنة مع تكلفة التطوير

إذا كان الهدف «تطبيقاً داخليّاً مخصَّصاً لـ Windows فقط، مع الرغبة في استخدام واجهة مستخدم بتقنيّة الويب»، فإنّ WebView2 هو الخيار الافتراضيّ مقارنةً بـ Electron. بما أنّه يمكن مشاركة بيئة التشغيل مع نظام التشغيل، فالتوزيع أخفّ، والتكامل مع أصول .NET القائمة مباشر.

10. الخلاصة

WebView2 تقنيّة يمكنها تضمين واجهة مستخدم ويب قائمة على Chromium كمكوِّن داخل تطبيقات Windows، وتنسجم جيّداً مع تحديث الأنظمة الداخليّة. النقاط العمليّة عند الاعتماد ثلاث: فحص وجود بيئة تشغيل Evergreen ومتابعة تحديثاتها، وتحديد مجلد بيانات المستخدم صراحةً، وتصميم التكامل القائم أساساً على رسائل الويب. أمّا على صعيد التخطيط، فالأمر هو مواجهة قيد عدم عمل ActiveX بصراحة، وجعل إعادة تصميم نقل وظائف ActiveX إلى الجانب الأصليّ محور حجم العمل.

إن كنتَ تفكّر في «حان وقت البحث عن مخرج» وأنت تراقب أجل وضع IE، فإنّ البداية الثابتة هي جرد النظام المستهدَف وتفكيك الوظائف المعتمِدة على ActiveX. توجد أجزاء كثيرة من طريقة التقدّم هذه يصعب الحكم عليها دون النظر إلى تهيئة النظام الفعليّة، فلا تتردَّد في التواصل معنا عند التردّد.

مقالات ذات صلة

مجالات الاستشارة ذات الصلة

تتعامل شركة Komura Soft LLC مع تصميم مخرج للأنظمة الداخليّة المعتمِدة على وضع IE وActiveX، والتحديث التدريجيّ باستخدام WebView2، والاستشارات حول دمج واجهة مستخدم ويب في تطبيقات Windows القائمة.

المراجع

  1. Microsoft Learn، Overview of WebView2 APIs. حول الصورة الشاملة لوظائف WebView2 كإدارة التنقّل، وتحميل المحتوى المحليّ، والاتّصال بين المضيف والويب (رسائل الويب، كائنات المضيف).  2 3 4 5

  2. Microsoft Learn، Distribute your app and the WebView2 Runtime. حول التوزيع عبر bootstrapper/مُثبِّت مستقلّ، وكشف التثبيت المسبَق، ومتابعة التحديثات عبر NewBrowserVersionAvailable، وإجراء إرفاق Fixed Version (يتجاوز 250 ميغابايت).  2 3 4

  3. Microsoft Learn، Evergreen vs. fixed version of the WebView2 Runtime. حول الفرق بين وضعَي توزيع بيئة التشغيل، والتضمين الافتراضيّ في Windows 11، ومزايا وعيوب Fixed Version.  2

  4. Microsoft Learn، Manage user data folders. حول دور مجلد بيانات المستخدم، وصلاحيّات القراءة/الكتابة اللازمة لـ UDF مخصَّص، وأنّ وضعه على قرص شبكيّ يسبِّب بطئاً وتعطّلاً وفقداناً للبيانات.  2 3

  5. Microsoft Learn، What is Internet Explorer (IE) mode?. حول عمل وضع IE بمحرّك Trident (MSHTML) ودعمه لعناصر تحكّم ActiveX وكائنات مساعد المتصفّح (أي أنّ WebView2 القائم على Chromium لا يملك هذا الدعم).  2

  6. Microsoft Learn، Development best practices for WebView2 apps. حول التوصية باستخدام Evergreen، والتعامل مع تحديثات بيئة التشغيل، وكشف الميزات، وضرورة التحديث الدوريّ عند استخدام Fixed Version.  2 3

  7. Microsoft Learn، Using local content in WebView2 apps. حول تحميل المحتوى المحليّ عبر تعيين اسم مضيف افتراضيّ، وفائدة منح أصل (origin)، وتحديد نوع الوصول (كـ DenyCors). 

أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.

ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.

الأسئلة الشائعة

أسئلة شائعة حول موضوع هذه المقالة.

هل يعمل ActiveX داخل WebView2؟
لا يعمل. يعمل وضع IE داخل Edge بمحرّك IE11 الحقيقيّ (محرّك Trident)، لذا يعمل ActiveX كما هو، أمّا WebView2 فقائم على Chromium ولا يملك آليّة لاستضافة ActiveX. لذلك لا يمكن الاكتفاء بـ«نقل الشاشات المعتمِدة على ActiveX إلى WebView2» فحسب، بل يلزم نقل الوظائف التي كان يتولّاها ActiveX (كالاتّصال التسلسليّ (serial)، والوصول إلى الملفّات، والتحكّم بالأجهزة المخصَّصة) إلى الجانب الأصليّ (Native، أي التطبيق المضيف)، وإعادة تصميمها بحيث تُستدعى عبر رسائل الويب (Web messages). وإعادة التصميم هذه بالذات هي حجم العمل الفعليّ لاعتماد WebView2.
أيّهما ينبغي اختياره لبيئة تشغيل WebView2، Evergreen أم Fixed Version؟
المبدأ الأساسيّ هو Evergreen (بيئة تشغيل مشتركة تُحدَّث تلقائيّاً)، وتوصي بها الجهة الرسميّة بوضوح لأنّ تصحيحات الأمان تُطبَّق تلقائيّاً واستهلاك القرص صغير. مدمجة افتراضيّاً في Windows 11، لكن توجد أجهزة لم تُثبَّت فيها بعد، لذا يُدمَج فحص الوجود وbootstrap (برنامج تثبيت تمهيديّ) في المُثبِّت. أمّا Fixed Version (المُرفَقة مع التطبيق) فيتجاوز حجمها المُرفَق 250 ميغابايت، وتتحمَّل الجهة مسؤوليّة توزيع إصلاحات ثغرات محرّك المتصفّح عبر إصداراتها الخاصّة، لذا ينبغي اختيارها فقط في حالات محدودة كأجهزة التصنيع غير المتّصلة بالإنترنت أو البيئات ذات إدارة التغيير الصارمة.
لماذا لا يُشغَّل تطبيق WebView2 بعد التثبيت؟
المطبّ النموذجيّ الأوّل هو مشكلة مجلد بيانات المستخدم (User Data Folder، اختصاراً UDF). يحفظ WebView2 الكوكيز والتخزين المؤقّت (cache) والصلاحيّات في UDF، لكن إن لم يُحدَّد موقعه، يحاول افتراضيّاً إنشاءه بجوار ملفّ الـ exe، فتفشل الكتابة في التطبيقات المُثبَّتة تحت Program Files ويحدث خطأ في التهيئة. هذا عطل نموذجيّ يعمل على جهاز التطوير لكن يتوقّف فور التثبيت. الحلّ هو تحديد مجلد مخصّص للتطبيق تحت %LOCALAPPDATA% صراحةً دوماً عند إنشاء CoreWebView2Environment. كما يجب تجنّب وضعه على قرص شبكيّ لأنّ ذلك يسبِّب بطئاً وتلفاً في البيانات.
كيف يتكامل الكود الأصليّ (Native) مع صفحة الويب في WebView2؟
الأساس هو التكامل الفضفاض (loosely coupled) عبر رسائل الويب. يرسل الجانب الأصليّ JSON عبر PostWebMessageAsJson، ويستقبله جانب الويب عبر حدث message الخاصّ بـ window.chrome.webview. أمّا الاتّجاه المعاكس فعبر postMessage وحدث WebMessageReceived. من المهمّ في جانب الاستقبال فحص عنوان URI المصدر عبر e.Source، وفحص نوع (type) الرسالة عبر قائمة سماح (whitelist). توجد أيضاً طريقة لكشف كائنات .NET/COM مباشرةً عبر AddHostObjectToScript، لكن نظراً لضخامة الأثر عند اختراق الصفحة، ينبغي قصرها على المحتوى الذي تديره الشركة نفسها، وتقليص الطرق (methods) المكشوفة إلى الحدّ الأدنى الضروريّ.

الملف الشخصي للمؤلف

صفحة الملف الشخصي لمؤلف المقالة.

غو كومورا

مؤسّس شركة كومورا سوفت ذ.م.م.

يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.

روابط عامة

العودة إلى المدونة