استكشاف أخطاء التشغيل المتداخل

التفاعل بين COM و التعليمات البرمجية المُدارة لـ .NET Framework، قد تواجه مشكلة أو أكثر من المشكلات الشائعة التالية.

توافق التنظيم

في بعض الأوقات قد تضطر إلى استخدام أنواع البيانات التي ليست جزءاً من .NET Framework. تجميعات إمكانية التشغيل المتداخل تعالج معظم العمل لكائنات COM, و لكن قد تحتاج الى التحكم بأنواع البينات التي تستخدم عندما تتعرض التعليمات البرمجية المدارة الى COM. على سبيل المثال، يجب أن تحدد بنية في مكتبات الفئة BStr نوع غير مدار على السلاسل المرسلة الى كائنات COM التي تم إنشاؤها بواسطة Visual Basic 6.0 والإصدارات السابقة. في مثل هذه الحالات، يمكنك استخدام MarshalAsAttribute السمة لتعريض الأنواع المدارة كأنواع غير مدارة.

تصدير سلاسل ذات الطول الثابت إلى التعليمات البرمجية الغير مدارة

في Visual Basic 6.0 والإصدارات السابقة، يتم تصدير السلاسل إلى كائنات COM كسلسلة من البت بدون حرف الانهاء null. للتوافق مع لغات أخرى, Visual Basic 2005 يتضمن حرف إنهاء عند تصدير السلاسل. أفضل طريقة لعنوان عدم التوافق هذا هو تصدير السلاسل التي تفتقر الى حرف الإنهاء كصفائف من Byte أو Char.

هرم توريث التصديرات

تراتب الفئة المدارة يتم بسطها عندما يتم عرضها ككائنات COM. على سبيل المثال، إذا قمت بتعريف فئة أساسية مع عضو, و ثم وراثت فئة أساسية في فئة مشتقة التي يتم عرضها ككائن COM, العملاء الذين يستخدمون الفئة المشتقة في كائن COM لن يتمكنوا من استخدام الأعضاء الموروثين. يمكن الوصول إلى أعضاء الفئة الأساسية من كائنات COM فقط كـ مثيلات الفئة الأساسية, وبعد ذلك فقط إذا تم إنشاء الفئة الأساسية أيضاً كـ كائن COM.

الأساليب الزائدة

على الرغم من أنه يمكنك إنشاء أساليب محمّلة فوق طاقتها مع Visual Basic، فانها غير معتمدة بواسطة COM. عندما يتم تعريض فئة التي تحتوي على أساليب محملة فوق طاقتها كـكائن COM, يتم إنشاء أسماء أسلوب جديدة للأساليب المحملة فوق طاقتها.

على سبيل المثال، ضع في الاعتبار فئة التي تملك اثنين من أسلوب Synch المحملة فوق طاقتها. عند كشف الفئة أنه كائن COM, أسماء الأسلوب الذي تم إنشاؤه الجديدة قد تكونSynch و Synch_2.

إعادة التسمية يمكن أن تسبب مشاكل للمستهلكين لكائن COM.

  1. قد لا يتوقع العملاء أسماء الأسلوب المنشأ.

  2. أسماء الأسلوب الذي تم إنشاؤه في فئة مكشوفة ككائن COM يمكن أن تتغير عندما يتم اضافة تحميلات زائدة جديدة للفئة أو الفئة الأساسية الخاصة به. يمكن أن يسبب هذا مشاكل في تعيين الإصدار.

لحل كلاالمشكلتين، قم باعطاء كل أسلوب اسم خاص, بدلا من استخدام التحميل الزائد, عند تطوير الكائنات التي سيتم كشفها ككائنات COM.

استخدام كائنات COM عبر تجميعات إمكانية التشغيل المتداخل

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

فئات يتم كشفها كـ كلا واجهات و فئات

بعكس الفئات في التجميعات القياسية, فئات COM يتم كشفها في تجميعات إمكانية التشغيل المتداخل كـ كلا واجهة و فئة التي تمثل فئة COM. يماثل اسم الواجهة لتلك التي في فئة COM. اسم فئة إمكانية التشغيل المتداخل هي نفسها التى لدى فئة COM الأصلي, ولكن مع كلمة "فئة" ملحقة. على سبيل المثال، افترض أن لديك مشروع مع مرجع لتجميع التوافق لكائن COM. إذا تم تسمية فئة COM MyComClass، يظهر التحسس الذكي و مستعرض الكائن واجهة باسم MyComClass و فئة مسماة MyComClassClass.

إنشاء مثيلات فئة Framework .NET

بشكل عام، يتم إنشاء مثيل .NET Framework الفئة استخدام New الكشف مع اسم الفئة. امتلاك فئة COM يتم تمثيلها بواسطة تجميع التوافق هي الحالة الوحيدة حيث يمكنك استخدام New الكشف مع واجهة. ما لم تكن تستخدم فئة COM مع Inherits الكشف يمكنك استخدام الواجهة تماماً كما تفعل بالفئة. توضح التعليمة البرمجية التالية كيفية إنشاء Command الكائن في مشروع يحوي على مرجع إلى كائن COM مكتبة كائنات بيانات ActiveX 2.8 Microsoft:

Dim cmd As New ADODB.Command

ومع ذلك، إذا كنت تستخدم فئة COM كأساس فئة مشتقة, يجب عليك استخدام فئة إمكانية التشغيل المتداخل التي تمثل فئة COM كما هو موضح في التعليمات البرمجية التالية:

Class DerivedCommand
    Inherits ADODB.CommandClass
End Class

ملاحظة

تجميعات التوافق تنفذ ضمنيا الواجهات التي تمثل فئات COM. يجب عدم محاولة استخدام Implements الكشف لتنفيذ هذه الواجهات أو سيؤدي ذلك إلى خطأ.

أنواع البيانات للمعلمات أو قيم الإرجاع

بعكس الأعضاء في التجميعات القياسية قد يكون أعضاء تجميع التوافق تملك أنواع بيانات التي تختلف عن تلك المستخدمة في تعريف الكائن الأصلي. على الرغم من أن تجميعات التوافق تحول ضمنيا أنواع COM إلى أنواع وقت التشغيل لغة عامة متوافقة, يجب الاهتمام بأنواع البيانات التي تستخدم على كلا الجانبين لمنع أخطاء وقت التشغيل. على سبيل المثال، في كائنات COM التي تم انشاؤها في Visual Basic 6.0 والإصدارات السابقة، القيم من نوع Integer تفترض .NET Framework الانوع المكافئ Short. من المستحسن استخدام مستعرض الكائن لفحص صفات الأعضاء المستوردة قبل استعمالها.

أساليب COM مستوى وحدة نمطية

يتم استخدام معظم كائنات COM عن طريق إنشاء مثيل من فئة COM باستخدام New الكلمة الأساسية ومن ثم استدعاء أساليب الكائن. استثناء واحد لهذه القاعدة تتضمن كائنات COM التي تحتوي على AppObj أو GlobalMultiUse فئات COM. فئات مثل هذه تشبه أساليب مستوى الوحدة النمطية في Visual Basic 2005 الفئات. Visual Basic 6.0 والإصدارات السابقة ضمنيًا تقوم بإنشاء مثيلات مثل هذه الكائنات للمرة الأولى التي قمت باستدعاء إحدى الطرق الخاصة بهم. على سبيل المثال، في Visual Basic 6.0 يمكنك إضافة مرجع إلى مكتبة كائن Microsoft DAO 3.6 ثم استدعاء DBEngine الأسلوب بدون إنشاء مثيل أولا:

Dim db As DAO.Database
' Open the database.
Set db = DBEngine.OpenDatabase("C:\nwind.mdb")
' Use the database object.

Visual Basic 2005 يتطلب إنشاء مثيلات كائنات COM دوماً قبل أن تتمكن من استخدام الأساليب الخاصة بهم. لاستخدام هذه الطرق في Visual Basic 2005، قم باعلان عن متغيّر من الفئة المطلوبة واستخدم الكلمة الأساسية الجديدة لتعيين الكائن إلى متغير كائن. Shared الكلمة الأساسية يمكن استخدامها عندما تريد أن تتأكد من إنشاء مثيل واحد فقط لتلك الفئة.

' Class level variable.
Shared DBEngine As New DAO.DBEngine

Sub DAOOpenRecordset()
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim fld As DAO.Field
    ' Open the database.
    db = DBEngine.OpenDatabase("C:\nwind.mdb")

    ' Open the Recordset.
    rst = db.OpenRecordset(
        "SELECT * FROM Customers WHERE Region = 'WA'",
        DAO.RecordsetTypeEnum.dbOpenForwardOnly,
        DAO.RecordsetOptionEnum.dbReadOnly)
    ' Print the values for the fields in the debug window.
    For Each fld In rst.Fields
        Debug.WriteLine(fld.Value.ToString & ";")
    Next
    Debug.WriteLine("")
    ' Close the Recordset.
    rst.Close()
End Sub

الأخطاء الغير معالجة في معالجات الحدث

تتضمن مشكلة إمكانية التشغيل المتداخل الشائعة الأخطاء في معالجات الحدث التي تعالج الأحداث المرفوعة من قبل كائنات COM. يتم تجاهل أخطاء مثل هذه ما لم تتأكد بشكل خاص الأخطاء باستخدام On Error أو Try...Catch...Finally الكشوف. على سبيل المثال، يكون المثال التالي من Visual Basic 2005 المشروع الذي يحوي على مرجع لكائن COM مكتبة كائنات 2.8 بيانات Microsoft ActiveX.

' To use this example, add a reference to the 
'     Microsoft ActiveX Data Objects 2.8 Library  
' from the COM tab of the project references page.
Dim WithEvents cn As New ADODB.Connection
Sub ADODBConnect()
    cn.ConnectionString =
    "Provider=Microsoft.Jet.OLEDB.4.0;" &
    "Data Source=C:\NWIND.MDB"
    cn.Open()
    MsgBox(cn.ConnectionString)
End Sub

Private Sub Form1_Load(ByVal sender As System.Object,
    ByVal e As System.EventArgs) Handles MyBase.Load

    ADODBConnect()
End Sub

Private Sub cn_ConnectComplete(
    ByVal pError As ADODB.Error,
    ByRef adStatus As ADODB.EventStatusEnum,
    ByVal pConnection As ADODB.Connection) Handles cn.ConnectComplete

    '  This is the event handler for the cn_ConnectComplete event raised 
    '  by the ADODB.Connection object when a database is opened.
    Dim x As Integer = 6
    Dim y As Integer = 0
    Try
        x = CInt(x / y) ' Attempt to divide by zero.
        ' This procedure would fail silently without exception handling.
    Catch ex As Exception
        MsgBox("There was an error: " & ex.Message)
    End Try
End Sub

يـرفع هذا المثال خطأ كما هو متوقع. ومع ذلك، إذا حاولت المثال نفسه بدون Try...Catch...Finally المقطع, يتم تجاهل الخطأ كما لو استخدمت OnError Resume Next الكشف. بدون معالجة الأخطاء, يفشل بصمت القسمة على صفر. بسبب مثل هذ الاخطاء لا ترفع أخطاء استثناء غير معالجة, من المهم استخدام بعض أشكال معالجة الاستثناء في معالجي الحدث الذي يعالج الأحداث من كائنات COM.

فهم أخطاء توافق COM

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

Try
    ' Place call to COM object here.
Catch ex As Exception
    ' Display information about the failed call.
End Try

يمكنك العثور على معلومات مثل وصف الخطأ, HRESULT, ومصدر أخطاء COM عن طريق فحص محتويات كائن ‏‏الاستثناء.

مشاكل تحكم ActiveX

معظم عناصر تحكم ActiveX التي تعمل مع Visual Basic 6.0 تعمل مع Visual Basic 2005 بدون مشكلة. الاستثناءات الرئيسية هي عناصر تحكم حاوية أو عناصر تحكم التي تحتوي على عناصر تحكم أخرى بشكل مرئي. بعض أمثلة لعناصر تحكم قديمة التي لا تعمل بشكل صحيح مع Visual Studio هي كما يلي:

  • عنصر تحكم إطار Microsoft Forms 2.0

  • التحكم لأعلى ولأسفل والتي تعرف أيضاً باسم تحكم زيادة ونقصان

  • عنصر تحكم علامة تبويب Sheridan

هناك فقط بعض الحلول لمشكلات عنصر تحكم ActiveX الغير معتمده. يمكن ترحيل عناصر التحكم الموجودة إلى Visual Studio إذا كنت تملك التعليمات البرمجية المصدر الأصلية. غير ذلك، دقق مع بائعي البرامج للحصول على إصدارات محدثة .NET المتوافقة من عناصر التحكم إلاستبدال عناصر تحكم ActiveX الغير معتمدة.

تمرير خصائص للقراءة فقط لعناصر التحكم ByRef

Visual Basic 2005 أحياناً يقوم بإصدار أخطاء COM مثل "CTL_E_SETNOTSUPPORTED 0x800A017F خطأ" عند تمرير كافة ReadOnly الخصائص لبعض عناصر تحكم ActiveX قديمة كـ ByRef المعلمات لاجراءات أخرى. استدعاءات اجراء مشابهة من Visual Basic 6.0 لا ترفع خطأ, ثم يتم التعامل مع المعلمات كما لو تم تمريرها لهم حسب القيمة. رسالة الخطأ التي تشاهدها في Visual Basic 2005 هي كائن COM الذي يرسل التقارير عن المحاولة لتغيير خاصية التي لا تحتوي على خاصية Set الإجراء.

إذا كان لديك حق الوصول إلى إجراء الذي يتم استدعاؤه, يمكنك منع هذا الخطأ باستخدام ByVal الكلمة الأساسية لاعلان المعلمات التي تقبل ReadOnly الخصائص. فعلى سبيل المثال:

Sub ProcessParams(ByVal c As Object)
    'Use the arguments here.
End Sub

إذا لم يكن لديك حق الوصول إلى التعليمات البرمجية المصدر للإجراء قيد الاستدعاء, يمكنك فرض الخاصية لتمريرها حسب القيمة بواسطة إضافة مجموعة إضافية من الأقواس حول الإجراء المستدعي. على سبيل المثال، في المشروع الذي يحوي على مرجع إلى كائن COM مكتبة ActiveX Data Objects 2.8, يمكنك استخدام:

Sub PassByVal(ByVal pError As ADODB.Error)
    ' The extra set of parentheses around the arguments
    ' forces them to be passed by value.
    ProcessParams((pError.Description))
End Sub

نشر تجميعات التي تكشف التوافق

نشر تجميعات التي تكشف واجهات COM يقدم بعض التحديات الفريدة. على سبيل المثال، تحدث مشكلة محتملة عند تشير تطبيقات منفصلة الى نفس تجميع COM. يكون هذا الموقف شائع عندما يتم تثبيت إصدار جديد من تجميع ولا يزال تطبيق آخر يستخدم الإصدار القديم من التجميع. إذا قمت بإزالة تثبيت تجميع الذي يشارك DLL يمكنك بدون قصد جعلها غير متوفرة لتجميعات أخرى.

لتجنب هذه المشكلة، يجب يثّبت التجميعات المشتركة إلى مخزن تجميع العمومي المؤقت (GAC) واستخدم MergeModule للمكون. إذا لم تتمكن من يثّبت التطبيق في GAC, يجب يثّبتها لـ CommonFilesFolder في دليل فرعي خاص الإصدار.

التجميعات التي لا يتم مشاركتها يجب أن تكون موجودة جنباً إلى جنب في الدليل مع التطبيق المستدعي.

راجع أيضًا:

المهام

الإرشادات التفصيلية: تطبيق توريث مع كائنات COM

كيفية: إضافة وحدات نمطية دمج إلى مشروع النشر

المرجع

MarshalAsAttribute

Tlbimp.exe (مستورد مكتبة الأنواع)

Tlbexp.exe (مُصدّر مكتبة الأنواع)

يرث الكشف

المبادئ

ذاكرة التخزين المؤقتة للتجميع العمومي

موارد أخرى

توافق COM