DLL .Net utilizzata in VB6

mercoledì 02 aprile 2008 - 20.35

Teech Profilo | Expert

Ho messo le mani su un vecchio progetto fatto in VB6...
Viene lanciata una DLL (fatta in VB6) che a sua volta ha referenziato una DLL (sempre VB6) ed io ho aggiunto un DLL (in .NET 2.0 - VB.NET 2005) referenziando il TLB nell'ultima DLL.

La struttura è questa:
DLL Principale - Main.DLL (VB6)
---> All'interno del sorgente di Main.DLL è referenziata ed usata una DLL - Work.DLL (VB6)
---> All'interno del sorgente Work.DLL ho referenziato ed usato Net.DLL (.NET)

Sul PC di programmazione tutto funziona correttamente.
Ho preso le DLL aggiornate e le ho installate nel PC di produzione, registrando con REGSVR32 quelle fatte in VB6 ed ho utilizzato regasm per registrare la DLL fatta in .NET
il comando che ho utilizzato è: REGASM C:\MiaDir\Net.DLL /tlb /codebase (così come atto sul PC di programmazione)
Quando viene richiamato l'oogetto fatto in .NET però esce un errore tipo 'Impossibile creare l'ActiveX'... Ovviamente il Framework .NET è installato nel PC di produzione...

Cosa può essere? Dove ho sbagliato?

Grazie dell'aiuto!!!
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole

0rph3n Profilo | Newbie

Dove hai messo l'assembly?
Ci sono due possibilità, o lo si registra nella GAC oppure lo si piazza nella stessa directory dell'eseguibile che ne fa uso (in questo caso essendo referenziato da una dll penso debba stare nella stessa directory della dll).

'iao

RedStripe Profilo | Newbie

Non so se è corretto ti dò semplicemente la mia interpretazione della cosa
Quando usi REGASM produci una libreria di tipi comprensibile a COM e quindi anche alle dll VB6 "vecchio stile" , regasm provvede anche a registrarla nel registro di configurazione.

Quando vai sul PC di produzione però se riutilizzi REGASM da capo crei altri GUID per la dll VB6 , può essere che in fase di distribuzione devi soltanto esporre la TLB e registrarla senza riutilizzare REGASM??? , poi bisognerebbe anche vedere se la refrence alla dll NET che hai inserito nel codice della dll VB6 e di tipo esplicito ( dim xxx as new .... ) o se fai un late binding da un tipo object..

Ti posso dire che in qualche caso che mi sono trovato ad affrontare non ha funzionato nemmeno a me, non avendo troppo tempo ho preferito reimplementare in NET tutto quanto ma mi rendo conto che a seconda dei casi la cosa è improponibile.

Spero questo ti sia di aiuto in qualche modo
In Bocca al Lupo

mmjc23 Profilo | Newbie

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]
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


Grazie e...alla prossima
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5