Risoluzione dei problemi relativi all'interoperabilità (Visual Basic)Troubleshooting Interoperability (Visual Basic)

Durante l'interazione tra COM e il codice gestito di .NET Framework, è possibile riscontrare uno o più dei seguenti problemi comuni.When you interoperate between COM and the managed code of the .NET Framework, you may encounter one or more of the following common issues.

Marshalling di interoperabilitàInterop Marshaling

In alcuni casi, è possibile usare i tipi di dati che non fanno parte di .NET Framework.At times, you may have to use data types that are not part of the .NET Framework. Assembly di interoperabilità di gestire la maggior parte del lavoro per gli oggetti COM, ma potrebbe essere necessario controllare i tipi di dati che vengono usati quando gli oggetti gestiti sono esposti a COM.Interop assemblies handle most of the work for COM objects, but you may have to control the data types that are used when managed objects are exposed to COM. Ad esempio, è necessario specificare le strutture nelle librerie di classi di BStr tipo nelle stringhe inviate agli oggetti COM creati da Visual Basic 6.0 e versioni precedenti non gestito.For example, structures in class libraries must specify the BStr unmanaged type on strings sent to COM objects created by Visual Basic 6.0 and earlier versions. In questi casi, è possibile usare il MarshalAsAttribute attributo in modo tipi gestiti da esporre come tipi non gestiti.In such cases, you can use the MarshalAsAttribute attribute to cause managed types to be exposed as unmanaged types.

Esportazione delle stringhe a lunghezza fissa a codice non gestitoExporting Fixed-Length Strings to Unmanaged Code

In Visual Basic 6.0 e versioni precedenti, le stringhe vengono esportate a oggetti COM come sequenze di byte senza un carattere di terminazione null.In Visual Basic 6.0 and earlier versions, strings are exported to COM objects as sequences of bytes without a null termination character. Per garantire la compatibilità con altri linguaggi, Visual Basic .NET include un carattere di terminazione quando si esportano le stringhe.For compatibility with other languages, Visual Basic .NET includes a termination character when exporting strings. Il modo migliore per risolvere i problemi di compatibilità consiste nell'esportare che non dispongono di carattere di terminazione come matrici di stringhe Byte o Char.The best way to address this incompatibility is to export strings that lack the termination character as arrays of Byte or Char.

Esportazione delle gerarchie di ereditarietàExporting Inheritance Hierarchies

Classe gerarchie spianare quando esposte come oggetti COM gestita.Managed class hierarchies flatten out when exposed as COM objects. Ad esempio, se si definisce una classe di base con un membro e quindi eredita la classe di base in una classe derivata che viene esposta come oggetto COM, i client che usano la classe derivata dell'oggetto COM non sarà in grado di usare i membri ereditati.For example, if you define a base class with a member, and then inherit the base class in a derived class that is exposed as a COM object, clients that use the derived class in the COM object will not be able to use the inherited members. I membri di classe di base sono accessibili dagli oggetti COM soltanto come istanze di una classe di base e quindi solo se la classe di base viene anche creata come oggetto COM.Base class members can be accessed from COM objects only as instances of a base class, and then only if the base class is also created as a COM object.

Metodi di overloadOverloaded Methods

Sebbene sia possibile creare metodi di overload con Visual Basic, questi non sono supportati da COM.Although you can create overloaded methods with Visual Basic, they are not supported by COM. Quando una classe che contiene i metodi di overload è esposta come oggetto COM, i nuovi nomi di metodo vengono generati per i metodi di overload.When a class that contains overloaded methods is exposed as a COM object, new method names are generated for the overloaded methods.

Ad esempio, si consideri una classe che ha due overload del Synch (metodo).For example, consider a class that has two overloads of the Synch method. Quando la classe viene esposta come oggetto COM, i nuovi nomi di metodo generato potrebbe rappresentare Synch e Synch_2.When the class is exposed as a COM object, the new generated method names could be Synch and Synch_2.

La ridenominazione può causare due problemi per i consumer dell'oggetto COM.The renaming can cause two problems for consumers of the COM object.

  1. I client potrebbero non prevedere i nomi di metodo generato.Clients might not expect the generated method names.

  2. I nomi di metodo generato nella classe esposta come oggetto COM possono cambiare quando vengono aggiunti nuovi overload per la classe o la relativa classe base.The generated method names in the class exposed as a COM object can change when new overloads are added to the class or its base class. Ciò può provocare problemi di controllo delle versioni.This can cause versioning problems.

Per risolvere entrambi i problemi, assegnare ogni metodo un nome univoco, invece di usare l'overload, quando si sviluppano oggetti che saranno esposti come oggetti COM.To solve both problems, give each method a unique name, instead of using overloading, when you develop objects that will be exposed as COM objects.

Uso di oggetti COM mediante assembly di interoperabilitàUse of COM Objects Through Interop Assemblies

Si usano assembly di interoperabilità quasi come se fossero in sostituzione di codice gestito per gli oggetti COM che rappresentano.You use interop assemblies almost as if they are managed code replacements for the COM objects they represent. Tuttavia, poiché sono wrapper e gli oggetti COM non effettivi, esistono alcune differenze tra l'uso di assembly di interoperabilità e assembly standard.However, because they are wrappers and not actual COM objects, there are some differences between using interop assemblies and standard assemblies. Le differenze includono l'esposizione di classi e tipi di dati per i parametri e valori restituiti.These areas of difference include the exposure of classes, and data types for parameters and return values.

Le classi esposte come entrambe le interfacce e classiClasses Exposed as Both Interfaces and Classes

A differenza delle classi negli assembly standard, le classi COM vengono esposte nell'assembly di interoperabilità come un'interfaccia sia una classe che rappresenta la classe COM.Unlike classes in standard assemblies, COM classes are exposed in interop assemblies as both an interface and a class that represents the COM class. Nome dell'interfaccia è identico a quella della classe COM.The interface's name is identical to that of the COM class. Il nome della classe di interoperabilità è uguale a quello della classe COM originale, ma con la parola "Class" aggiunto.The name of the interop class is the same as that of the original COM class, but with the word "Class" appended. Si supponga, ad esempio, che si dispone di un progetto con un riferimento a un assembly di interoperabilità per un oggetto COM.For example, suppose you have a project with a reference to an interop assembly for a COM object. Se la classe COM è denominata MyComClass, IntelliSense e il Visualizzatore Mostra un'interfaccia denominata MyComClass e una classe denominata MyComClassClass.If the COM class is named MyComClass, IntelliSense and the Object Browser show an interface named MyComClass and a class named MyComClassClass.

Creazione di istanze di classi .NET FrameworkCreating Instances of a .NET Framework Class

In genere, si crea un'istanza di una classe .NET Framework utilizzando il New istruzione con un nome di classe.Generally, you create an instance of a .NET Framework class using the New statement with a class name. Quando una classe COM rappresentata da un assembly di interoperabilità è un caso in cui è possibile usare il New istruzione con un'interfaccia.Having a COM class represented by an interop assembly is the one case in which you can use the New statement with an interface. A meno che non si usa la classe COM con un Inherits istruzione, è possibile usare l'interfaccia esattamente come se fosse una classe.Unless you are using the COM class with an Inherits statement, you can use the interface just as you would a class. Il codice seguente viene illustrato come creare un Command oggetto in un progetto che contiene un riferimento all'oggetto Microsoft ActiveX Data oggetti 2.8 libreria COM:The following code demonstrates how to create a Command object in a project that has a reference to the Microsoft ActiveX Data Objects 2.8 Library COM object:

Dim cmd As New ADODB.Command

Tuttavia, se si usa la classe COM come base per una classe derivata, è necessario utilizzare la classe di interoperabilità che rappresenta la classe COM, come nel codice seguente:However, if you are using the COM class as the base for a derived class, you must use the interop class that represents the COM class, as in the following code:

Class DerivedCommand
    Inherits ADODB.CommandClass
End Class

Nota

Assembly di interoperabilità in modo implicito implementano interfacce che rappresentano le classi COM.Interop assemblies implicitly implement interfaces that represent COM classes. È consigliabile non usare il Implements determinerà l'istruzione per implementare queste interfacce o un errore.You should not try to use the Implements statement to implement these interfaces or an error will result.

Tipi di dati per i parametri e valori restituitiData Types for Parameters and Return Values

A differenza dei membri dell'assembly standard, i membri di assembly di interoperabilità abbia i tipi di dati che differiscono da quelli utilizzati nella dichiarazione dell'oggetto originale.Unlike members of standard assemblies, interop assembly members may have data types that differ from those used in the original object declaration. Anche se gli assembly di interoperabilità convertono implicita dei tipi COM per tipi di common language runtime compatibile, è necessario prestare attenzione ai tipi di dati che vengono usate per entrambi i lati per evitare errori di runtime.Although interop assemblies implicitly convert COM types to compatible common language runtime types, you should pay attention to the data types that are used by both sides to prevent runtime errors. Ad esempio, negli oggetti COM creati in Visual Basic 6.0 e versioni precedenti, i valori di tipo Integer presupporre il tipo equivalente di .NET Framework, Short.For example, in COM objects created in Visual Basic 6.0 and earlier versions, values of type Integer assume the .NET Framework equivalent type, Short. È consigliabile utilizzare il Visualizzatore oggetti per esaminare le caratteristiche dei membri importati prima di usarli.It is recommended that you use the Object Browser to examine the characteristics of imported members before you use them.

Metodi COM a livello di moduloModule level COM methods

Vengono utilizzati quasi tutti gli oggetti COM mediante la creazione di un'istanza di una classe COM mediante la New (parola chiave) e quindi chiamando i metodi dell'oggetto.Most COM objects are used by creating an instance of a COM class using the New keyword and then calling methods of the object. Un'eccezione a questa regola riguarda gli oggetti COM che contengono AppObj o GlobalMultiUse classi COM.One exception to this rule involves COM objects that contain AppObj or GlobalMultiUse COM classes. Tali classi sono simili a metodi a livello di modulo in classi Visual Basic .NET.Such classes resemble module level methods in Visual Basic .NET classes. Visual Basic 6.0 e versioni precedenti in modo implicito creano istanze di tali oggetti è la prima volta che viene chiamato uno dei relativi metodi.Visual Basic 6.0 and earlier versions implicitly create instances of such objects for you the first time that you call one of their methods. In Visual Basic 6.0, ad esempio, è possibile aggiungere un riferimento per la libreria di oggetti 3.6 DAO e chiamare il DBEngine metodo senza dover prima creare un'istanza:For example, in Visual Basic 6.0 you can add a reference to the Microsoft DAO 3.6 Object Library and call the DBEngine method without first creating an instance:

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

Visual Basic .NET è necessario creare istanze degli oggetti COM sempre prima di poter usare i relativi metodi.Visual Basic .NET requires that you always create instances of COM objects before you can use their methods. Per usare questi metodi in Visual Basic, dichiarare una variabile della classe desiderata e usare la parola chiave new per assegnare l'oggetto alla variabile di oggetto.To use these methods in Visual Basic, declare a variable of the desired class and use the new keyword to assign the object to the object variable. Il Shared parola chiave può essere utilizzata quando si desidera assicurarsi che viene creata solo un'istanza della classe.The Shared keyword can be used when you want to make sure that only one instance of the class is created.

' 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

Errori non gestiti nei gestori eventiUnhandled Errors in Event Handlers

Un problema comune che interoperabilità comporta errori nei gestori di eventi che gestiscono gli eventi generati dagli oggetti COM.One common interop problem involves errors in event handlers that handle events raised by COM objects. Tali errori vengono ignorati a meno che non un controllo specifico per gli errori usando On Error o Try...Catch...Finally istruzioni.Such errors are ignored unless you specifically check for errors using On Error or Try...Catch...Finally statements. Nell'esempio seguente viene ad esempio, da un progetto di Visual Basic .NET che presenta un riferimento all'oggetto Microsoft ActiveX Data oggetti 2.8 libreria COM.For example, the following example is from a Visual Basic .NET project that has a reference to the Microsoft ActiveX Data Objects 2.8 Library COM object.

' 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

In questo esempio genera un errore nel modo previsto.This example raises an error as expected. Tuttavia, se si prova lo stesso esempio senza il Try...Catch...Finally blocco, l'errore viene ignorato perché se è stato usato il OnError Resume Next istruzione.However, if you try the same example without the Try...Catch...Finally block, the error is ignored as if you used the OnError Resume Next statement. Senza la gestione degli errori di divisione per zero non riuscirà automaticamente.Without error handling, the division by zero silently fails. Poiché tali errori non generano mai gli errori di eccezione non gestita, è importante usare qualche forma di gestione delle eccezioni in gestori di eventi che gestiscono gli eventi dagli oggetti COM.Because such errors never raise unhandled exception errors, it is important that you use some form of exception handling in event handlers that handle events from COM objects.

Informazioni sugli errori di interoperabilità COMUnderstanding COM interop errors

Senza la gestione degli errori, le chiamate di interoperabilità generano spesso errori che forniscono informazioni limitate.Without error handling, interop calls often generate errors that provide little information. Se possibile, utilizzare gestione per fornire ulteriori informazioni sui problemi quando si verificano errori strutturata.Whenever possible, use structured error handling to provide more information about problems when they occur. Ciò può essere particolarmente utile quando si esegue il debug delle applicazioni.This can be especially helpful when you debug applications. Ad esempio:For example:

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

È possibile trovare informazioni quali l'origine degli errori COM, HRESULT e la descrizione dell'errore esaminando il contenuto dell'oggetto eccezione.You can find information such as the error description, HRESULT, and the source of COM errors by examining the contents of the exception object.

Problemi relativi al controllo ActiveXActiveX Control Issues

La maggior parte dei controlli ActiveX che funzionano con Visual Basic 6.0 funzionano con Visual Basic .NET senza problemi.Most ActiveX controls that work with Visual Basic 6.0 work with Visual Basic .NET without trouble. Le principali eccezioni sono controlli contenitore, o controlli visivamente contenenti altri controlli.The main exceptions are container controls, or controls that visually contain other controls. Alcuni esempi di controlli precedenti che non funzionano correttamente con Visual Studio sono come segue:Some examples of older controls that do not work correctly with Visual Studio are as follows:

  • Controllo di Microsoft Forms 2.0 FrameMicrosoft Forms 2.0 Frame control

  • Controllo di scorrimento, noto anche come il controllo di selezioneUp-Down control, also known as the spin control

  • Schede SheridanSheridan Tab Control

Sono disponibili solo alcune soluzioni alternative per problemi di controlli ActiveX non supportati.There are only a few workarounds for unsupported ActiveX control problems. Se si è proprietari del codice sorgente originale, è possibile migrare i controlli esistenti a Visual Studio.You can migrate existing controls to Visual Studio if you own the original source code. In caso contrario, è possibile controllare con fornitori di software per l'aggiornamento. Le versioni compatibili di NET dei controlli da sostituire non supportati controlli ActiveX.Otherwise, you can check with software vendors for updated .NET-compatible versions of controls to replace unsupported ActiveX controls.

Passaggio delle proprietà di sola lettura ByRef typu ByRef controlliPassing ReadOnly Properties of Controls ByRef

Visual Basic .NET a volte genera errori COM, ad esempio, "Errore 0x800A017F CTL_E_SETNOTSUPPORTED", quando si passano ReadOnly delle proprietà di alcuni controlli ActiveX precedente come ByRef parametri alle altre procedure.Visual Basic .NET sometimes raises COM errors such as, "Error 0x800A017F CTL_E_SETNOTSUPPORTED", when you pass ReadOnly properties of some older ActiveX controls as ByRef parameters to other procedures. Chiamate di procedure simili da Visual Basic 6.0 non generano un errore e i parametri vengono considerati come se li si passati per valore.Similar procedure calls from Visual Basic 6.0 do not raise an error, and the parameters are treated as if you passed them by value. Il messaggio di errore di Visual Basic .NET indica che si sta tentando di modificare una proprietà che non dispone di una proprietà Set procedure.The Visual Basic .NET error message indicates that you are trying to change a property that does not have a property Set procedure.

Se si ha accesso per la routine chiamata, è possibile impedire questo errore tramite il ByVal parola chiave per dichiarare i parametri che accettano ReadOnly proprietà.If you have access to the procedure being called, you can prevent this error by using the ByVal keyword to declare parameters that accept ReadOnly properties. Ad esempio:For example:

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

Se non si ha accesso al codice sorgente per la routine chiamata, è possibile forzare la proprietà può essere passato per valore mediante l'aggiunta di un set aggiuntivo di parentesi quadre intorno alla routine chiamante.If you do not have access to the source code for the procedure being called, you can force the property to be passed by value by adding an extra set of brackets around the calling procedure. Ad esempio, in un progetto che contiene un riferimento all'oggetto COM della libreria di Microsoft ActiveX Data oggetti 2.8, è possibile usare:For example, in a project that has a reference to the Microsoft ActiveX Data Objects 2.8 Library COM object, you can use:

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

Distribuzione di assembly che espongono l'interoperabilitàDeploying Assemblies That Expose Interop

Distribuzione di assembly che espongono interfacce COM presenta alcune sfide univoche.Deploying assemblies that expose COM interfaces presents some unique challenges. Ad esempio, un potenziale problema si verifica quando applicazioni separate che fa riferimento allo stesso assembly COM.For example, a potential problem occurs when separate applications reference the same COM assembly. Questa situazione è comune quando si installa una nuova versione di un assembly e un'altra applicazione utilizza ancora la versione precedente dell'assembly.This situation is common when a new version of an assembly is installed and another application is still using the old version of the assembly. Se si disinstalla un assembly che condivide una DLL, è possibile involontariamente renderlo disponibile per gli altri assembly.If you uninstall an assembly that shares a DLL, you can unintentionally make it unavailable to the other assemblies.

Per evitare questo problema, è necessario installare gli assembly condivisi alla Global Assembly Cache (GAC) e usare un MergeModule per il componente.To avoid this problem, you should install shared assemblies to the Global Assembly Cache (GAC) and use a MergeModule for the component. Se non è possibile installare l'applicazione nella Global Assembly Cache, questo servizio deve essere installato in CommonFilesFolder in una sottodirectory specifica della versione.If you cannot install the application in the GAC, it should be installed to CommonFilesFolder in a version-specific subdirectory.

Gli assembly che non sono condivisi devono trovarsi side-by-side nella stessa directory dell'applicazione chiamante.Assemblies that are not shared should be located side by side in the directory with the calling application.

Vedere ancheSee also