في بعض الأحيان ، يجب على مكون COM إرسال إشعار إلى العميل أو استدعاء وظيفة رد الاتصال. المخطط بسيط: يقوم المكون بنشر الواجهة ، ويقوم العميل بإنشاء كائن موروث من الواجهة ويمررها إلى المكون ، ويقوم المكون بدوره باستدعاء وظائف الواجهة ، وبالتالي استدعاء الوظائف على جانب العميل.
في حالة Visual Basic أو Visual Basic for Applicatons ، يمكننا كتابة فئة موروثة من أي واجهة ، ولكن هذا غير ممكن لملفات البرامج النصية VBScript.
هنا واجهة IDispatch
يندفع لمساعدتنا. باستخدام هذه الواجهة ، سيتولى مكوننا القوي بكل تواضع الدور المتواضع للعميل ، وسوف يتحول البرنامج النصي الصغير إلى خادم أتمتة حقيقي.
سنقوم بتطوير المكون في لغة البرمجة FreeBASIC.
فصول في ملف البرنامج النصي
يمكنك التصريح واستخدام الفصول في ملفات البرامج النصية. يتم توريث هذه الفئات ضمنيًا من واجهة IDispatch
وهي فئات COM حقيقية.
نعلن عن فئة ، سننتقل بعدها إلى مكوننا:
Class CallBack Function CallBack(Param)
سيتلقى المكون الخاص بنا CallBack
لفئة CallBack
، ويستدعي وظيفة CallBack
سلسلة نصية في المعلمة.
IDispatch و
هذه الواجهة هي حجر عثرة في الأتمتة. عادةً ما يعتمد تطبيق IDispatch
على مكتبة ITypeInfo->Invoke
خلال ITypeInfo->Invoke
أو الدالة CreateStdDispatch
، ولكن في هذه الحالة ، يوجد خادم الأتمتة في برنامج نصي ولا يحتوي على مكتبة أنواع ، ويعمل المكون الخاص بنا كعميل. لتبسيط ، يعمل IDipatch
مثل هذا: يأخذ اسم الوظيفة وينقل التحكم إليها.
يكمن تعريف الواجهة في العنوان "oaidl.bi" (تتم إضافة المسافات البادئة وفواصل الأسطر لسهولة القراءة):
Type IDispatch As IDispatch_ Type LPDISPATCH As IDispatch Ptr Type IDispatchVtbl
تعد وظائف GetIDsOfNames
و Invoke
أكثر إثارة للاهتمام في هذه الواجهة.
GetIDsOfNames
يأخذ اسم الدالة وإرجاع معرف الإرسال DISPID
. DISPID
هو اسم مستعار لنوع LONG
.
من وجهة نظر العميل ، يعد DISPID
مجرد أداة تحسين تتجنب تمرير السلسلة. بالنسبة للخادم ، DISPID
هو معرف الوظيفة التي يريد العميل الاتصال بها.
استدعاء
بواسطة معرف الإرسال يؤدي الوظيفة المقابلة.
DISPPARAMS
تحتوي هذه البنية على معلمات الوظيفة المدعوة. يتم حزم جميع المعلمات في VARIANT
.
Type tagDISPPARAMS
لتبسيط الرمز ، لن نستخدم الوسائط المسماة ، سنقوم بتعيين NULL
بدلاً من ذلك.
عنصر
للاستخدام في البرامج النصية ، يجب أن ترث المكونات أيضًا بشكل مباشر أو غير مباشر من IDipatch
.
واجهة ITestCOMServer
ITestCOMServer
نبني واجهة ITestCOMServer
مع وظيفتين SetCallBack
و InvokeCallBack
. الأول سيوفر كائن خادم الأتمتة ، والثاني سوف استدعاء وظيفة الكائن.
Type ITestCOMServer As ITestCOMServer_ Type LPITESTCOMSERVER As ITestCOMServer Ptr Type ITestCOMServerVirtualTable
فئة TestCOMServer
الآن يمكنك إعلان فئة COM:
Type TestCOMServer
وظيفة setcallback
تنفيذ وظيفة SetCallBack
بسيط: نحن SetCallBack
كائن خادم الأتمتة الذي يرسله العميل والمعلمة استدعاء دالة.
Function TestCOMServerSetCallBack( _ ByVal pTestCOMServer As TestCOMServer Ptr, _ ByVal CallBack As IDispatch Ptr, _ ByVal UserName As BSTR _ )As HRESULT
وظيفة InvokeCallBack
لكن وظيفة InvokeCallBack
ستعمل بجد. تحتاج أولاً إلى الحصول على معرف المرسل لوظيفة CallBack
لخادم الأتمتة.
Function TestCOMServerInvokeCallBack( _ ByVal pTestCOMServer As TestCOMServer Ptr _ )As HRESULT If pTestCOMServer->CallBack = NULL Then Return E_POINTER End If
بعد استلام DISPID
للوظيفة ، يمكن تسميتها:
استنتاج
كما ترون ، حتى مع وجود ملف نصي ، يمكن للمكون الحصول على ملاحظات. هذا مفيد لإعلام العميل بالعمليات المكتملة بواسطة المكون.
يمكن تسجيل الفئات في البرامج النصية في السجل ، وفي هذه الحالة ستكون متاحة للنظام بأكمله باستخدام ProgID
، لكن هذه قصة مختلفة تمامًا.
مراجع
رمز المشروع على موقع جيثب: https://github.com/zamabuvaraeu/TestCOMServer
ملاحظة: بطريقة ما ، اختفى تسليط الضوء على بناء جملة BASIC ، واستخدم VBScript بدلاً من ذلك ، ولم يتم إبراز بعض العوامل به.