Együttműködési hibák elhárítása (Visual Basic)
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 merülhet fel.
Interop Marshalling
Időnként előfordulhat, hogy olyan adattípusokat kell használnia, amelyek nem részei a .NET-keretrendszer. Az interop szerelvények kezelik a COM-objektumok legtöbb munkáját, de előfordulhat, hogy szabályoznia kell a felügyelt objektumok COM-nak való közzétételekor használt adattípusokat. Az osztálytárak struktúráinak például meg kell adniuk a nem felügyelt típust a BStr
Visual Basic 6.0-s és korábbi verziói á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 felügyelt 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 null értékű megszakítási karakter nélkül. A más nyelvekkel való kompatibilitás érdekében a Visual Basic .NET sztringek exportálásakor egy leállítási karaktert tartalmaz. Ennek az inkompatibilitásnak a legjobb megoldásához exportálja azokat a sztringeket, amelyekből hiányzik a végződés karaktere a vagy Char
a tömbjekéntByte
.
Öröklési hierarchiák exportálása
A felügyelt osztályhierarchiák elsimulnak, ha COM-objektumként vannak elérhetővé téve. Ha például egy taggal rendelkező alaposztályt határoz meg, 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 az alaposztály példányaiként érhetők el COM-objektumokból, majd csak akkor, ha az alaposztály COM-objektumként is létrejön.
Többszörös szerepű 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 van elérhetővé téve, a rendszer új metódusneveket hoz létre a túlterhelt metódusokhoz.
Vegyük például azt az osztályt, amelynek a metódus két túlterhelése Synch
van. Ha a osztály COM-objektumként van elérhetővé téve, az új létrehozott metódusnevek lehetnek Synch
és Synch_2
.
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 el 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 COM-objektumként elérhetővé válik objektumok fejlesztésekor.
COM-objektumok használata interop szerelvényeken keresztül
Az interop szerelvényeket szinte úgy használja, mintha felügyelt kódcserék lennének az általuk képviselt COM-objektumokhoz. Mivel azonban burkolók, és nem tényleges COM-objektumok, van néhány különbség az interop szerelvények és a standard szerelvények használata között. A különbség ezen területei közé tartozik az osztályok kitettsége, valamint a paraméterek és a visszaadott értékek adattípusa.
Interfészként és osztályként is elérhető osztályok
A szabványos szerelvények osztályaitól eltérően a COM-osztályok interop szerelvényekben vannak elérhetővé téve interfészként és a COM osztályt képviselő osztályként is. 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 az "Osztály" szó hozzá van fűzve. 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 nevű MyComClass
felületet és egy nevű MyComClassClass
osztályt jelenít meg.
.NET-keretrendszer osztály példányainak létrehozása
Általában egy .NET-keretrendszer osztály egy példányát hozza létre az New
osztálynévvel rendelkező utasítással. Az interop szerelvény által jelölt COM-osztály az egyetlen eset, amelyben az New
utasítást egy illesztővel használhatja. Hacsak nem a COM osztályt használja utasítással Inherits
, ugyanúgy használhatja a felületet, mint egy osztályt. Az alábbi kód bemutatja, hogyan hozhat létre Command
olyan objektumot egy 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, akkor a COM osztályt képviselő interop osztályt kell használnia, az alábbi kódban leírtak szerint:
Class DerivedCommand
Inherits ADODB.CommandClass
End Class
Megjegyzés
Az interop szerelvények implicit módon implementálják a COM-osztályokat képviselő interfészeket. Ne próbálja meg az utasítást Implements
használni ezen felületek implementálásához, mert a hibaüzenetet kapja.
Paraméterek és visszatérési értékek adattípusai
A szabványos szerelvények tagjaitól eltérően 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 figyelni azokat az adattípusokat, amelyeket mindkét oldal használ a futásidejű hibák megelőzése érdekében. A Visual Basic 6.0-s és korábbi verzióiban létrehozott COM-objektumokban például a típusértékek Integer
a .NET-keretrendszer egyenértékű típust feltételezik. 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 úgy használja a rendszer, hogy létrehoz egy COM-osztálypéldányt a New
kulcsszóval, majd meghívja az objektum metódusait. A szabály alól kivételt képeznek azok a COM-objektumok, amelyek vagy GlobalMultiUse
COM-osztályokat tartalmaznakAppObj
. 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 a 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 együttműködési probléma a COM-objektumok által kiváltott eseményeket kezelő eseménykezelők hibáit érinti. Az ilyen hibák figyelmen kívül lesznek hagyva, kivéve, ha kifejezetten a vagy Try...Catch...Finally
utasításokkal On Error
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 =
"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
Ez a példa a várt módon jelez hibát. Ha azonban a blokk nélkül próbálja meg ugyanazt a Try...Catch...Finally
példát, a rendszer figyelmen kívül hagyja a hibát, mintha a utasítást OnError Resume Next
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 eredményeznek, amelyek kevés információt nyújtanak. Amikor csak lehetséges, használjon strukturált hibakezelést, hogy több információt nyújtson 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ál, mint a hiba leírása, a HRESULT és a COM-hibák forrása.
ActiveX-vezérléssel kapcsolatos problémák
A Visual Basic 6.0-val működő ActiveX-vezérlők többsége probléma nélkül együttműködik a Visual Basic .NET-tel. A fő kivételek a tárolóvezérlők, vagy a más 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 Keret vezérlőelem
Up-Down vezérlő, más néven a spin vezérlőelem
Sheridan Tab Control
Csak néhány kerülő megoldás létezik a nem támogatott ActiveX-vezérlési problémákra. Az eredeti forráskód birtokában meglévő vezérlőket migrálhat a Visual Studióba. Ellenkező esetben a szoftvergyártóknál érdeklődhet a frissítésről. A nem támogatott ActiveX-vezérlők lecseréléséhez a vezérlők NET-kompatibilis verziói.
A Vezérlők ByRef olvasási tulajdonságainak átadása
A Visual Basic .NET időnként COM-hibákat (például "Hiba 0x800A017F CTL_E_SETNOTSUPPORTED" okoz, amikor bizonyos régebbi ActiveX-vezérlők tulajdonságait paraméterekként ByRef
adja át ReadOnly
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üzenete azt jelzi, hogy olyan tulajdonságot próbál módosítani, amely nem rendelkezik tulajdonságeljárással Set
.
Ha rendelkezik hozzáféréssel a meghívandó eljáráshoz, ezt a hibát megakadályozhatja, ha a kulcsszóval deklarálja a ByVal
tulajdonságokat elfogadó ReadOnly
paramétereket. 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 szögletes zárójelek hozzáadásával a hívási eljárás köré. Egy olyan projektben például, amely a Microsoft ActiveX Data Objects 2.8 Library COM objektumra hivatkozik, a következőket 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-t közzétesző szerelvények üzembe helyezése
A COM-felületeket elérhetővé tevő szerelvények üzembe helyezése egyedi kihívásokat jelent. Lehetséges probléma például akkor fordul elő, 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 használó szerelvényt, akaratlanul elérhetetlenné teheti azt a többi szerelvény 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 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 CommonFilesFolder mappába.
A nem megosztott szerelvényeknek egymás mellett kell lenniük a címtárban a hívó alkalmazással.
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: