ما هو COM - لماذا لا يزال تصميم Windows COM يبدو جميلاً حتى اليوم
· آخر تحديث: · 小村 豪 · COM, ActiveX, تطوير Windows
سجل التعديلات (3 تحديثات، آخر تحديث 3 Sep، 2026)
سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.
- أُضيفت روابط الاستشارة الموجودة في الأصل الياباني (consultation_services). ولم يتغيّر نصّ المقالة نفسه. قراءة النسخة السابقة لهذا التحديث (DOI: 10.5281/zenodo.22240793)
- أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
- أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
- النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621303)
هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.
小村 豪 (2026). ما هو COM - لماذا لا يزال تصميم Windows COM يبدو جميلاً حتى اليوم. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621303 https://comcomponent.com/ar/blog/2026/01/25/001-why-com-is-beautiful/
- DOI (أحدث نسخة)
- 10.5281/zenodo.21621303
- DOI (هذه النسخة)
- 10.5281/zenodo.22279674
ما هو COM؟
COM (Component Object Model) هو «عقد ثنائي» تتواصل به المكوّنات فيما بينها على Windows. آلية تتواصل عبر عقد صارم اسمه الواجهة، متجاوزة اختلافات اللغات والمترجمات، وفي أسسه فكرة تصميم تقول: «لا تبرمج مقابل التنفيذ، بل مقابل العقد».
في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 23، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle
العناصر الثلاثة المهمّة في COM
ما نعدّه في هذا الباب هو أجزاء تكوّن آلية COM. أمّا «نقاط قوّة COM الأربع» لاحقاً فهي خصائص تنتج عن جمع هذه الأجزاء، وليست إعادة شرح للشيء نفسه مرّتين. نعرض التقابل في جدول في نهاية باب نقاط القوّة.
1. تصميم يتمحور حول الواجهة
في COM «العقد قبل التنفيذ». يمكنك استخدام الكائن إذا عرفت الواجهة المنشورة، حتى إن لم تعرف تنفيذه الداخلي.
2. التعريف عبر GUID (CLSID / IID)
يُمنح كلّ مكوّن وكلّ واجهة معرّفاً فريداً عالمياً (GUID)، لذلك لا يقع تصادم الأسماء أصلاً.
3. IUnknown
الواجهة الأساسية التي ترثها كلّ واجهات COM. تقدّم الوظائف الثلاث التالية.
| الدالة | الدور |
|---|---|
QueryInterface |
السؤال عمّا إذا كان الكائن يحمل واجهة أخرى |
AddRef |
زيادة عدّاد المراجع |
Release |
إنقاص عدّاد المراجع (وعند الصفر يدمّر الكائن نفسه) |
عندما تجتمع هذه العناصر الثلاثة، لا يبقى بين المستدعي والتنفيذ سوى «واجهة معرّفة بـ GUID وترتيب دوالّها ثابت». لا تظهر اللغة ولا المترجم في هذا العقد.
flowchart LR
subgraph CALLER["جهة الاستدعاء ── اللغة غير مقيّدة"]
A1["تطبيق C++"]
A2["تطبيق C#"]
A3["VBA / Python وغيرهما"]
end
CONTRACT["العقد (الجزء المثبت ثنائياً)<br/>· يحدّد IID (GUID) أيّ عقد هو بشكل فريد<br/>· ترتيب يبدأ بدوال IUnknown الثلاث<br/>· نوع الوسائط والقيمة المعادة وcalling convention لكلّ دالة"]
subgraph IMPL["التنفيذ ── اللغة غير مقيّدة"]
B1["مكوّن مكتوب بـ C++"]
B2["مكوّن مكتوب بـ C#"]
end
A1 --> CONTRACT
A2 --> CONTRACT
A3 --> CONTRACT
CONTRACT --> B1
CONTRACT --> B2
الشكل 1: العقد الثنائي في COM. لا تظهر لغة المستدعي ولا لغة التنفيذ في العقد، لذلك يمكن استبدال أيّ طرف دون إعادة بناء الطرف الآخر.
«البرمجة مقابل العقد» كما تظهر في الشيفرة
يصعب فهم ذلك بالنصّ وحده، فنحوّله إلى حدّ أدنى من الشيفرة. المثال يستخدم مكوّن جمع بسيط ICalcService دون أيّ معرفة بتنفيذه.
نبدأ من C++ (COM خام). تعريف ICalcService المكتوب هنا هو العقد نفسه. لا يظهر في شيفرة المستدعي إن كان التنفيذ مكتوباً بـ C++ أو بـ C#.
#include <objbase.h>
// تعريف العقد. عادةً تُولَّد ترويسة بهذا الشكل من IDL
// يرث IUnknown لذا يحمل QueryInterface / AddRef / Release حتماً
struct __declspec(uuid("7A4B5B23-0A2F-4D2B-9D4D-8A2A92B8B001"))
ICalcService : public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE Add(int a, int b, int* result) = 0;
};
// عقد موسَّع أُضيف لاحقاً. GUID مختلف
struct __declspec(uuid("7A4B5B23-0A2F-4D2B-9D4D-8A2A92B8B002"))
ICalcServiceEx : public ICalcService
{
virtual HRESULT STDMETHODCALLTYPE Multiply(int a, int b, int* result) = 0;
};
// CLSID مكوّن التنفيذ. عادةً يُعرَّف في ترويسة مولَّدة من IDL
static const CLSID CLSID_CalcService =
{ 0x1C9B6F4D, 0x1E9A, 0x4E61, { 0x9A, 0x4F, 0x6A, 0x0F, 0x1D, 0x2D, 0x9A, 0x11 } };
// جهة الاستدعاء
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) { return hr; }
ICalcService* calc = nullptr;
hr = CoCreateInstance(CLSID_CalcService, nullptr, CLSCTX_ALL,
__uuidof(ICalcService), reinterpret_cast<void**>(&calc));
// المؤشّر العائد هنا نُفِّذ عليه AddRef (عدّ المراجع = 1)
if (SUCCEEDED(hr))
{
int sum = 0;
hr = calc->Add(1, 2, &sum); // يُستدعى دون معرفة التنفيذ
// السؤال وقت التشغيل «هل يحمل العقد الموسَّع أيضاً» = تنفيذ يتعايش مع الإصدارات
ICalcServiceEx* calcEx = nullptr;
if (SUCCEEDED(calc->QueryInterface(__uuidof(ICalcServiceEx),
reinterpret_cast<void**>(&calcEx))))
{
// لا نصل هنا إلا إذا كان المكوّن الإصدار الجديد
calcEx->Release(); // من استلم المؤشّر يعيده
}
// إن لم يحمله يُعاد E_NOINTERFACE فقط، ويستمرّ الإصدار القديم في العمل
calc->Release(); // يصل عدّ المراجع إلى 0 فيُدمَّر
}
CoUninitialize();
مواضع القراءة ثلاثة.
- نادراً ما تكتب
AddRefبنفسك. كلّ منCoCreateInstanceوQueryInterfaceيكون قد نفّذAddRefعلى المؤشّر الذي يعيده. المبدأ إذاً: «من استلم المؤشّر يستدعيRelease». لا تستدعيAddRefصراحة إلا عندما تبدأ بالاحتفاظ بالمؤشّر نفسه في موضع ثانٍ. - فشل
QueryInterfaceليس حالة شاذّة. «لا أحمل هذا العقد» (E_NOINTERFACE) جواب سليم، وهو ما يتيح «إضافة وظيفة جديدة دون كسر المكوّن القديم». - كلّ قيمة معادة هي
HRESULT. إعادة النجاح والفشل بقيمة معادة لا باستثناء ترتيب لازم لعبور اللغات. طريقة رمي الاستثناءات تختلف من لغة إلى لغة، أمّا قيمة صحيحة فيفهمها الجميع.
flowchart TB
accTitle: مبدأ عدّ المراجع وRelease
accDescr: مخطّط يبيّن المبدأ: CoCreateInstance وQueryInterface يعيدان مؤشّراً نُفِّذ عليه AddRef سلفاً، فيستدعي المستلم Release عند انتهاء الاستخدام، ويُدمَّر الكائن عندما يصل عدّاد المراجع إلى صفر.
api["CoCreateInstance أو QueryInterface"] --> ret["يعود مؤشّر نُفِّذ عليه AddRef"]
ret --> use["المستلم يستخدمه"]
use --> rel["المستلم يستدعي Release"]
rel --> zero["يُدمَّر عند وصول العدّاد إلى صفر"]
use -.->|"AddRef صراحة"| add["الاحتفاظ بالمؤشّر نفسه في موضع ثانٍ"]
الشكل 2: المبدأ أنّ من استلم المؤشّر يستدعي Release، ولا يُستدعى AddRef صراحة إلا عند زيادة مواضع الاحتفاظ.
استخدام العقد نفسه من C# يبدو كالتالي. GUID نفسه يعني العقد نفسه، لذلك لا بأس إن كان الطرف الآخر تنفيذاً بـ C++.
using System;
using System.Runtime.InteropServices;
// اكتب GUID نفسه الذي في جانب C++. هذا إعلان «العقد نفسه»
[ComImport]
[Guid("7A4B5B23-0A2F-4D2B-9D4D-8A2A92B8B001")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ICalcService
{
int Add(int a, int b);
}
// جانب الاستدعاء
Type t = Type.GetTypeFromProgID("KomuraSoft.CalcService")
?? throw new InvalidOperationException("خادم COM غير مسجَّل.");
object server = Activator.CreateInstance(t)!;
try
{
var calc = (ICalcService)server; // هذا التحويل يعادل QueryInterface
int sum = calc.Add(1, 2);
Console.WriteLine(sum); // 3
}
finally
{
Marshal.ReleaseComObject(server); // يعادل Release
}
سبب كون قيمة Add المعادة int في جانب C# هو أنّ التشغيل البيني لـ COM في .NET يجري تحويلاً ثابتاً: «آخر وسيط [out, retval] يصير قيمة معادة، وHRESULT الفاشل يُحوَّل إلى استثناء». كذلك يختفي AddRef/Release عن شيفرة المستدعي، لكنّهما لم يزولا؛ الغلاف الرقيق الذي يوفّره .NET (RCW) يستدعيهما نيابة عنك. العقد نفسه يُستخدم بأسلوب طبيعي لكلّ لغة — هذا هو الوجه العملي لـ «العقد الثنائي».
flowchart TB
accTitle: تقابل أسلوب C# مع COM
accDescr: مخطّط يبيّن التقابل: في C# يعادل التحويل إلى الواجهة QueryInterface، ويعادل Marshal.ReleaseComObject دالة Release، ويُحوَّل HRESULT الفاشل إلى استثناء، ويستدعي RCW دالتي AddRef وRelease نيابة عنك.
cs["شيفرة C#"] --> cast["التحويل إلى نوع"]
cs --> rco["ReleaseComObject"]
cs --> hrx["HRESULT فاشل"]
cast --> qi["يعادل QueryInterface"]
rco --> rel["يعادل Release"]
hrx --> ex["يُحوَّل إلى استثناء"]
cs -.-> rcw["RCW ينوب في عدّ المراجع"]
الشكل 3: حتى مع العقد نفسه، يُستبدل أسلوب C# بما يناسب اللغة، ويتولّى RCW وطبقة التشغيل البيني التحويل.
نقاط قوّة COM الأربع
1. التوافق الثنائي
يمكن إعادة استخدام مكوّن بُني مرّة واحدة بغضّ النظر عن لغة البرمجة أو زمن التشغيل. استدعاء مكوّن COM مكتوب بـ C++ من C# أو Python أمر شائع.
2. فصل الواجهة
لأنّ التنفيذ يُخفى بالكامل ويُنشر العقد فقط، يمكنك تغيير التنفيذ الداخلي بحرّية دون أثر على المستدعي.
3. تعايش الإصدارات
الأساس لإضافة وظائف مع الإبقاء على التوافق الخلفي هو إضافة واجهة جديدة. تقدّم الوظيفة الجديدة دون تغيير الواجهة القديمة.
عند جمع مستدعٍ قديم أو جديد مع مكوّن قديم أو جديد، تعمل ثلاث تركيبات من الأربع كما هي، والرابعة لا تفعل أكثر من إعادة جواب «لا أحمل هذا العقد».
flowchart LR
OLDC["مستدعٍ قديم<br/>لا يعرف سوى ICalcService"]
NEWC["مستدعٍ جديد<br/>يسأل عن ICalcServiceEx"]
OLDS["مكوّن بالإصدار القديم<br/>ينفّذ ICalcService فقط"]
NEWS["مكوّن بالإصدار الجديد<br/>ينفّذ الاثنين"]
OLDC -->|"QueryInterface(IID_ICalcService)<br/>S_OK"| OLDS
OLDC -->|"QueryInterface(IID_ICalcService)<br/>S_OK ── لا ينكسر بعد التحديث"| NEWS
NEWC -->|"QueryInterface(IID_ICalcServiceEx)<br/>S_OK ── تتاح الوظيفة الجديدة"| NEWS
NEWC -.->|"QueryInterface(IID_ICalcServiceEx)<br/>E_NOINTERFACE ── المتابعة بالوظيفة القديمة"| OLDS
الشكل 4: إضافة IID جديد دون تغيير الواجهة القائمة يبقي كلّ تركيب للقديم والجديد يعمل. الخطّ المتقطّع هو الجواب السليم «لا أحمل هذا العقد».
4. إعادة الاستخدام عبر حدود العملية
لمكان مكوّن COM نوعان. In-proc (خادم DLL) الذي يُحمَّل في العملية نفسها مع المستدعي كـ DLL، وOut-of-proc (خادم EXE، LocalServer) الذي يُشغَّل كـ EXE في عملية أخرى. مظهر شيفرة الاستدعاء لا يتغيّر في الحالتين.
flowchart TB
accTitle: مكانان لوضع المكوّن
accDescr: مخطّط يبيّن أنّ شيفرة الاستدعاء بالمظهر نفسه يمكن أن تصل إمّا إلى In-proc الذي يُحمَّل كـ DLL في عملية المستدعي، أو إلى Out-of-proc الذي يُشغَّل كـ EXE في عملية أخرى.
caller["شيفرة المستدعي (المظهر نفسه)"] --> ip["In-proc (خادم DLL)"]
caller --> op["Out-of-proc (خادم EXE)"]
ip -.-> ipd["يُحمَّل كـ DLL في العملية نفسها"]
op -.-> opd["يُشغَّل كـ EXE في عملية أخرى"]
الشكل 5: المكان نوعان، In-proc وOut-of-proc، لكنّ مظهر شيفرة الاستدعاء لا يتغيّر.
| In-proc (خادم DLL) | Out-of-proc (خادم EXE) | |
|---|---|---|
| مكان التنفيذ | العملية نفسها مع المستدعي | عملية أخرى |
| حقيقة الاستدعاء | استدعاء مباشر عبر مؤشّر دالة | إعادة تعبئة الوسائط (marshalling) وتمريرها عبر تواصل بين العمليات |
| السرعة | سريع | أبطأ بمقدار التواصل بين العمليات |
| إذا سقط الطرف الآخر | يسقط المستدعي معه | يبقى المستدعي حيّاً (يعود الاستدعاء كفشل) |
| عدد البتّات (32/64bit) | لا يُحمَّل إن لم يتطابق | يجوز أن يختلف |
باستخدام Out-of-proc COM (خادم EXE) يمكنك استدعاء وظائف عملية أخرى بأمان. الصفّ الأخير «يجوز أن يختلف 32bit/64bit» ينفع في الميدان، وتركيبة استدعاء DLL بـ 64bit من تطبيق 32bit مشروحة في «دراسة حالة لجسر COM يستدعي DLL بـ 64bit من تطبيق 32bit».
غير أنّ الوجود في عملية أخرى يعني أيضاً أنّ الطرف الآخر قد يختفي في أيّ وقت. إذا تعطّلت عملية الخادم أو انتهت، يعود إلى المستدعي فشل كهذا. هذه أخطاء خاصة بـ Out-of-proc تعني «الطرف الآخر لم يعد موجوداً»، لا «انكسر شيء».
| رمز الخطأ | المعنى |
|---|---|
RPC_E_DISCONNECTED |
الكائن الذي حاولت استدعاءه انفصل عن العميل (كائن الطرف الآخر لم يعد موجوداً) |
RPC_S_SERVER_UNAVAILABLE |
تعذّر الوصول إلى خادم الاستدعاء (العملية) |
ما كان يمكنك تجاهله في In-proc («إن سقط سقطت معه») يدخل في تصميم Out-of-proc كـ معالجة استعادة بإعادة التشغيل أو إعادة الاتّصال. الأدقّ أن تراه عملاً يزيد مقابل السلامة.
flowchart TB
accTitle: التدفّق عندما تختفي عملية الطرف الآخر
accDescr: مخطّط يبيّن أنّه في Out-of-proc إذا اختفت عملية الخادم بتعطّل أو إنهاء يعود الاستدعاء كفشل ويبقى المستدعي حيّاً، لذلك يلزم إدخال معالجة استعادة بإعادة التشغيل أو إعادة الاتّصال في التصميم.
gone["تعطّل عملية الخادم أو إنهاؤها"] --> fail["يعود الاستدعاء كفشل"]
fail --> alive["المستدعي يبقى حيّاً"]
alive --> rec["إلى معالجة الاستعادة بإعادة التشغيل أو إعادة الاتّصال"]
fail -.-> mean["ليس انكساراً بل غياب الطرف الآخر"]
الشكل 6: في Out-of-proc لا تسقط مع الطرف الآخر إذا اختفى، وفي المقابل تدخل معالجة الاستعادة في التصميم.
تقابل العناصر الثلاثة ونقاط القوّة الأربع
كما ذكرنا في البداية، «العناصر الثلاثة» أجزاء، و«نقاط القوّة الأربع» نتيجتها. صفّ أيّ جزء يدعم أيّ قوّة فيوضّح تقسيم الأدوار الذي بدا متداخلاً.
| نقطة القوّة | العنصر الذي يعمل أساساً |
|---|---|
| 1. التوافق الثنائي | التصميم المتمحور حول الواجهة + IUnknown (ترتيب الاستدعاء يُحسم على المستوى الثنائي) |
| 2. فصل الواجهة | التصميم المتمحور حول الواجهة (نشر العقد فقط) |
| 3. تعايش الإصدارات | GUID + QueryInterface (يمكن السؤال عن عقد آخر وقت التشغيل) |
| 4. إعادة الاستخدام عبر حدود العملية | التصميم المتمحور حول الواجهة (يمكن فصل مكان التنفيذ عن العقد أيضاً) |
COM ما زال في الخدمة
كثيراً ما يُظنّ «تقنية قديمة»، لكنّ COM آلية ما زالت تُستخدم في صميم Windows.
أين يُستخدم COM
- امتدادات Explorer (قائمة النقر بالزر الأيمن، عرض المعاينة)
- أتمتة Office (التحكّم الخارجي بـ Excel وWord)
- التشغيل البيني مع .NET (COM Interop)
- الأنظمة القائمة التي تضمّ ActiveX
- عدد كبير من واجهات Windows API مثل DirectX وWindows Shell API
حتى إن ظننت أنّه «لا يعنيني»، ما دمت تطوّر لـ Windows سيظهر COM في مكان ما.
خلاصة
مركز تصميم COM هو «الاستقلال عن اللغة والعملية والتنفيذ». تصميم واجهة محايد لغوياً، وتعريف فريد وإدارة إصدارات عبر GUID، وعدّ مراجع عبر IUnknown، وآلية تعامل شفّاف مع التواصل بين العمليات.
flowchart TB
accTitle: مركز تصميم COM
accDescr: مخطّط يبيّن أنّ أربع آليات تسند مركز التصميم، وهو الاستقلال عن اللغة والعملية والتنفيذ: تصميم واجهة محايد لغوياً، وتعريف فريد وإدارة إصدارات عبر GUID، وعدّ مراجع عبر IUnknown، وتواصل شفّاف بين العمليات.
i1["تصميم محايد لغوياً"] --> core["الاستقلال عن اللغة والعملية والتنفيذ"]
i2["تعريف فريد عبر GUID"] --> core
i3["عدّ المراجع في IUnknown"] --> core
i4["تواصل شفّاف بين العمليات"] --> core
الشكل 7: تجتمع أربع آليات لتسند مركز COM: «الاستقلال عن اللغة والعملية والتنفيذ».
«جميل» حكم ذاتي، لكنّ مستنده ملموس. إذا صففنا المشكلة التي حاول COM حلّها وطريقة حلّها، نحصل على التالي.
| قيد كان قائماً آنذاك (وما زال) | جواب COM |
|---|---|
| لا يملك C++ عقداً ثنائياً قياسياً (ABI)، فيتعذّر إعادة الاستخدام لمجرد اختلاف المترجم. لا تتوافق زخرفة الأسماء ولا تخطيط الكائن | جعل العقد «ترتيب جدول الدوال الافتراضية» فقط. لأنّه اختُصر إلى هذه النقطة، لم تعد اللغة ولا المترجم مقيّدين |
| استبدال مكتبة يفرض إعادة بناء كلّ من يستخدمها | ما دام العقد (الواجهة) لم يتغيّر، لا حاجة لإعادة البناء. يمكن الاستبدال كثنائي |
| تريد إضافة وظيفة دون كسر المستدعين القائمين | تُضاف الواجهة دون تغييرها، ويُسأل QueryInterface وقت التشغيل «هل تحملها؟» |
| تصادم الأسماء (أشياء مختلفة بالاسم نفسه تتعايش) | التعريف الفريد بـ GUID. ألغى الحاجة إلى ضبط الأسماء أصلاً |
| استدعاء وظيفة في عملية أخرى أو جهاز آخر يغيّر أسلوب كتابة الاستدعاء تماماً | إدخال Proxy/Stub يحافظ على شكل شيفرة المستدعي |
أي أنّ تصميم COM لم يبدأ من «كيف يكون أنيقاً»، بل وصل إلى شكله الحالي كنتيجة لإزالة عوائق إعادة الاستخدام واحداً تلو الآخر. قليل من التصاميم يمكن تتبّع تقابل القيد والحلّ فيه بهذه الاستقامة.
وهذه الطريقة في الحلّ ما زالت قائمة في تطوير المكوّنات المعاصر كما هي.
| COM | المقابل المعاصر |
|---|---|
| تثبيت العقد أوّلاً بـ IDL، وتوليد شيفرة الطرفين منه | توليد العميل/الخادم من مخطّط OpenAPI أو Protocol Buffers |
| إضافة واجهة جديدة دون تغيير الواجهة القائمة | في Protocol Buffers إضافة حقول دون إعادة استخدام أرقامها، أو تقسيم إصدارات API |
| اللغة غير مقيّدة (عقد ثنائي) | اللغة غير مقيّدة (عقد رسائل عبر الشبكة) |
| Proxy/Stub يخفي حدود العملية | عميل RPC stub يخفي حدود الشبكة |
ما يختلف هو نوع الحدود (حدود عملية على الجهاز نفسه، أم شبكة) وتعبير العقد (ثنائي، أم نصّ/مخطّط) فقط. إذا فهمت COM، يستقرّ في تصميم واجهات الخدمات المصغّرة «لماذا يُثبَّت العقد أوّلاً» و«لماذا لا يجوز حذف حقل قائم» كضرورة، لا كموضة.
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
ما ينبغي تنظيمه قبل طلب التعهيد أو التطوير التعاقديّ لتطبيق Windows
قبل تكليف جهة خارجية بتطوير تطبيق Windows تعاقديّاً، إليك النقاط التي ينبغي تنظيمها: تعديل البرمجيّات القائمة، وتكامل الأجهزة، وCOM/Activ...
فخاخ التسجيل وbitness في تطوير COM و OCX / ActiveX
نرتّب من منظور عمليّ ما يسهل التعثّر فيه في تطوير COM و OCX و ActiveX: 32-bit/64-bit، Visual Studio 2022، regsvr32/Regasm، صلاحيات المسؤو...
ما هي COM / ActiveX / OCX: الفروق والعلاقات
تنظيم ما هي COM وما هي ActiveX وما هي OCX، مع الفروق والعلاقات وصلة OLE، وأين تُستخدم، وكيف تُفهم اليوم من منظور العمل اليومي.
كيف تتعامل مع ActiveX / OCX اليوم - جدول قرار للإبقاء أو التغليف أو الاستبدال
عند العثور على ActiveX أو OCX، يبيّن المقال كيف تختار بين الإبقاء والتغليف والاستبدال، مع 32bit / 64bit والتسجيل واعتماد المتصفّح وصيانة ...
WinRT هو COM ── IInspectable و.winmd وإسقاط اللغات، ولماذا لا يزال WinUI يركب عقداً ثنائياً
WinRT ليس وقت تشغيل مُداراً؛ بل ABI أُضيفت إليه بيانات وصفية (.winmd) وإسقاطات لغات فوق COM. من علاقة IUnknown وIInspectable إلى تهيئة HW...
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
دعم إعادة استخدام الأصول القديمة وترحيلها
فهم تصميم COM وتوافقيته مدخل مناسب للتفكير في كيفية الاستفادة من أصول Windows القائمة.
الاستشارات التقنية ومراجعة التصميم
إن أردت ترتيب الخطة انطلاقاً من فهم IUnknown وGUID وطريقة النظر إلى تصميم الحدود، فذلك يقود إلى الاستشارة التقنية ومراجعة التصميم.
الأسئلة الشائعة
أسئلة شائعة حول موضوع هذه المقالة.
- ما هو COM؟
- COM (Component Object Model) هو «عقد ثنائي» تتواصل به المكوّنات فيما بينها على Windows. وهو آلية تتواصل عبر عقد صارم اسمه الواجهة، متجاوزة اختلافات اللغات والمترجمات. في أسسه فكرة تصميم تقول: «لا تبرمج مقابل التنفيذ، بل مقابل العقد».
- ما هو IUnknown؟
- الواجهة الأساسية التي ترثها كلّ واجهات COM. تقدّم ثلاث وظائف: QueryInterface للسؤال عمّا إذا كان الكائن يحمل واجهة أخرى، وAddRef لزيادة عدّاد المراجع، وRelease لإنقاص العدّاد وتدمير الكائن لنفسه عندما يصل إلى صفر. إدارة عمر كائن COM تقوم على عدّ المراجع هذا.
- هل ما زال COM مستخدماً اليوم؟
- نعم. COM آلية ما زالت تُستخدم في صميم Windows. تظهر في امتدادات Explorer (قائمة النقر بالزر الأيمن والمعاينة)، وأتمتة Office لـ Excel وWord، وCOM Interop مع .NET، والأنظمة القائمة التي تضمّ ActiveX، وكثير من واجهات Windows API مثل DirectX وWindows Shell API. ما دمت تطوّر لـ Windows، سيظهر COM في مكان ما.
- ما نقاط قوّة COM؟
- أربع نقاط رئيسة. التوافق الثنائي الذي يتيح إعادة استخدام مكوّن بُني مرّة واحدة بغضّ النظر عن اللغة أو زمن التشغيل، وفصل الواجهة الذي يخفي التنفيذ وينشر العقد فقط، وتعايش الإصدارات بإضافة واجهة جديدة مع الإبقاء على التوافق الخلفي، والاستدعاء الآمن لوظائف عملية أخرى عبر Out-of-proc COM (خادم EXE).
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.