Buongiorno a tutti
Riesumo questa discussione perchè sto letteralmente impazzendo...
Ho una applicazione VB.NET 2005 "Server" che passa dei dati ad una applicazione Client.
L'applicazione Client può essere un'applicazione VB ed ho bisogno quindi di creare un oggetto COM.
Le strutture passate sulla rete tra le due applicazioni, devono essere (ovviamente) uguali e sono dichiarate in una classe che si chiama "Comuni".
La classe Comuni utilizzata all'interno dell'applicazione VB.NET non può essere la stessa utilizzata dall'applicazione VB6...primo perchè mentre la "Comuni" di VB.net è una classe standard, la "Comuni" VB6, deve essere compilato come oggetto COM e secondo, perchè potrei avere la necessità in futuro che non tutto quello che viene passato all'applicazione .Net, venga passato anche all'applicazione VB6 (comunque al momento il codice all'interno, è identico).
Mi trovo quindi con la "Comuni" utilizzata dalla parte Server VBNET che ha versione 2.6.0.0 e la "Comuni" VB6 che ha versione 1.0.2.2.
Succede una cosa veramente strana (a mio avviso)...
Una volta compilata la dll Comuni da utilizzarsi con VB6 e generato il file Tlb, entro nei riferimenti del progetto e mi carico il riferimento al file, poi, premo il "Play" per debuggare l'applicazione e, quando l'applicazione tenta di Deserializzare una struttura inviata dalla parte Server, mi viene generato l'errore "Impossibile trovare l'assembly 'Comuni, Version=2.6.0.0'...". Sembra quasi che la struttura passata via rete, contenga le informazioni di quale DLL l'ha serializzata (la dll server versione 2.6.0.0) e quando, VB6 tenta di deserializzarla con una DLL uguale, ma con versione diversa (la dll VB6 1.0.2.2), generi un errore.
La cosa ancor più strana però è questa...
Se io, invece di eseguire l'applicazione VB6 in debug, la compilo, copio la dll e il tlb all'interno della cartella del progetto e lancio l'exe...l'applicazione funziona correttamente
Ovviamente, ho provato anche ad eseguire il VB6 in debug con la dll e il tlb nella directory del progetto ma non funziona comunque.
Ho notato una cosa...siccome la DLL ha al suo interno delle funzioni che scrivono su di un file di log nella stessa routine dove si trova la DLL, ho notato che:
-Quando lancio l'applicazione VB6 in debug, viene utilizzata la DLL presente nella cartella "Release" del progetto COM VBNET
-Quando lancio l'exe dell'applicazione VB6, viene utilizzata la DLL copiata manualmente nella cartella del progetto (nonostante tra un tentativo e l'altro non venga eseguita alcuna registrazione con RegAsm o altro)
A me, potrebbe anche andare bene che per provare l'applicazione debba compilare l'exe ogni volta ma purtroppo, ho la necessità di utilizzare la dll anche all'interno di un Database Access (con VBA). Con quest'ultimo, nonostante io esegua il "Compila" di VBA oppure crei il Database.accde (mde), va sempre ad utilizzare la DLL del progetto COM VB.NET e quindi non funziona.
Qualche idea? Si deve magari impostare da qualche parte in VB6 (o in VB.NET?) di ignorare la versione delle dll nei riferimenti?
Grazie infinite
EDIT [13/02/2012]:
Ho provato ad installare la DLL nella GAC ma mi viene generato un errore in quanto la DLL, all'avvio, carica delle impostazioni dal file XML che cerca nello stesso percorso della DLL, ma ovviamente, non posso mettere il file XML nella C:\Windows\Assembly
EDIT [13/02/2012] v2:
Finalmente, dopo una settimana, sembra abbia risolto.
Mi sa che...era proprio come pensavo...
La DLL che serializza, probabilmente, scrive nel pacchetto inviato sulla rete la versione della DLL utilizzata (2.6.0.0); quando il pacchetto arriva all'applicazione Client, questa va in errore in quanto la DLL che lei utilizza è di una versione differente.
Leggendo Online, sembrava che la soluzione fosse quella di impostare sia per l'oggetto che serializza che per quello che deserializza la proprietà "AssemblyFormat" al valore "Simple" in modo che venga ignorata la versione degli assembly.
Nonostante questa impostazione (già comunque attiva di default), il problema rimaneva...
Continuando le ricerche, ho trovato sul sito Microsoft che il Framework 2.0 SP2 e il 3.5 SP1 sembra avessero un baco che generava questo tipo di errore (vedi kb960442) ma nonostante abbia installato le relative patch (KB981574) il problema rimaneva...
Ho trovato quindi su un sito c# un trucco per "imbrogliare" l'oggetto che effettua la deserializzazione in modo da sostiuire la versione dell'assembly all'interno del pacchetto ricevuto via rete con quello della DLL utilizzata prima di effettuare la deserializzazione.
In questo modo, sembra funzionare correttamente...spero possa essere utile a qualcuno
Codice per la deserializzazione [VB.NET]
[CODE]
Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim ms As New IO.MemoryStream(Buffer)
formatter.Binder = New mAPICommon.Functions.AllowAllAssemblyVersionDeserializationBinder
Oggetto = formatter.Deserialize(ms)
ms.Close()
[/CODE]
Codice Nuova classe che esegue l'"imbroglio" :D [VB.NET]
Grazie e...alla prossima