Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Amikor együttműködik a COM és a .NET-keretrendszer felügyelt kódja között, az alábbi gyakori problémák közül egy vagy több is felmerülhet.
Interop Marshalling
Időnként előfordulhat, hogy olyan adattípusokat kell használnia, amelyek nem részei a .NET-keretrendszernek. Az interop szerelvények kezelik a COM-objektumok legtöbb munkáját, de előfordulhat, hogy szabályoznia kell azokat az adattípusokat, amelyeket akkor használnak, amikor a felügyelt objektumok elérhetővé válnak a COM számára. Az osztálytárak struktúráinak például meg kell adniuk a BStr nem felügyelt típust a Visual Basic 6.0 és a korábbi verziók által létrehozott COM-objektumoknak küldött sztringeken. Ilyen esetekben a MarshalAsAttribute attribútum használatával a felügyelt típusok nem felügyelt típusokként lesznek közzétéve.
Fixed-Length sztringek exportálása nem kezelt kódba
A Visual Basic 6.0-s és korábbi verzióiban a sztringeket a rendszer bájtok sorozataként exportálja a COM-objektumokba nullmegszüntetési karakter nélkül. A más nyelvekkel való kompatibilitás érdekében a Visual Basic .NET sztringek exportálásakor egy végződési karaktert tartalmaz. Ennek az inkompatibilitásnak a kezelésére a legjobb megoldás az olyan sztringek exportálása, amelyek nem rendelkeznek végjel karakterrel, Byte vagy Chartömbként.
Öröklési hierarchiák exportálása
COM-objektumként való expozíció során a felügyelt osztályhierarchiák laposak lesznek. Ha például egy taggal együtt definiál egy alaposztályt, majd egy COM-objektumként közzétett származtatott osztályban örökli az alaposztályt, a COM-objektum származtatott osztályát használó ügyfelek nem fogják tudni használni az örökölt tagokat. Az alaposztálytagok csak alaposztály példányaiként érhetők el COM-objektumokból, és csak akkor, ha az alaposztály COM-objektumként is létrejön.
Túlterhelt metódusok
Bár a Visual Basic használatával túlterhelt metódusokat is létrehozhat, a COM nem támogatja őket. Ha egy túlterhelt metódusokat tartalmazó osztály COM-objektumként jelenik meg, a rendszer új metódusneveket hoz létre a túlterhelt metódusokhoz.
Vegyük például azt az osztályt, amelynek két túlterhelése van a Synch metódusnak. Amikor az osztály COM-objektumként van közzétéve, az új létrehozott metódusnevek Synch és Synch_2lehetnek.
Az átnevezés két problémát okozhat a COM-objektum felhasználói számára.
Előfordulhat, hogy az ügyfelek nem várják a létrehozott metódusneveket.
A COM-objektumként közzétett osztályban létrehozott metódusnevek megváltozhatnak, ha új túlterheléseket adnak hozzá az osztályhoz vagy annak alaposztályához. Ez verziószámozási problémákat okozhat.
Mindkét probléma megoldásához adjon minden metódusnak egyedi nevet a túlterhelés használata helyett, amikor az objektumokat COM-objektumként tesszük elérhetővé.
COM-objektumok használata interop szerelvényeken keresztül
Az interop szerelvényeket szinte úgy használja, mintha azok felügyelt kódként helyettesítenék az általuk képviselt COM-objektumokat. Az interop összetevők és a standard összetevők használata között néhány különbség tapasztalható, mivel azonban burkolók, és nem tényleges COM-objektumok. A különbség ezen területei közé tartozik az osztályok expozíciója, valamint a paraméterek adattípusai és a visszaadott értékek.
Felületekként és osztályokként egyaránt kifejtett osztályok
A szabványos szerelvények osztályaival ellentétben a COM-osztályok interop szerelvényekben is elérhetők, mind interfészként, mind pedig a COM-osztályt képviselő osztályként. A felület neve megegyezik a COM-osztály nevével. Az interop osztály neve megegyezik az eredeti COM-osztály nevével, de hozzá van fűzve az "Osztály" szó. Tegyük fel például, hogy van egy projektje, amely egy COM-objektum interop szerelvényére hivatkozik. Ha a COM osztály neve MyComClass, az IntelliSense és az Object Browser egy MyComClass nevű felületet és egy MyComClassClassnevű osztályt jelenít meg.
.NET-keretrendszerosztály példányainak létrehozása
Általában egy .NET-keretrendszerosztály egy példányát hozza létre a New utasítással egy osztálynévvel. Ha egy COM osztályt egy interop-összeállítás képvisel, akkor ez az egyetlen eset, amikor a New utasítást használhatja egy interfésszel. Hacsak nem Inherits utasítással használja a COM osztályt, ugyanúgy használhatja a felületet, mint egy osztályt. Az alábbi kód bemutatja, hogyan hozhat létre Command objektumot egy olyan projektben, amely a Microsoft ActiveX Data Objects 2.8 Library COM objektumra hivatkozik:
Dim cmd As New ADODB.Command
Ha azonban a COM osztályt használja egy származtatott osztály alapjaként, a COM osztályt képviselő interop osztályt kell használnia, ahogyan az alábbi kódban is látható:
Class DerivedCommand
Inherits ADODB.CommandClass
End Class
Jegyzet
Az interop szerelvények implicit módon implementálják a COM-osztályokat képviselő interfészeket. Ne próbálja meg használni a Implements utasítást ezeknek az interfészeknek a implementálásához, vagy hiba fog következni.
Paraméterek és visszatérési értékek adattípusai
A szabványos szerelvények tagjaival ellentétben az interop szerelvény tagjai olyan adattípusokkal rendelkezhetnek, amelyek eltérnek az eredeti objektumdeklarációban használt adatoktól. Bár az interop szerelvények implicit módon konvertálják a COM-típusokat kompatibilis közös nyelvi futtatókörnyezet-típusokká, érdemes figyelnie azokat az adattípusokat, amelyeket mindkét fél használ a futásidejű hibák megelőzése érdekében. Például a Visual Basic 6.0 és korábbi verzióiban létrehozott COM-objektumokban a Integer típus értékek felveszik a .NET-keretrendszer egyenértékű típusát, Short. Javasoljuk, hogy a használat előtt az Object Browser használatával vizsgálja meg az importált tagok jellemzőit.
Modulszintű COM-metódusok
A legtöbb COM-objektumot egy COM-osztály egy példányának létrehozásával, az New kulcsszó használatával, majd az objektum metódusainak meghívásával lehet használni. A szabály alól kivételt képeznek az olyan COM-objektumok, amelyek AppObj vagy GlobalMultiUse COM-osztályokat tartalmaznak. Az ilyen osztályok a Visual Basic .NET-osztályok modulszintű metódusaihoz hasonlítanak. A Visual Basic 6.0-s és korábbi verziói implicit módon létrehozzák az ilyen objektumok példányait, amikor először hívja meg az egyik metódusukat. A Visual Basic 6.0-ban például hozzáadhat egy hivatkozást a Microsoft DAO 3.6 objektumtárhoz, és meghívhatja a DBEngine metódust példány létrehozása nélkül:
Dim db As DAO.Database
' Open the database.
Set db = DBEngine.OpenDatabase("C:\nwind.mdb")
' Use the database object.
A Visual Basic .NET használatához mindig létre kell hoznia COM-objektumok példányait. Ha ezeket a metódusokat a Visual Basicben szeretné használni, deklaráljon egy változót a kívánt osztályból, és az új kulcsszóval rendelje hozzá az objektumot az objektumváltozóhoz. A Shared kulcsszó akkor használható, ha meg szeretné győződni arról, hogy az osztálynak csak egy példánya van létrehozva.
' 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
Nem kezelt hibák az eseménykezelőkben
Az egyik gyakori interop-probléma a COM-objektumok által kiváltott eseményeket kezelő eseménykezelők hibáit foglalja magában. Az ilyen hibák figyelmen kívül lesznek hagyva, kivéve, ha kifejezetten On Error vagy Try...Catch...Finally utasítások használatával keres hibákat. Az alábbi példa például egy Visual Basic .NET-projektből származik, amely a Microsoft ActiveX Data Objects 2.8 Library COM objektumra hivatkozik.
' 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 = "..."
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
Ez a példa a várt módon jelez hibát. Ha azonban ugyanazt a példát próbálja ki a Try...Catch...Finally blokk nélkül, a rendszer figyelmen kívül hagyja a hibát, mintha a OnError Resume Next utasítást használta volna. Hibakezelés nélkül a nulladik osztás csendesen meghiúsul. Mivel az ilyen hibák soha nem okoznak kezeletlen kivételhibákat, fontos, hogy valamilyen kivételkezelést használjon a COM-objektumok eseményeit kezelő eseménykezelőkben.
A COM-együttműködés hibáinak ismertetése
Hibakezelés nélkül az interop-hívások gyakran olyan hibákat okoznak, amelyek kevés információt adnak meg. Amikor csak lehetséges, strukturált hibakezeléssel további információt kaphat a felmerülő problémákról. Ez különösen hasznos lehet az alkalmazások hibakeresése során. Például:
Try
' Place call to COM object here.
Catch ex As Exception
' Display information about the failed call.
End Try
A kivételobjektum tartalmának vizsgálatával olyan információkat találhat, mint a hiba leírása, a HRESULT és a COM-hibák forrása.
ActiveX-vezérlési problémák
A Visual Basic 6.0-val működő ActiveX-vezérlők többsége probléma nélkül használhatja a Visual Basic .NET-et. A fő kivételek a tárolóvezérlők, vagy az egyéb vezérlőket vizuálisan tartalmazó vezérlők. Néhány példa a Visual Studióval nem megfelelően működő régebbi vezérlőkre:
Microsoft Forms 2.0 Keretvezérlő
Up-Down vezérlő, más néven spin vezérlő
Sheridan Fülkezelő
Csak néhány kerülő megoldás létezik a nem támogatott ActiveX-vezérlési problémákra. A meglévő vezérlőket migrálhatja a Visual Studióba, ha ön az eredeti forráskód tulajdonosa. Ellenkező esetben ellenőrizheti a szoftvergyártóknál, hogy vannak-e frissített, .NET-kompatibilis verziók a vezérlőkből, amelyekkel lecserélheti a nem támogatott ActiveX-vezérlőket.
A vezérlők csak olvasható tulajdonságainak ByRef átadása
A Visual Basic néha COM-hibákat , például "Hiba 0x800A017F CTL_E_SETNOTSUPPORTED" okoz, amikor bizonyos régebbi ActiveX-vezérlők ReadOnly tulajdonságait adja át paraméterekként ByRef más eljárásoknak. A Visual Basic 6.0 hasonló eljáráshívásai nem okoznak hibát, és a paramétereket úgy kezeli a rendszer, mintha érték alapján adta volna át őket. A Visual Basic .NET hibaüzenet azt jelzi, hogy olyan tulajdonságot próbál módosítani, amely nem rendelkezik tulajdonság Set eljárással.
Ha hozzáféréssel rendelkezik a meghívandó eljáráshoz, megakadályozhatja ezt a hibát a ByVal kulcsszóval olyan paraméterek deklarálásához, amelyek elfogadják ReadOnly tulajdonságokat. Például:
Sub ProcessParams(ByVal c As Object)
'Use the arguments here.
End Sub
Ha nem fér hozzá a meghívandó eljárás forráskódjaihoz, kényszerítheti a tulajdonság érték szerinti átadását egy további zárójelek hozzáadásával a hívási eljáráshoz. Például egy olyan projektben, amely a Microsoft ActiveX Data Objects 2.8 Library COM objektumra hivatkozik, a következőt használhatja:
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
Interop-ot közzétévő szerelvények telepítése
A COM-interfészeket elérhetővé tevő szerelvények üzembe helyezése egyedi kihívásokat jelent. Lehetséges probléma például akkor jelentkezik, ha a különálló alkalmazások ugyanarra a COM-szerelvényre hivatkoznak. Ez a helyzet akkor gyakori, ha egy szerelvény új verziója van telepítve, és egy másik alkalmazás továbbra is a szerelvény régi verzióját használja. Ha eltávolít egy DLL-t tartalmazó szerelvényt, véletlenül elérhetetlenné teheti azt a többi szerelvények számára.
A probléma elkerülése érdekében telepítse a megosztott szerelvényeket a globális szerelvény-gyorsítótárba (GAC), és használjon egy MergeModule-t az összetevőhöz. Ha nem tudja telepíteni az alkalmazást a GAC-ban, azt egy verzióspecifikus alkönyvtárban kell telepíteni a CommonFilesFolderbe.
A nem megosztott szerelvényeknek egymás mellett kell lenniük a címtárban a hívó alkalmazással.