Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

Îåêßíçóå áðü ôï ìÝëïò George J. Capnias. Τελευταία δημοσίευση από το μέλος George J. Capnias στις 06-03-2005, 21:25. Υπάρχουν 7 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  05-03-2005, 20:38 1358

    Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

    Συνημμένα: demoIBlogExtension.zip

    Ένα καλό...

    Θέλω να στιάξω ένα component που να υλοποιεί το IBlogExtension interface σε VB6.

    Για να κάνουμε μια παρόμοια δουλειά σε .NET υπάρχει ένα .dll (blogExtension.dll) που είναι φτιαγμένο από τους δημιουργούς του extension για να γίνεται implement.

    Για να κάνουμε implement ένα interface σε VB6 πρέπει να έχουμε ένα .tlb αρχείο ή να είναι διαθέσιμο μέσα από ένα .dll. Το συγκεκριμένο είναι σε C# γραμμένο και δεν έχει μέσα .tlb για να κάνει interop με COM services.

    Μπορούμε να φτιάξουμε ένα με το regasm blogExtension.dll /tlb:blogExtension.tlb και να το χρησιμοποιήσουμε απο VB6.

    Το έκανα και έκανα reference το .tlb από τη VB6, αλλά όταν έγραψα το Implements IBlogExtension δεν εμφανίστηκε στη λίστα το IBlogInterface για να μπορέσω να το κάνω implement!

    Που έχω κάνει λάθος;

    Συνημμένο στο μήνυμα είναι ένα .zip που έχει όλα τα αναφερόμενα αρχεία (το .NET assembly, το blogExtension.tlb και το blogExtension.cs - εξτρα είναι και το blogExtension.idl αν βοηθάει)


    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  06-03-2005, 00:11 1359 σε απάντηση της 1358

    Re: Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

    Δοκίμασε να κάνεις compile και reference από VB6 αυτό:

     

    Imports System

    Imports System.Xml.XPath

    Imports System.Reflection

    Imports System.Runtime.InteropServices

    Imports System.Windows.Forms

     

    Namespace Syndication.Extensibility

     

        <Guid("BB071552-04E6-4144-8179-A36613DD4B98")> Public Interface IBlogExtension

            ' Name of plug-in, suitable for display to a user

            <DispId(1)> ReadOnly Property DisplayName() As String

     

            ' return true if plug-in has configuration settings

            <DispId(2)> ReadOnly Property HasConfiguration() As Boolean

            ' Return true if an editing GUI will be shown to the

            ' user when BlogItem is called. In this case, the

            ' aggregator will not display its own editing UI.

     

            <DispId(3)> ReadOnly Property HasEditingGUI() As Boolean

            ' Display configuration dialog to user, if applicable

            <DispId(4)> Sub Configure(ByVal parent As IWin32Window)

     

            ' Post item to weblog. If plug-in is going to show a

            ' GUI for editing, it should return true to HasEditingGUI().

            <DispId(5)> Sub BlogItem(ByVal rssFragment As IXPathNavigable, ByVal edited As Boolean)

        End Interface 'IBlogExtension

    End Namespace 'Syndication.Extensibility

     

    Επίσης, πρόσθεσε στο AssemblyInfo.vb τη γραμμή:

     

    <Assembly: ClassInterface(ClassInterfaceType.None)>

     

    Ο λόγος που δεν δούλευε το προηγούμενο είναι ότι αν απλά γράψεις ένα interface, το κάνεις compile και πάρεις το tlb, τότε έχεις μόνο late binding μέσα από το ΙDispatch interface. Με τον παραπάνω τρόπο, μέσα από το AssemblyInfo.vb ζητάς να μην παραχθεί μόνο το IDispatch αλλά το interface που προσδιορίζεις εσύ (μιας και στη συνέχεια θα μπορούσες να γράψεις μια κλάση που να χρησιμοποιεί αυτό το interface, την οποία κλάση θα ήθελες να χρησιμοποιήσεις από το COM). Επίσης, δίνεις συγκεκριμένο Dispatch Id για κάθε method (<DispId(1)>, κλπ) και τέλος  το guid (εκεί βάζεις ό,τι GUID θέλεις) χρησιμεύει για να μην αποκτά νέο guid το interface σου στην περίπτωση που το ξανακάνεις compile (οπότε και θα πρέπει να ξαναβάλεις το reference).

    Τώρα βέβαια μένει το ερώτημα, γιατί θέλεις να κάνεις κάτι τέτοιο και δεν κάνεις implement το interface μέσα από ένα .NET component?


    Vir prudens non contra ventum mingit
  •  06-03-2005, 03:32 1360 σε απάντηση της 1359

    Re: Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

     KelMan wrote:

    Ο λόγος που δεν δούλευε το προηγούμενο είναι ότι αν απλά γράψεις ένα interface, το κάνεις compile και πάρεις το tlb, τότε έχεις μόνο late binding μέσα από το ΙDispatch interface. Με τον παραπάνω τρόπο, μέσα από το AssemblyInfo.vb ζητάς να μην παραχθεί μόνο το IDispatch αλλά το interface που προσδιορίζεις εσύ (μιας και στη συνέχεια θα μπορούσες να γράψεις μια κλάση που να χρησιμοποιεί αυτό το interface, την οποία κλάση θα ήθελες να χρησιμοποιήσεις από το COM). Επίσης, δίνεις συγκεκριμένο Dispatch Id για κάθε method (<DispId(1)>, κλπ) και τέλος  το guid (εκεί βάζεις ό,τι GUID θέλεις) χρησιμεύει για να μην αποκτά νέο guid το interface σου στην περίπτωση που το ξανακάνεις compile (οπότε και θα πρέπει να ξαναβάλεις το reference).


    Λοιπόν αυτό που λες το βλέπω και μέσα από το .IDL αρχείο (με το εργαλείο OLEView). Όντως το Interface IDispatch φτιάχνεται μόνο.

    Δοκίμασα και το δικό σου κώδικα, αλλά δεν είδα κάποια διαφορά. Μαζί με το .dll βγάζει κατευθείαν  και .tlb αλλά χρησιμοποιώντας αυτό το .tlb έχω τα ίδια αποτελέσματα. Από το OLEView βλέπω ότι το .IDL αρχείο βγαίνει και πάλι μόνο το IDispatch Interface.

    Θυμάμαι μια φορά που έκανα μια παρόμοια δουλειά σε VB χρησιμοποιώντας οδηγίες από τo Microsoft KB -
    182598 How To Implement IObjectSafety in Visual Basic Controls. Εδώ πάλι είχα ένα interface που έκανα Implement από VB6 και προερχόταν από .IDL/.ODL αρχείο. Ωραίο παρόμοιο άρθρο είναι και το 143258 How To Create Constants and DLL Declarations in a Type Library που κινήται στο ίδιο δρόμο.

    Για να γίνει εμφανές το Interface στην VB6 είναι IUnknown και όχι IDispatch. Άλλαξα στο .IDL που είχα το IDispatch σε IUnknown και προσπάθησα να το κάνω .tlb, αλλά το MkTypLib επιστρέφει λάθος, ότι δεν καταλαβαίνει τον τύπο των μεταβλητών...

    Εχει δει κάποιος, κάπου, specs για την IDL/ODL; MSDN ή κάπου αλλού;

     KelMan wrote:

    Τώρα βέβαια μένει το ερώτημα, γιατί θέλεις να κάνεις κάτι τέτοιο και δεν κάνεις implement το interface μέσα από ένα .NET component?


    Γιατί, ρωτάς... Απλή η απάντηση:

    Θέλω να φτιάξω ένα .dll που θα έχει Interface μια φόρμα για κάνει post ένας χρήστης ένα άρθρο σε WebBlog. Κατά συνέπεια ο κώδικας που είναι το άρθρο θα είναι HTML. Ένας εύκολος WYSIWYG HTML editor είναι ένα control που έρχεται με τον IE και είναι μέσα στο \Program Files\Common Files\Microsoft Shared\Triedit. Μπορείς να το παραμετροποιήσεις πλήρως. Και φυσικά χρειάζομαι και το Webcontrol για να μπορώ να κάνω και Preview τον κώδικα.

    Να φτιάξω 2 wrappers για δύο πολύ βαριά controls, και να τα κάνω απλώς πιο βαριά, μόνο και μόνο για να είμαι μέσα από managed περιβάλλον; Δεν είναι χαζό; Δεν είναι προτιμητέο να κάνω το Interface .tlb και να το κάνω implement κάτω από unmanaged περιβάλλον, από VB6;

    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  06-03-2005, 09:39 1361 σε απάντηση της 1360

    Re: Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

    Συνημμένα: interface.gif

    Περίεργο, εμένα το intellisence (σε VB6) μου εμφανίζει το Interface (βλ. attached)
    Αυτό δεν ήταν το ζητούμενο?



    Vir prudens non contra ventum mingit
  •  06-03-2005, 09:46 1362 σε απάντηση της 1361

    Re: Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

    Συνημμένα: interface2.gif

    Για του λόγου το αληθές, το άνοιξα και με τον object viewer και πάλι το δείχνει το interface (έχω φορτώσει το COM component)

    Δοκίμασες να κάνεις unregister το παλίο και reregister το καινούργιο;



    Vir prudens non contra ventum mingit
  •  06-03-2005, 11:47 1363 σε απάντηση της 1362

    Re: Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

    Αυτό το έκανε από την αρχή... Για διάλεξε το interface από πάνω για να μπορέσεις να γράψεις τον κώδικα στις function που θες να υλοποιήσεις να σε δω... Δεν βλέπεις το interface!

    Βρήκα ένα άρθρο μέσα στην KB που μάλλον εξηγεί τι είναι... Θα το δοκιμάσω και θα πω...

    George J.

    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  06-03-2005, 17:57 1364 σε απάντηση της 1363

    Re: Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

     gcapnias wrote:
    Το έκανα και έκανα reference το .tlb από τη VB6, αλλά όταν έγραψα το Implements IBlogExtension δεν εμφανίστηκε στη λίστα το IBlogInterface για να μπορέσω να το κάνω implement!

    Αααα... sorry, αλλά νόμιζα ότι δεν φαίνονταν το interface όταν έγραφες το "implements xxx", δεν πήγα παρακάτω να κάνω implement κάποιο member...
    Όντως συμβαίνει αυτό που λες και για να σου πω την αλήθεια, έχω μπερδευτεί με αυτό που προσπαθείς να κάνεις...
     gcapnias wrote:
    Να φτιάξω 2 wrappers για δύο πολύ βαριά controls, και να τα κάνω απλώς πιο βαριά, μόνο και μόνο για να είμαι μέσα από managed περιβάλλον; Δεν είναι χαζό; Δεν είναι προτιμητέο να κάνω το Interface .tlb και να το κάνω implement κάτω από unmanaged περιβάλλον, από VB6;

    Οι δύο wrappers αυτοί ουσιαστικά είναι proxy objects οπότε δεν πρόκειται για δύο νέα βαριά objects αλλά για τα proxies τους, το δε dll που παράγεται από μια τέτοια διαδικασία είναι πολύ μικρό ακριβώς γι αυτόν το λόγο.
    Από την άλλη μεριά, το interface που έχεις βάλει στο μάτι, στα δύο τελευταία sub χρησιμοποιεί δύο άλλα interfaces που ανήκουν στο assembly System.Windows.Forms
    οπότε, μπλέκεται το πράγμα όταν θα τις κάνεις implement... Θα πρέπει να κάνεις wrapper για το System.Windows.Forms για να το δεις μέσα από unmanager περιβάλλον...
    Οπότε, αν έχω καταλλάβει αυτό που θες να κάνεις, δεν γλυτώνεις το περιτύλιγμα Gift


    Vir prudens non contra ventum mingit
  •  06-03-2005, 21:25 1365 σε απάντηση της 1364

    Re: Φτιάχνοντας ένα COM Wrapper για ένα .NET Component

    Λοιπόν από την αρχή... Προχτές για τα γεννεθλιά μου - μην ρωτήσεις πόσο έγινα - μου κάνανε δώρο το "COM and .NET Interoperability" του Andrew Troelsen της Apress. Αυτό μου έβαλε τις φυτιλές και είπα να κάνω αυτό το "project".

    Μετά αυτό που μου είπες να βάλω το AssemblyInfo.vb το


    <Assembly: ClassInterface(ClassInterfaceType.None)>

    είναι ότι δεν δεν θα πρέπει να κάνεις σε μια τέτοια δουλειά απο .NET σε VB. Δεν βάζει τίποτα μέσα στο TypeLib από automation και άντε να καταλάβει η VB... Και αυτό δουλεύει μόνο για Classes. Εδώ δεν είχαμε Classes αλλά μόνο Interface. Για να κάνεις το ίδιο για το Interface γράφεις το

    <Guid("BB071552-04E6-4144-8179-A36613DD4B98"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> Public Interface IBlogExtension

    Από ότι κατάλαβα άμα χρησιμοποιήσεις το

    ComInterfaceType.InterfaceIsDual


    τα κάνει όλα μόνο του, και την αρίθμιση των members όπως πρότεινες.

    Θα μου πεις τώρα αν δούλεψε τελικά!

    Τσου! Δεν πρόλαβα να προβληματιστώ πως θα δω το System.Windows.Forms.dll - που ούτως ή άλλως είναι κάτω από τα References της VB, ψάξε να το δεις - γιατί η VB δεν υποστηρίζει Interfaces που τα members τους έχουν μεταβλητές τύπου IUnknown, που είναι οι μεταβλητές από τα δύο τελευταία members για την VB.

    Για αυτό ενώ το βλέπεις να το κάνεις Implement και το βλέπεις από τον Object Browser δεν βλέπεις τα members να γράψεις το κώδικα.

    Εχω σχεδόν διαβάσει το μισό βιβλίο από χτες, θα συνεχίσω να διαβάσω και το υπόλοιπο και κατά πάσα πιθανότητα θα το φτιάξω σε VB.NET, αν δεν βαρεθώ.

    Πάντως μετά από την βαβούρα και το ψάξιμο βρήκα ότι μπορείς να κάνεις πολλά πράγματα με τα .IDL αρχεία, πχ να φτιάξεις TypeLibs που κάνουν reference το WinAPI και δεν χρειάζεται να γράφεις τα Declare μέσα από VB6 ποτέ ξανά...

    Αχ αυτοί οι C++ programmers γιατί μας αφήνουν τόσα χρόνια στα σκοτάδια και να τα βλέπω αυτά τα πράγματα μετά από 8 χρόνια developing VB6, ενώ το VS6 και VC6 μπορούσε να φτιάχνει .IDLs και να τα κάνεις TypeLib από την αρχή;

    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems