في بعض الأحيان ، يجب على مكون 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 بدلاً من ذلك ، ولم يتم إبراز بعض العوامل به.