توزيع تطبيق Windows في ملفّ واحد - حدود الملفّ التنفيذي الواحد واعتماد نظام التشغيل

· آخر تحديث: · · Windows, توزيع, ملفّ تنفيذي واحد, .NET, C++, WebView2, WinUI

سجل التعديلات (3 تحديثات، آخر تحديث 3 Sep، 2026)

سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.

أُضيفت روابط الاستشارة الموجودة في الأصل الياباني (consultation_services). ولم يتغيّر نصّ المقالة نفسه. قراءة النسخة السابقة لهذا التحديث (DOI: 10.5281/zenodo.22240870)
أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621429)

هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.

小村 豪 (2026). توزيع تطبيق Windows في ملفّ واحد - حدود الملفّ التنفيذي الواحد واعتماد نظام التشغيل. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621429 https://comcomponent.com/ar/blog/2026/03/19/003-windows-single-binary-and-os-dependencies/

DOI (أحدث نسخة)
10.5281/zenodo.21621429
DOI (هذه النسخة)
10.5281/zenodo.22279862

بدأت هذه المقالة من حديث عابر: «إلى أيّ حدّ يجوز في Windows أن نسمّي الأمر ملفاً تنفيذيّاً واحداً (single binary)». المنشور الذي أشعل الحديث هو التالي. يمكن تخطّي هذا الجزء؛ ما بعده مكتوب ليُقرأ وحده.

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

لكن إن لم تُفصَل هذه القصّة أوّلاً، ينفرط التفاهم في المنتصف عادة. لأنّ «نريد ملفاً تنفيذيّاً واحداً» في Windows يختلط فيه غالباً أربعة أحاديث منفصلة.

  • تريد المُنتَج المسلَّم ملفّاً واحداً
  • تريد إلغاء التثبيت المسبق لوقت تشغيل .NET أو Visual C++
  • تريد أن يعمل بمجرّد الوضع، بلا مثبِّت وبلا امتيازات مدير
  • لا تريد الاعتماد على اختلاف Windows المستهدف

هذه الأربعة ليست الشيء نفسه. عمليّاً، التفكير كالتالي هو الأقلّ انحرافاً.

تقريب المُنتَج المسلَّم إلى EXE واحد ممكن إلى حدّ بعيد. لكن تصفير الاعتماد على Windows المستهدف غير ممكن.

تنظّم هذه المقالة ذلك الخطّ الفاصل لصعيد عملي لتطبيقات Windows.

حتى إن صار EXE واحداً لا يزول اعتماد نظام التشغيلمخطّط يبيّن أنّ طلب الملفّ التنفيذي الواحد يختلط فيه حديث التوزيع وحديث الاعتماد، وأنّ تقريب المُنتَج المسلَّم إلى EXE واحد ممكن إلى حدّ بعيد بينما تصفير الاعتماد على Windows المستهدف غير ممكن.«نريد ملفاً تنفيذيّاً واحداً»حديث التوزيع: ملفّ واحد · الوضع فقطحديث الاعتماد: بلا وقت تشغيل · بلا اعتماد على نظام التشغيلالتقريب إلى EXE واحد ممكن إلى حدّ بعيدتصفير اعتماد نظام التشغيل غير ممكن

الشكل 1: «نريد توزيعه في ملفّ واحد» يختلط فيه الممكن والمستحيل.

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

أوّلاً الخلاصة فقط، كالتالي.

  • إن كان EXE سطح مكتب عادياً، يمكن جعله ملفاً تنفيذيّاً واحداً إلى حدّ بعيد
  • لكن إمكان EXE واحد وعدم الاعتماد على Windows المستهدف أمران مختلفان
  • امتدادات Shell، وخدمات Windows، والتعريفات، وWebView2، وجزء من WinUI 3، غالباً ما يكون موضوعها ماذا تسجّل في نظام التشغيل وماذا تفترض أكثر من عدد الملفّات
  • الأهمّ عمليّاً فصل القرار: أتريد ملفاً تنفيذيّاً واحداً، أم إلغاء المثبِّت، أم تقليل الاعتماد على نظام التشغيل

بعبارة أخرى، الخطّ الفاصل في Windows كالتالي.

  • تقريب المُنتَج المسلَّم إلى ملفّ واحد: ممكن إلى حدّ بعيد
  • حمل وقت تشغيل إضافي: ممكن إلى حدّ بعيد
  • التقريب إلى توزيع xcopy: حسب نوع التطبيق
  • محو الاعتماد من جهة Windows المستهدف: مستحيل
الخطّ الفاصل في Windowsمخطّط يبيّن أنّ تقريب المُنتَج المسلَّم إلى ملفّ واحد وحمل وقت تشغيل إضافي ممكنان إلى حدّ بعيد، وأنّ التقريب إلى توزيع xcopy حسب نوع التطبيق، وأنّ محو الاعتماد من جهة Windows المستهدف مستحيل.تقريب المُنتَج المسلَّم إلى ملفّ واحدممكن إلى حدّ بعيدتضمين وقت تشغيل إضافيالتقريب إلى توزيع xcopyحسب نوع التطبيقمحو اعتماد جهة نظام التشغيلمستحيل

الشكل 2: خطّ فاصل بين ما يمكن، وما يعتمد على النوع، وما لا يمكن.

1.1 مصطلحات تستخدمها المقالة

أوّلاً نرتّب كلمات تتكرّر لاحقاً.

المصطلح القراءة / التوسيع المعنى في هذه المقالة
UCRT Universal C Runtime جزء مكتبة C القياسية الذي نشأ عند تقسيم وقت تشغيل C في Visual Studio 2015. من Windows 10 فصاعداً مضمَّن مكوّناً من نظام التشغيل
حزمة VC++ القابلة لإعادة التوزيع Visual C++ Redistributable مثبِّت يُدخل مكتبات DLL لوقت تشغيل Visual C++ عدا UCRT على الجهاز المستهدف
framework-dependent توزيع يعتمد على .NET في البيئة المستهدفة شكل توزيع يفترض وجود وقت تشغيل .NET على الجهاز المستهدف
self-contained تضمين وقت تشغيل .NET شكل يحمل التطبيق حزمة وقت تشغيل .NET كاملة ويوزّعها
single-file إصدار ملفّ واحد خيار إصدار في .NET يجمع المُنتَج المسلَّم في EXE واحد
Native AOT Native Ahead-Of-Time شكل توزيع يُترجَم فيه IL مسبقاً إلى شيفرة أصلية عند الإصدار. لا يستخدم JIT في وقت التشغيل
توزيع app-local توزيع مجاور للتطبيق أسلوب توزيع يضع DLL في المجلد نفسه مع EXE ليستخدمها ذلك التطبيق فقط
توزيع xcopy توزيع بالنسخ فقط أسلوب توزيع يعمل بوضع المجلد كما هو، بلا مثبِّت وبلا امتيازات مدير
SCM Service Control Manager، مدير التحكّم بالخدمات آلية نظام التشغيل التي تدير تسجيل خدمات Windows وتشغيلها وإيقافها
UAC User Account Control، التحكّم بحساب المستخدم آلية أمن Windows التي تتحكّم بالترقية إلى امتيازات المدير
امتداد Shell امتداد الصدفة مكوّن COM يُحمَّل في عملية مثل مستكشف الملفات ويعمل فيها
Evergreen أسلوب التحديث المستمر وضع توزيع يوكل WebView2 Runtime إلى نسخة مشتركة واحدة تُحدَّث تلقائيّاً
Fixed Version أسلوب تثبيت الإصدار وضع توزيع يضمّن إصدار محدَّداً من WebView2 Runtime في تطبيقك
arch architecture، معمارية المعالج x86 / x64 / Arm64

في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 22، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle

2. «الملفّ التنفيذي الواحد» يُفكَّر فيه على أربع درجات

إن رُسمت الدرجات أوّلاً، تكون كالتالي. تصعب من الأسفل إلى الأعلى، والأعلى لا يُبلَغ في Windows.

المستوى A: المُنتَج المسلَّم ملفّ واحدممكن إلى حدّ بعيدالمستوى B: بلا تثبيت مسبق لوقت تشغيل اللغةممكن إلى حدّ بعيدالمستوى C: بلا تثبيت ولا تسجيلحسب نوع التطبيقالمستوى D: بلا اعتماد على Windows المستهدفلا يُبلَغ في Windows

الشكل 3: أربع درجات للملفّ التنفيذي الواحد. تصعب من الأسفل، والمستوى D لا يُبلَغ.

حديث «نريد ملفاً تنفيذيّاً واحداً» يتغيّر العمل اللازم فيه تماماً حسب أيّ درجة من هذه الأربع يُقصَد.

2.1 المستوى A: المُنتَج المسلَّم ملفّ واحد

الأكثر سطحية هذا.

  • يُرسَل واحداً بالبريد
  • يكفي وضع واحد على USB
  • يُوضَع app.exe فقط في وجهة النشر

هذا حديث وحدة التسليم الظاهرة. حتى إن وُسِّع مؤقّتاً عند الإقلاع، أو اعتمد على DLL من جهة نظام التشغيل، يكفي هذا الشرط وحده.

2.2 المستوى B: بلا تثبيت مسبق لوقت تشغيل اللغة

التالي حالة تعمل دون تثبيت وقت تشغيل .NET أو حزمة VC++ القابلة لإعادة التوزيع مسبقاً على الجهاز المستهدف.

  • الربط الساكن في C/C++
  • self-contained في .NET
  • single-file في .NET
  • Native AOT في .NET

عند هذا المستوى يقوى إحساس «يُحمَل وحده» كثيراً.

2.3 المستوى C: بلا تثبيت ولا تسجيل

من هنا يصعب فجأة.

EXE العادي قد يعمل بمجرّد الوضع. لكن هذه ليست كذلك.

  • امتداد Shell
  • خدمة Windows
  • مخطّط URL مخصَّص أو ربط نوع ملفّ
  • تعريف (driver)
  • مكوّن يُحمَّل في عملية أخرى مثل Explorer أو Office

هذا المجال لا يكفي وضع الملفّات. يلزم تسجيل في جهة نظام التشغيل، أو ربط مع جهة المضيف.

مجال لا يكفي فيه الوضع فقطمخطّط يبيّن أنّ امتدادات Shell وخدمات Windows وربط الملفّات والتعريفات والمكوّنات المحمَّلة في عملية أخرى لا تكفي بوضع الملفّ، بل تحتاج تسجيلاً في جهة نظام التشغيل أو ربطاً مع جهة المضيف.امتداد Shell · خدمةالوضع وحده لا يكفيربط · تعريفما يُحمَّل في عملية أخرىيلزم تسجيل جهة نظام التشغيل وربط المضيف

الشكل 4: المستوى C يصعب فجأة لأنّه مجال يحتاج تسجيلاً في نظام التشغيل.

2.4 المستوى D: بلا اعتماد على Windows المستهدف

هذا مستحيل في Windows.

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

3. مجال يسهل فيه التقريب إلى EXE واحد إلى حدّ بعيد

حتى في Windows توجد تطبيقات يسهل نسبيّاً تقريبها إلى EXE واحد.

  • أدوات سطح مكتب تُشغَّل وحدها
  • تطبيقات عمل يحمل فيها EXE نفسه الواجهة والمعالجة
  • أدوات مثل الاتصال ومعالجة الملفّات وجمع السجلّات والمراقبة والتحكّم بالأجهزة
  • ما لا يحتاج تكامل مضيف مع Explorer أو Office
  • واجهة لا تفترض وقت تشغيل ويب

لهذا النوع كثير ممّا يسهل تضمينه في جسم التطبيق.

  • شيفرتك
  • الموارد
  • البيان (manifest)
  • الإعدادات الافتراضية
  • بيانات القوالب
  • بعض مكتبات الطرف الثالث
  • جسم وقت تشغيل اللغة

وإضافة، حتى دون دفن DLL بالكامل داخل EXE، توزيع app-local بوضع DLL بجانب EXE خيار قوي شائع في Windows. عمليّاً،

  • app.exe واحد
  • أو app.exe + بضعة DLL مجاورة
  • لكن بلا مثبِّت، بلا امتيازات مدير، يُوزَّع بـ xcopy

هذا الشكل ليس نادراً أن تكون صيانته أسهل من الضغط قسراً إلى EXE واحد.

app-local بوصفه موضع استقرارمخطّط يبيّن أنّ وضع DLL بجانب EXE دون دفنها بالكامل في EXE، إن أمكن توزيع xcopy بلا مثبِّت وبلا امتيازات مدير، ليس نادراً أن تكون صيانته أسهل من الضغط قسراً إلى EXE واحد.app.exe+بضعة DLL مجاورةبلا مثبِّت · بلا امتيازات مديريُوزَّع بـ xcopyقد تكون الصيانة أسهل من ضغط EXE واحد قسري

الشكل 5: حتى دون الإصرار على EXE واحد، كثيراً ما يفي التوزيع app-local بالغرض.

4. اعتماد Windows الذي لا يزول حتى مع EXE واحد

إن ظننت «EXE واحد يعني عدم الاعتماد على Windows المستهدف»، تقع الحادثة هنا. في الواقع يبقى اعتماد حتى مع EXE واحد.

4.1 الاعتماد على إصدار نظام التشغيل

لكلّ واجهة Windows حدّ أدنى من نظام التشغيل المدعوم. ويوجد أيضاً فرق x64 / Arm64. أي حتى مع EXE واحد،

  • هل يعمل حتى Windows 10
  • أم يفترض Windows 11
  • أم يُشغَّل أيضاً على Windows Server
  • أيّ من x86 / x64 / Arm64 مستهدف

يلزم تثبيتها أوّلاً.

4.2 الاعتماد على مكتبات DLL للنظام

حتى إن نويت EXE واحداً، تستخدم عند التشغيل بطبيعة الحال مكوّنات يوفّرها نظام التشغيل.

  • kernel32.dll
  • user32.dll
  • advapi32.dll
  • أساس COM
  • أساس التحكّم بالخدمات

هذا نطاق مسؤولية جهة Windows.

4.3 الاعتماد على نموذج الأمن

  • UAC
  • ACL للملفّات
  • مدير التحكّم بالخدمات
  • السجلّ
  • سياسة توقيع التعريفات

هذه لا يستطيع التطبيق حملها وحده.

اعتماد يبقى حتى مع EXE واحدمخطّط يبيّن أنّه حتى مع EXE واحد يبقى الاعتماد على أدنى نظام تشغيل مدعوم لواجهات Windows والمعمارية، ومكتبات DLL للنظام مثل kernel32.dll وأساس COM، ونموذج الأمن مثل UAC وACL وسياسة توقيع التعريفات.تطبيق EXE واحدإصدار نظام التشغيل وarchمكتبات DLL للنظام · أساس COMنموذج الأمنلا يستطيع التطبيق حمل أيّ منها

الشكل 6: حتى مع مُنتَج مسلَّم واحد يبقى الاعتماد على نطاق مسؤولية جهة Windows.

4.4 الاعتماد على المضيف أو وقت التشغيل

إن لم يكن EXE يُشغَّل وحده بل تصميماً يركب على مضيف ما، يزيد الاعتماد دفعة واحدة.

  • استخدام WebView2: يلزم WebView2 Runtime
  • استخدام WinUI 3 / Windows App SDK: يلزم ترتيب وضع التوزيع
  • صنع امتداد Shell: يلزم تسجيل في جهة Explorer

أي أنّ اختيار الواجهة أو التكامل كثيراً ما يصير صعوبة التوزيع كما هو.

اختيار الواجهة والتكامل يصير صعوبة التوزيعمخطّط يبيّن أنّ استخدام WebView2 يلزم Runtime، واستخدام WinUI 3 يلزم ترتيب وضع التوزيع، وصنع امتداد Shell يلزم تسجيلاً في جهة Explorer، فاختيار المضيف أو وقت التشغيل يصير صعوبة التوزيع كما هو.استخدام WebView2يلزم Runtimeاستخدام WinUI 3يلزم ترتيب وضع التوزيعصنع امتداد Shellيلزم تسجيل في Explorer

الشكل 7: كلّما ابتعدت عن EXE يُشغَّل وحده، زاد الاعتماد دفعة واحدة.

5. مواضع استقرار واقعيّة حسب التقنية

5.1 C/C++ الأصلي

C/C++ الأصلي في الجهة ذات حرّية أعلى لجعل الملفّ التنفيذي واحداً. يوجد مجال لاختيار الربط الساكن، وEXE الذي يُشغَّل وحده يسهل تقريبه كثيراً.

لكن أهمّ عمليّاً من دفن الكلّ في ملفّ واحد:

  • كيف تعامل UCRT ووقت تشغيل VC++
  • هل تضع مكتبات DLL للطرف الثالث app-local
  • إلى أيّ حدّ تضيّق المعالج / نظام التشغيل المستهدف

المدخل: الفرق بين /MT و/MD

ما يقرّر عمليّاً في MSVC «هل تحمل وقت التشغيل» هو خيار المترجم هذا.

الخيار ما يُربَط ما يلزم على الجهاز المستهدف
/MD مكتبات استيراد لـ DLL هي ucrt.lib وvcruntime.lib. عند التشغيل تُستخدَم ucrtbase.dll وvcruntime<إصدار>.dll UCRT ووقت تشغيل VC++
/MT ربط ساكن لـ libucrt.lib وlibvcruntime.lib وlibcmt.lib بلا وقت تشغيل إضافي

أصغر تجربة، في Developer Command Prompt، هذا فقط.

cl /std:c++17 /EHsc /O2 /MT app.cpp /Fe:app.exe

هنا ثلاث نقاط تستحقّ الانتباه.

  • صار UCRT مكوّناً من Windows عند تقسيم وقت تشغيل C في Visual Studio 2015، وهو مضمَّن جزءاً من نظام التشغيل من Windows 10 فصاعداً. إن استهدفت Windows أقدم، يلزم إعادة التوزيع بـ vcredist.
  • صنع جهة DLL بـ /MT غير مستحسَن. CRT المربوط ساكناً تنغلق حالته داخل ذلك DLL، فيختلف سلوك حجز الذاكرة والإعدادات المحلّية و_set_se_translator بين EXE وDLL. مواءمة «EXE بـ /MT وDLL المضمَّن أيضاً /MT» بلا رويّة تقع حادثتها عند الحجز والتحرير عبر الحدود.
  • /clr و/MT لا يُجمَعان. إن اختلط C++/CLI فجهة /MD.
ثلاث تنبيهات للربط الساكنمخطّط يبيّن أنّ UCRT مضمَّن في نظام التشغيل من Windows 10 فصاعداً بينما الأقدم يحتاج إعادة توزيع بـ vcredist، وأنّ صنع جهة DLL بـ /MT يغلق حالة CRT داخل DLL فتقع حادثة عند الحجز والتحرير عبر الحدود، وأنّ /clr و/MT لا يُجمَعان.ربط ساكن بـ /MTWindows الأقدم يحتاج vcredist/MT لجهة DLL غير مستحسَنلا يُجمَع مع /clrحادثة عند الحجز والتحرير عبر الحدود

الشكل 8: /MT قوي، لكن انتبه إلى افتراض UCRT وحدود DLL وC++/CLI.

5.2 .NET

لدى .NET single-file وself-contained وNative AOT، لذا يمكن تصغير وحدة التسليم الظاهرة كثيراً.

لكن التمييز لازم.

  • framework-dependent: يعتمد على .NET في البيئة المستهدفة
  • self-contained: يحمل وقت تشغيل .NET
  • single-file: يقرّب المُنتَج المسلَّم إلى واحد
  • Native AOT: يقلّل اعتماد الإقلاع أكثر، مع قيود وظيفية

ليس أنّ «single-file يقلّل الاعتماد على نظام التشغيل». ما يقلّ أساساً هو تماسك مُنتَج التطبيق المسلَّم.

ما يقلّله single-file تماسك المُنتَج المسلَّممخطّط يبيّن أنّ framework-dependent يعتمد على .NET في البيئة المستهدفة، وself-contained يحمل وقت التشغيل، وsingle-file يقرّب المُنتَج المسلَّم إلى واحد فقط، وأنّ single-file لا يقلّل الاعتماد على نظام التشغيل.framework-dependentيعتمد على .NET في البيئة المستهدفةself-containedيحمل وقت تشغيل .NETsingle-fileيقرّب المُنتَج المسلَّم إلى واحدلا يعني تقليل اعتماد نظام التشغيل

الشكل 9: لكلّ شكل إصدار في .NET ما يقلّ وما يبقى مختلفان.

المدخل: ثلاثة أنماط لـ dotnet publish

لرؤية الفرق بالتشغيل أوّلاً، هذه الثلاثة تكفي.

rem 1. framework-dependent + single-file: 対象機に .NET ランタイムが要る
dotnet publish -c Release -r win-x64 --self-contained false -p:PublishSingleFile=true

rem 2. self-contained + single-file: .NET ランタイムを抱える
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true

rem 3. Native AOT: csproj に PublishAot を書いたうえで発行する
dotnet publish -c Release -r win-x64

PublishSingleFile وPublishAot التوصية الرسمية كتابتهما في csproj لا سطر الأوامر. لأنّ تحليل التوافق أثناء البناء يُفعَّل، فتقلّ حوادث تُكتشَف بعد الإصدار.

<PropertyGroup>
  <PublishSingleFile>true</PublishSingleFile>
  <PublishAot>true</PublishAot>
</PropertyGroup>

لاحظ أنّ تحديد RuntimeIdentifier يجعل SelfContained افتراضيّاً true. إن أردت framework-dependent فصرّح بـ --self-contained false. لإصدار Native AOT على Windows يلزم حمل عمل تطوير سطح المكتب بـ C++ في Visual Studio.

المقايضة: «جعله واحداً» ليس مجّاناً

هنا الكتابة عن «الممكن» وحدها تُوقِع حادثة، لذا نرتّب الثمن أيضاً.

التوسيع عند إقلاع single-file

  • الافتراضي أنّ ما يُضمَّن هو مكتبات DLL المُدارة فقط. تُحمَّل في الذاكرة عند الإقلاع ولا تُوسَّع إلى مجلد. الثنائيات الأصلية لجسم وقت التشغيل تبقى ملفّات منفصلة.
  • لتضمين الثنائيات الأصلية أيضاً في واحد استخدم IncludeNativeLibrariesForSelfExtract، ولتوسيع الكلّ قبل التشغيل استخدم IncludeAllContentForSelfExtract. كلاهما سلوك «وسّع ثمّ أقلع»، وعلى Windows يُوسَّع تحت %TEMP%\.net. يمكن تغيير الموضع بـ DOTNET_BUNDLE_EXTRACT_BASE_DIR، لكن لا تجعله موضعاً يكتب فيه مستخدمون أو خدمات بصلاحيات مختلفة.
  • تفعيل EnableCompressionInSingleFile يصغّر EXE كثيراً، لكن الإقلاع يبطؤ بقدر التمديد في الذاكرة عند الإقلاع. الوثائق الرسمية أيضاً بصيغة «قِس الحجم وتكلفة الإقلاع كليهما قبل الاستخدام». الأثر يتغيّر كثيراً حسب التطبيق.

عدم توافق واجهات single-file

جعل المُنتَج المسلَّم واحداً يكسر بهدوء شيفرة تفترض مسار ملفّ.

الواجهة السلوك مع single-file
Assembly.Location تعيد سلسلة فارغة
Assembly.CodeBase PlatformNotSupportedException
Assembly.GetFile IOException
Module.Name تعيد السلسلة <Unknown>

لمس ملفّ بجانب EXE انحز إلى AppContext.BaseDirectory، وإن لزم مسار الملفّ التنفيذي فانحز إلى Environment.ProcessPath. مكتبات الطرف الثالث قد تستخدم هذه داخليّاً أيضاً، لذا بعد جعله single-file يلزم تأكيد الإقلاع مرّة على جهاز حقيقي.

شيفرة تفترض المسار تنكسر بهدوءمخطّط يبيّن أنّ جعل المُنتَج المسلَّم واحداً يغيّر سلوك الواجهات التي تفترض مسار ملفّ مثل إعادة Assembly.Location سلسلة فارغة، لذا انحز لملفّ مجاور إلى AppContext.BaseDirectory ولمسار الملفّ التنفيذي إلى Environment.ProcessPath، وأكّد الإقلاع مرّة على جهاز حقيقي.جعله single-fileيتغيّر سلوك الواجهات التي تفترض المسارالملفّ المجاور: AppContext.BaseDirectoryالملفّ التنفيذي: Environment.ProcessPathأكّد الإقلاع مرّة على جهاز حقيقي

الشكل 10: بعد جعله single-file، استبدل أخذ المسار وتحقّق على جهاز حقيقي.

القيود الوظيفية لـ Native AOT

مقابل «إقلاع أسرع وبلا وقت تشغيل»، يتعذّر التالي.

  • التحميل الديناميكي مثل Assembly.LoadFile
  • توليد الشيفرة في وقت التشغيل مثل System.Reflection.Emit
  • C++/CLI
  • على Windows COM المضمَّن
  • التقليم إلزامي، فقيود التقليم تركب كما هي
  • عمليّاً single-file، فعدم توافق الواجهات أعلاه يركب كما هو
  • System.Linq.Expressions يعمل دائماً مفسِّراً، فيبطؤ عن الشيفرة المولَّدة في وقت التشغيل

المنصّة المستهدفة أيضاً مثبتة سلفاً. في .NET 8 Windows هو x64 وArm64، ومن .NET 9 فصاعداً أُضيف x86. تصوّر «واحد بـ AnyCPU» لا يقوم من البداية.

ثمن Native AOTمخطّط يبيّن أنّ Native AOT يقلّل اعتماد الإقلاع مقابل تعطّل التحميل الديناميكي وتوليد الشيفرة في وقت التشغيل وC++/CLI وCOM المضمَّن على Windows، وتركب أيضاً قيود التقليم وsingle-file، والمنصّة المستهدفة مثبتة سلفاً.Native AOTيقلّل اعتماد الإقلاعالتحميل الديناميكي والتوليد في وقت التشغيل متعذّرانC++/CLI وCOM المضمَّن متعذّرانتركب أيضاً قيود التقليم وsingle-fileنظام التشغيل وarch المستهدفان مثبتان سلفاً

الشكل 11: مزيّة Native AOT تُرى مجموعة مع الوظائف التي تتعطّل.

5.3 WebView2

اعتماد WebView2 يغيّر صعوبة الملفّ التنفيذي الواحد جذريّاً. الموضوع هنا ليس عدد EXE، بل كيف تعامل WebView2 Runtime.

قبل «هل يمكن EXE واحد»، أسئلة يجب التفكير فيها.

  • هل تفترض Runtime في البيئة القائمة
  • هل تستخدم Evergreen
  • هل تضمّن Fixed Version
  • إلى أيّ حدّ تتحمّل المسؤولية في التوزيع غير المتّصل

فرق Evergreen وFixed Version تقريباً كالتالي.

  Evergreen Fixed Version
من يحدّث Microsoft. يُحدَّث تلقائيّاً أنت. تُبدِّله مع تحديث التطبيق
الكيان على الجهاز نسخة واحدة مشتركة لكلّ التطبيقات مضمَّن لكلّ تطبيق
حجم التوزيع يكاد لا يزيد يتجاوز 250 MB
طريقة الوضع Bootstrapper نحو 2 MB ينزّل ما يلزم. غير المتّصل: ضمّن Standalone Installer وزّع مجموعة الثنائيات الموسَّعة مع التطبيق
قيد قائم يلزم التحقّق قبل الإقلاع هل هو على الجهاز لا يمكن التشغيل من مسار شبكة أو UNC

Evergreen Runtime مثبَّت مسبقاً جزءاً من نظام التشغيل على Windows 11. لكن تبقى أجهزة Windows 10 بلاه، لذا تكتب Microsoft نفسها «حتى إن اخترت Evergreen فالأفضل توزيع Runtime». أي أنّ إجراء التحقّق من الوجود في جهة التطبيق وإدخاله إن نقص يلزم في الحالين. Fixed Version مقابل «تمسك توقيت التحديث بنفسك» يزيد المُنتَج المسلَّم مئات MB. يلزم تقرير هذا أوّلاً، منفصلاً عن حديث EXE واحد.

WebView2 قرّر أسلوب التوزيع أوّلاًمخطّط يبيّن أنّ Evergreen نسخة مشتركة واحدة يحدّثها Microsoft تلقائيّاً لكن قد لا تكون على الجهاز، وFixed Version يمسك التحديث بنفسك مقابل زيادة المُنتَج المسلَّم مئات MB، وفي الحالين يلزم إجراء التحقّق من الوجود في جهة التطبيق وإدخاله إن نقص.اعتماد WebView2Evergreen: نسخة مشتركة تُحدَّث تلقائيّاًFixed Version: تضمين وتحديث بنفسكتحقّق من الوجود وأدخل إن نقصيزيد المُنتَج المسلَّم مئات MB

الشكل 12: موضوع WebView2 ليس عدد EXE بل معاملة Runtime.

5.4 WinUI 3 / Windows App SDK

WinUI 3 أيضاً تتغيّر متطلّبات التوزيع لحظة اعتماده. اختيار تقنية الواجهة يصير اختيار أسلوب التوزيع كما هو.

تحديداً، ما تقرّره محوران.

  • packaging: packaged (MSIX)، أو packaged يشير إلى موضع خارجي، أو unpackaged
  • runtime: framework-dependent أو self-contained

وما يؤثّر من زاوية الملفّ التنفيذي الواحد قيد هذا التركيب.

  • PublishSingleFile يعمل فقط لتطبيق WinUI 3 unpackaged وself-contained، ويلزم Windows App SDK 1.5 فصاعداً.
  • التطبيقات packaged، والتطبيقات packaged التي تشير إلى موضع خارجي، لا يعمل فيها PublishSingleFile.
  • جعلها unpackaged يفقد package identity، فتتعدّر وظائف Windows التي تفترض package identity مثل الإشعارات ومهام الخلفية وربط الملفّات وامتداد قائمة السياق.

أي أنّ في WinUI 3 «جعله EXE واحداً» و«استخدام امتدادات Windows» يصطدمان وجهاً لوجه. إن جعلت الملفّ التنفيذي الواحد أولوية قصوى، كثيراً ما يكون مراجعة افتراض تقنية الواجهة أوّلاً أسرع.

اصطدام EXE واحد وpackage identityمخطّط يبيّن أنّ PublishSingleFile في WinUI 3 يعمل فقط في تركيب unpackaged وself-contained، وأنّ unpackaged يفقد package identity فتتعدّر وظائف مثل الإشعارات وربط الملفّات، لذا يصطدم EXE واحد وامتدادات Windows وجهاً لوجه.تريد استخدام PublishSingleFileunpackaged+self-contained فقطتفقد package identityالإشعارات والربط وغيرها تتعدّرEXE واحد وامتدادات يصطدمان وجهاً لوجه

الشكل 13: في WinUI 3 اختيار EXE واحد يعني التخلّي عن package identity.

6. مجال يحتاج جوهريّاً «تسجيلاً واعتماداً»

6.1 امتداد Shell

امتداد Shell الذي يُحمَّل في Explorer شيء آخر غير «EXE يُوضَع فقط». هنا الموضوع ليس عدد الملفّات بل كيف تسجّل في Explorer.

6.2 خدمة Windows

حتى إن صار exe الخدمة نفسه ملفّاً واحداً، التوزيع مسألة أخرى.

  • التسجيل في SCM
  • الصلاحيات
  • حساب التشغيل
  • إعدادات الاستعادة

يلزم التفكير فيها. أي أنّ الخدمة مجال تُحكَم فيه «كيف تثبّت» أكثر من «جعله EXE واحداً».

6.3 التعريفات

التعريفات أوضح. لا تقوم إلّا مع INF والتوقيع وإجراء التثبيت، فتصعب ركوب ملعب الملفّ التنفيذي الواحد من البداية.

مجال موضوعه التسجيل والتوقيعمخطّط يبيّن أنّ امتداد Shell تسجيل في Explorer، وخدمة Windows تسجيل في SCM وصلاحيات وحساب تشغيل، والتعريف لا يقوم إلّا مع INF والتوقيع، لذا الموضوع تصميم التسجيل والاعتماد أكثر من عدد الملفّات.امتداد Shellتسجيل في Explorerخدمةتسجيل SCM · صلاحيات · حسابتعريفINF والتوقيعالموضوع تصميم التسجيل أكثر من عدد الملفّات

الشكل 14: في هذه المجالات الثلاثة أحكم «كيف تسجّل» أكثر من «جعله EXE واحداً».

7. جدول قرار للتشغيل

للحكم التقريبي هذا الجدول سهل الاستخدام.

ما تريد بناءه واقعية EXE واحد ما يجب التفكير فيه أوّلاً
أداة Win32 / C++ تُشغَّل وحدها عالية الربط الساكن، نظام التشغيل / arch المستهدف
أداة WinForms / WPF تُشغَّل وحدها عالية ملاءمة self-contained وsingle-file وNative AOT
تطبيق WinUI 3 / Windows App SDK متوسطة وضع التوزيع، اعتماد إضافي
واجهة سطح مكتب مبنية على WebView2 منخفضة إلى متوسطة أسلوب توزيع Runtime
امتداد نقر أيمن أو معاينة في Explorer منخفضة تسجيل COM / السجلّ
خدمة Windows متوسطة تسجيل SCM، الصلاحيات، إجراء التحديث
تطبيق يضمّ تعريفاً منخفضة INF، التوقيع، التثبيت

أهمّ ما في هذا الجدول إدراك أنّ «عدد الثنائيات» و«نطاق مسؤولية التوزيع» أمران مختلفان.

8. ما يجب تقريره أوّلاً في تصميم التوزيع

إن أردت نجاح جعله ملفاً تنفيذيّاً واحداً، أمور يستحقّ تقريرها قبل التنفيذ.

8.1 قرّر ماذا تريد واحداً

  • أتريد المُنتَج المسلَّم ملفّاً واحداً
  • أم إلغاء التثبيت المسبق لوقت التشغيل
  • أم إلغاء المثبِّت
  • أم تبسيط التحديث غير المتّصل

بهذا الجواب تتغيّر التقنية المختارة.

8.2 ثبّت أدنى Windows مدعوم وarch أوّلاً

single-file وNative AOT في الأساس خاصّان بنظام التشغيل / المعمارية. إن مضيت بـ «ملفّ واحد كيفما اتّفق» وهذا غامض، تنسدّ أخيراً بنقص واجهة أو عدم تطابق وقت التشغيل.

8.3 صرّح بما تضمّنه وما توكله إلى Windows

عمليّاً، كتابة هذا الجدول وحدها تقلّل الحوادث كثيراً.

  • ما تضمّنه في التطبيق
    • exe الجسم
    • DLL الخاصة بك
    • قالب الإعداد
    • وقت تشغيل self-contained
  • ما توكله إلى Windows
    • مكتبات DLL للنظام
    • واجهات نظام التشغيل
    • SCM / السجلّ / Explorer
    • أساس التعريفات
  • ما تفترضه على حدة
    • WebView2 Runtime
    • VC++ Redistributable
    • Office / Excel
    • تعريف مخصَّص
صرّح بثلاثة تصنيفات لنطاق المسؤوليةمخطّط يبيّن أنّ كتابة ثلاثة تصنيفات: ما تضمّنه في التطبيق، وما توكله إلى Windows، وما تفترضه على حدة، وحدها تقلّل حوادث التوزيع كثيراً.نطاق مسؤولية المُنتَج المسلَّمما تضمّنه في التطبيقما توكله إلى Windowsما تفترضه على حدةكتابته وحدها تقلّل الحوادث

الشكل 15: صرّح أوّلاً بثلاثة تصنيفات: التضمين، والتوكيل إلى نظام التشغيل، والافتراض على حدة.

8.4 إن أوليت الملفّ التنفيذي الواحد أولوية، قلّل تكامل المضيف

هذا ذو أثر كبير.

  • اترك امتداد Shell واجعله EXE عادياً
  • لا تجعله خدمة، واكتفِ بمجدول المهام أو تشغيل صريح
  • استخدم واجهة أصلية لا WebView2
  • أغلق COM داخل عمليتك

باختصار، كلّما قلّلت تصميماً «يحمّله نظام التشغيل» أو «يسجّله»، اقتربت من الملفّ التنفيذي الواحد.

كلّما قلّل تكامل المضيف اقتربتمخطّط يبيّن أنّ ترك امتداد Shell وجعله EXE عادياً، وعدم جعله خدمة والاكتفاء بمجدول المهام أو تشغيل صريح، واستخدام واجهة أصلية لا WebView2، أي تقليل تصميم التحميل والتسجيل في نظام التشغيل، يقرّبك من الملفّ التنفيذي الواحد.اترك امتداد Shell واجعله EXE عادياًقلّل تصميم التسجيل في نظام التشغيللا تجعله خدمة واستخدم تشغيلاً صريحاًواجهة أصلية لا WebView2تقترب من الملفّ التنفيذي الواحد

الشكل 16: إن أوليت الملفّ التنفيذي الواحد أولوية، قلّل تكامل المضيف نفسه.

9. الخلاصة

جعل الملفّ التنفيذي واحداً في Windows ممكن إلى حدّ بعيد. لكن المحطّة هذه الجملة.

يمكنك جعل التطبيق EXE واحداً. لكن لا يمكنك جعل Windows الذي يعتمد عليه التطبيق EXE واحداً أيضاً.

خمس نقاط تستحقّ التذكّر خصوصاً.

  • EXE العادي الذي يُشغَّل وحده يمكن تقريبه إلى توزيع ملفّ واحد إلى حدّ بعيد
  • الربط الساكن في C/C++ وsingle-file في .NET وNative AOT خيارات قويّة
  • لكن الاعتماد على إصدار نظام التشغيل وarch ومكتبات DLL للنظام ونموذج الأمن لا يزول
  • امتدادات Shell والخدمات والتعريفات وWebView2 وجزء من WinUI 3 يصير حديث التسجيل في نظام التشغيل ووقت التشغيل الإضافي هو الأصل
  • نجاح الملفّ التنفيذي الواحد يُحسَم بفصل «ماذا تريد واحداً» أوّلاً

إن أوليت الملفّ التنفيذي الواحد أولوية شديدة، فالتصميم عند اختيار التقنية باتجاه خفض درجة الارتباط بنظام التشغيل أنجح بكثير.

مفتاح النجاح درجة الارتباط بنظام التشغيلمخطّط يبيّن أنّ جعل التطبيق EXE واحداً ممكن بينما جعل Windows الذي يعتمد عليه EXE واحداً غير ممكن، لذا إن أوليت الملفّ التنفيذي الواحد أولوية شديدة فالتصميم عند اختيار التقنية باتجاه خفض درجة الارتباط بنظام التشغيل أنجح.جعل التطبيق EXE واحداًممكنجعل Windows المعتمد عليه EXE واحداًغير ممكنلذلك اخفض درجة الارتباط بنظام التشغيل عند اختيار التقنية

الشكل 17: نجاح جعله EXE واحداً يُحسَم بتصميم درجة الارتباط بنظام التشغيل أوّلاً.

10. روابط مرجعية

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

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

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

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

هل يمكن توزيع تطبيق Windows في ملفّ EXE واحد فقط؟
إن كان أداة سطح مكتب تُشغَّل وحدها، فإلى حدّ بعيد نعم. الربط الساكن في C/C++، وself-contained وsingle-file وNative AOT في .NET، تقرّب المُنتَج المسلَّم إلى EXE واحد. لكن إمكان EXE واحد وعدم الاعتماد على Windows المستهدف أمران مختلفان؛ الاعتماد على إصدار نظام التشغيل والمعمارية ومكتبات DLL للنظام ونموذج الأمن لا يزول.
هل يزيل single-file في .NET الاعتماد على نظام التشغيل؟
لا. ما يقلّله single-file أساساً تماسك مُنتَج التطبيق المسلَّم، لا الاعتماد على نظام التشغيل. framework-dependent يعتمد على .NET في البيئة المستهدفة، وself-contained يحمل وقت تشغيل .NET، وNative AOT يقلّل اعتماد الإقلاع أكثر مع قيود وظيفية. single-file وNative AOT في الأساس خاصّان بنظام التشغيل والمعمارية، لذا يلزم تثبيت أدنى Windows مدعوم والمعمارية أوّلاً.
أيّ التطبيقات يصعب جعلها EXE واحداً؟
امتدادات Shell، وخدمات Windows، والتعريفات، وواجهة مبنية على WebView2، وجزء من WinUI 3. هنا الموضوع ليس عدد الملفّات بقدر ما يُسجَّل في نظام التشغيل وكيف يُعامَل وقت تشغيل إضافي. مثلاً امتداد Shell يحتاج تسجيلاً في Explorer، والخدمة تحتاج تسجيلاً في SCM وتصميم صلاحيات وحساب تشغيل، والتعريف لا يقوم إلّا مع INF والتوقيع، فلا يقوم توزيع بالوضع فقط. WebView2 يتطلّب تقرير أسلوب توزيع WebView2 Runtime أوّلاً.
هل يوجد أسلوب توزيع أفضل من الدفن قسراً في EXE واحد؟
التوزيع app-local بوضع DLL بجانب EXE خيار قوي. حتى شكل app.exe مع بضعة DLL مجاورة، إن أمكن توزيع xcopy بلا مثبِّت وبلا امتيازات مدير، فليس نادراً أن تكون الصيانة أسهل من الضغط قسراً إلى EXE واحد. المهمّ فصل المراد أوّلاً: أتريد مُنتَجاً مسلَّماً واحداً، أم إلغاء التثبيت المسبق لوقت التشغيل، أم إلغاء المثبِّت.

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

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

غو كومورا

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

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

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