COM multi-interfaces en C# pour vbscript
Bonjour à tous,
J’ai un problème d’accès depuis un script VBS pour remonter dans la classe héritée de l’objet COM d’un assembly développé en C#. Bon c’est pas très parlant, je développe :
J'ai fait un assembly .NET, en version 1.0.0.0, inscrit dans le GAC, publié dans COM, pour l’utiliser depuis un script VB. Mon assembly est codé avec une classe et son interface. J’ai donné manuellement tous les ID (CLSID, ProgID, IID, LIBID) pour gérer ça correctement. Mon vbscript fonctionne parfaitement. La structure du code de l’assembly peut se résumer à :
Citation:
MonInterface{ getValue() }
MaClass : MonInterface{ getValue() }
Fort de ce succès, aujourd’hui j’ai amélioré mon assembly .NET. J’ai ajouté des méthodes...
J’ai désinscrit la 1.0.0.0 du GAC, dépublié dans COM, supprimé la DLL.
Incrémenté la version de la DLL en 1.1.0.0, recompilé, inscrit dans le GAC et publié dans COM.
Je ne veux pas toucher à l’ancien code pour rester compatible avec les anciens programmes client-COM. J’ai donc joué avec les implémentations des interfaces et l’héritage pour n’ajouter que le nouveau code... La structure du projet recompilé est la suivante :
Citation:
MonInteface{ getValue() }
MaClasse : MonInterface{ getValue() }
MonInterface1 : MonInterface{ getValue1() }
MaClasse 1 : MaClasse, MonInterface1{ getValue1() }
Les vieux scripts VB fonctionnent toujours parfaitement car les CLSID, ProgID, IID, LIBID de MonInterface et MaClasse n’ont pas changé :
Code:
1 2
| Set oMonComposant = CreateObject("MonComposant.MaClasse")
MsgBox oMonComposant.getValue() |
Les nouveaux scripts VB fonctionnent parfaitement car j’ai des nouveaux CLSID, ProgID, IID. Le LIBID par contre, est resté le même puisque c’est le même projet C# pour les 2 classes (dans AssemblyInfo.cs, l’attribut [assembly: Guid(...)] ) :
Code:
1 2
| Set oMonComposant = CreateObject("MonComposant.MaClasse1")
MsgBox oMonComposant.getValue1() |
Enfin, et c’est là mon problème, dans les nouveaux scripts VB, je devrais pouvoir faire appel via la nouvelle classe aux méthodes héritées de l’ancienne classe. Et c’est ici que j’ai une erreur. Je ne comprends pas pourquoi ce code ne fonctionne pas :
Code:
1 2
| Set oMonComposant = CreateObject("MonComposant.MaClasse1")
MsgBox oMonComposant.getValue() |
Voici le vrai code C# de l'assembly :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace MonComposant
{
// Interface originale
[ComVisible(true), GuidAttribute("00FC2F76-E57A-4a64-904C-5BF44BEEBF8D")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface MonInterface
{
string getValue();
}
// Classe originale
[ComVisible(true), GuidAttribute("E7FF8AB7-4F15-4dac-89BD-A20FB1E9E10D")]
[ProgId("MonComposant.MaClasse")]
[ClassInterface(ClassInterfaceType.None)]
public class MaClasse : MonInterface
{
public string getValue()
{
return "hello v0";
}
}
// Nouvelle Interface (hérite de MonInterface)
[ComVisible(true), GuidAttribute("82B1983C-7C33-4158-8CCF-D2A87713A060")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface MonInterface1 : MonInterface
{
string getValue1();
string getValue2();
}
// Nouvelle Classe (hérite de MaClasse + implémente MonInterface1)
[ComVisible(true), GuidAttribute("62561DCA-B35C-4bd5-B5BB-80A72D2AB207")]
[ProgId("MonComposant.MaClasse1")]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(MonInterface1))]
public class MaClasse1 : MaClasse, MonInterface1
{
public string getValue1()
{
return "hello v1";
}
public string getValue2()
{
return this.getValue() + " -+- " + this.getValue1();
}
}
} |
avec le assemblyinfo.cs :
Code:
1 2 3 4
| [assembly: ComVisible(true)]
[assembly: Guid("0fd06878-6c46-40a2-aff8-7e19ed68ac4c")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")] |
Voilà, voilà... je ne comprends pas ce que je fais mal.
Merci d'avance pour votre aide.
herit interface in com not supported
bonjour
tu as empeche l'heritage des membres d'interface de base par un attribut com .
voici le bout de code et un exemple en vba(identique à vbscript):
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace MonComposant
{
// Interface originale
[ComVisible(true), GuidAttribute("4BB56966-2BCA-4587-AB86-AC5EF47ADA24")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface MonInterface
{
string getValue();
string messageValue();
string getPropToShadow();
}
// Classe originale
[ComVisible(true), GuidAttribute("EE94F5D7-6C3B-4471-82BA-07DB2765E1C5")]
[ProgId("MonComposant.MaClasse")]
[ClassInterface(ClassInterfaceType.None)]
public class MaClasse
{
public string getValue()
{
return "hello getValue from BaseClasse MaClasse ";
}
public string messageValue()
{
return "hello messageValue from BaseClasse MaClasse ";
}
public string getPropToShadow()
{
return "hello getPropToShadow sera masquee ";
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace MonComposant
{
// Nouvelle Interface (hérite de MonInterface)
[ComVisible(true), GuidAttribute("54D391AF-3866-4aea-9A28-B4B36A7D2BD4")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface MonInterface1 : MonInterface
{
string getValue1();
string getAutreProp();
//Pour masquer eventuellement une prop de classe base MaClasse
//utiliser plutot un New qui redefinit cette prop
new string getPropToShadow();
}
// Nouvelle Classe (hérite de MaClasse + implémente MonInterface1)
[ComVisible(true), GuidAttribute("7713C7EB-A93B-4c0d-9856-87B4AE737F54")]
[ProgId("MonComposant.MaClasse1")]
[ClassInterface(ClassInterfaceType.None)]
//SUPPRIME CA qui fait le contraire de ce que tu veux.
//Empeche l'acces aux classes de MonInterface base
//[ComDefaultInterface(typeof(MonInterface1))]
public class MaClasse1 :MaClasse, MonInterface1
{
#region MonInterface1 Membres
string MonInterface1.getValue1()
{
return "hello1 getValue1 from MaClasse1";
}
string MonInterface1.getAutreProp()
{
return "hello1 getAutreProp from MaClasse1";
}
string MonInterface1.getPropToShadow()
{
return "hello getPropToShadow Masquee ";
}
#endregion
}
} |
code vba qui accede aux classes com:
Code:
1 2 3 4 5 6 7 8 9 10 11 12
|
'a noter que classe base MaClasse n'est accessible que via son
'interface "MonInterface" en liaison tardive via CreateObject
Private Sub CommandButton1_Click()
Dim c As MaClasse1
Set c = New MaClasse1
TextBox1.Text = c.getValue1 & " - " & c.getAutreProp & " - " & c.getPropToShadow & vbCrLf
Dim IObjInterface As MonInterface
Set IObjInterface = CreateObject("MonComposant.MaClasse1")
TextBox2.Text = IObjInterface.getValue & " - " & IObjInterface.messageValue & " - " & c.getPropToShadow
End Sub |
bon code...