Results 1 to 19 of 19

Thread: Dll

  1. #1

    Thread Starter
    Hyperactive Member FLasH3r's Avatar
    Join Date
    Feb 2001
    Location
    Bad command or filename
    Posts
    259

    Unhappy

    How can i make plug-in DLL's to my Project?

    If a user downloads a dll from a site and then
    copy that file to the application directory, how
    can i make the application see it and send messages
    to it?

    please help...

  2. #2
    Guest
    Oh, you are asking for trouble, aren't you

    Ok, here's a few pointers

    The only way to do it properly is to make sure that any of the plugin DLLs implement a particular known interface. This is for two reasons - it means that you know what the public properties of the DLL are, and it allows you to query the interface to makes sure that it actually is a DLL that you can plugin.

    Using the TypeLibrary DLL, you can scan a directory, and dynamically get the GUID, any interfaces and the progID of the DLL in that directory. Once you have amtched an interface in the DLL with an interface that you know about, you can store the progID to the DLL in an array or something. You need to check to see if the DLL is registered, and if not, register the DLL first.

    After that, when you want to use the plugin, you can load it using CreateObject, then put it into a variable that is of the Interface type. This lets you call the DLL methods and properties in what is in effect early bound mode.

    It's knid of complex from a design point, but not very dificult to put into practice.

    - gaffa

  3. #3

    Thread Starter
    Hyperactive Member FLasH3r's Avatar
    Join Date
    Feb 2001
    Location
    Bad command or filename
    Posts
    259

    Smile OK, But...

    I know the interface has to be the same the problem is how to get the GUID and the other stuff i need in order to use the CreateObject...

    P.S.
    That is the only way i can think of using plu-ins in my application...



  4. #4
    Guest
    It is if you have no clue what the Typelibrary Dll is...

    Would you mind explaining that to me? Preferably with a code sample of course...

    I thought it was impossible!

    By the way another way of doing plugins is to make your main exe an ActiveX EXE and implement the plugins as EXE's that reference the main exe.

    When you want to run a plugin, runthe EXE file and the plugin can use your main exe to get data.

    The problem here is that Interprocess communication is VERY slow.

    Gerco.

  5. #5
    Guest
    OK, here's some sample code to help you on your merry way.

    The attached project is the full version of this, which is pretty much a complete demo of creating plugins in VB. It dynamically detects them on the fly (even if they are unregistered), and loads them only when required, accessing thme through IDisp-binding

    Code:
    Private Sub LoadLanguagePlugins(pstrPluginDirectory As String, & _
    Optional pbolRegisterNewLibraries As Boolean = False)
    
        'Scans through the specified directory,
        'and looks at all DLL files. It queries the DLL
        'to decide if it supports the expected interface
        'and if so, ads the ProgId, Name and description into
        'the languages collection
        
        Dim lobjFSO As Scripting.FileSystemObject
        Dim lobjFile As Scripting.File
        Dim lobjPlugin As Object
        Dim lobjTypeLib As TLIApplication
        Dim lobjTypeLibInfo As TypeLibInfo
        Dim lstrProgID As String
        Dim lobjILang As ILanguageLib.ILanguage
        Dim lobjLanguage As clsLanguage
        Dim llngCounter As Long
        Dim lobjInterface As TLI.InterfaceInfo
        Dim lobjCoClass As TLI.CoClassInfo
    
        'Init the objects
        Set lobjFSO = New FileSystemObject
        Set lobjTypeLib = New TLIApplication
        
        llngCounter = 0
        For Each lobjFile In lobjFSO.GetFolder(pstrPluginDirectory).Files
            If Right(UCase(lobjFile.Name), 3) = "DLL" Then
                
                'cmbLang.AddItem lobjFile.Name
                
                'Found a possible library to load
                Set lobjTypeLibInfo = lobjTypeLib.TypeLibInfoFromFile(lobjFile.Path)
                
                'Get the prog id
                lstrProgID = lobjTypeLibInfo.Name & "." & lobjTypeLibInfo.CoClasses(1).Name
                
                'Scan through the CoClasses
                For Each lobjCoClass In lobjTypeLibInfo.CoClasses
                    'Loop through the intefaces to see if it
                    'supports the required interface.
                    'NOTE: the DLL can support multiple interfaces
                    For Each lobjInterface In lobjCoClass.Interfaces
                        If lobjInterface.Name = "_ILanguage" Then
                            'This one is OK
                            lstrProgID = lobjTypeLibInfo.Name & "." & lobjCoClass.Name
                            
                            'Possible error point
                            'Load the library into the object
                            On Error GoTo Err_RegisterOCX
                            Set lobjILang = CreateObject(lstrProgID)
                            On Error GoTo Err_NotSupported
                            
                            'Increment the counter
                            llngCounter = llngCounter + 1
                            'Query the interface
                            Set lobjLanguage = New clsLanguage
                            lobjLanguage.Language = lobjILang.LanguageSupported
                            lobjLanguage.Description = lobjILang.Description
                            lobjLanguage.ProgID = lobjILang.ProgID
                            lobjLanguage.Key = "Key_" & llngCounter
                            mcolLanguages.Add lobjLanguage, lobjLanguage.Key
                            'Reset error handler
                            On Error GoTo 0
    
                        End If
                    Next lobjInterface
                Next lobjCoClass
            End If
                
    Err_NotSupported:
                'Error occured, so we assume that this DLL is not
                'a language DLL, or it failed to register
                
        Next lobjFile
        'Bail out
        Exit Sub
        
    Err_RegisterOCX:
        'Debug.Print "About to register new Language Library: " & lstrProgID
    '    If pbolRegisterNewLibraries Then
            If Not RegisterDLLOROCX(lobjFile.Path, Register, True) Then
                'Error occured registering the file
                Debug.Print "Failed to register " & lstrProgID
                GoTo Err_NotSupported
            Else
                Debug.Print "Registered New Language Library: " & lstrProgID
                Resume
            End If
    '    Else
    '        Err.Clear
    '        On Error GoTo 0
    '        GoTo Err_NotSupported
    '    End If
    End Sub
    
    Public Function RegisterDLLOROCX(File As String, _
                                     Optional Process As RegUnreg = Register, _
                                     Optional PromptOnError As Boolean = False)_
                                     As Boolean
    
        Dim LoadedLib As Long
        Dim EntryPoint As Long
        Dim ExitCode As Long
        Dim newThread As Long
        Dim newThreadID As Long
        
        On Error Resume Next
    
        '// Check file exists
        If Dir(File, vbNormal) = "" Then
            If PromptOnError Then MsgBox "The file " & File & " doesn't exist",_
             vbCritical, "DLL/OCX Register"
            RegisterDLLOROCX = False
            Exit Function
        End If
    
        LoadedLib = LoadLibrary(File)                          '// Load file
    
        If LoadedLib = 0 Then
            If PromptOnError Then MsgBox _
            "An error occured while loading the file " & File, _
            vbCritical, "DLL/OCX Register"
            RegisterDLLOROCX = False
            Exit Function
        End If
    
        '// Find right entery point
        If Process = Register Then
            EntryPoint = GetProcAddress(LoadedLib, "DllRegisterServer")
        ElseIf Process = UnRegister Then
            EntryPoint = GetProcAddress(LoadedLib, "DllUnregisterServer")
        Else
            If PromptOnError Then MsgBox _
            "An error occured while loading the file " & File, _
            vbCritical, "DLL/OCX Register"
            RegisterDLLOROCX = False
            Exit Function
        End If
    
    
        If EntryPoint = vbNull Then
            If PromptOnError Then MsgBox _
            "An error occured while locating the entery point for the file : " & _
            vbNewLine & File, vbCritical, "DLL/OCX Register"
            FreeLibrary (LoadedLib)                            '// Unload libarary
            RegisterDLLOROCX = False
            Exit Function
        End If
    
        Screen.MousePointer = vbHourglass
    
        newThread = CreateThread(ByVal 0, 0, ByVal EntryPoint, _
            ByVal 0, 0, newThreadID)    '// Create a new thread.
    
        If newThread = 0 Then
            Screen.MousePointer = vbDefault
            If PromptOnError Then
                MsgBox "An error occured while attempting to create a new thread.",_
             vbCritical, "DLL/OCX Register"
            End If
            FreeLibrary (LoadedLib)                            '// Unload libarary
            Exit Function
        End If
    
        If WaitForSingleObject(newThread, 10000) <> 0 Then
            Screen.MousePointer = vbDefault
            If PromptOnError Then MsgBox _
            "An error occured while attempting to register/unregister the file : " & _
            vbNewLine & File, vbCritical, "DLL/OCX Register"
            ExitCode = GetExitCodeThread(newThread, ExitCode)
            ExitThread (ExitCode)
            FreeLibrary (LoadedLib)
            RegisterDLLOROCX = False
            Exit Function
        End If
    
    
        CloseHandle (newThread)                                '// Close thread
        FreeLibrary (LoadedLib)                                '// Unload libarary
        Screen.MousePointer = vbDefault                        '// Reset cursor
        RegisterDLLOROCX = True
    
    End Function
    The attached source is complete (except for the flexbag dll which is gettable from www.spidereye.com.au/software/flexbag/

    Basically, unzip the projects, and load the gLanguagePlugin.vbg. Register the ILanguage.dll first. Obviously, there is no requirement to register the DLL's in the "PlugIns" directory.

    This project basically swap languages on the form, based on all the possible languages which are in the Plugins directory. Note that the individual language plugins MUST be compiled before they will work.

    Not all the code is mine - the RegisterDLLorOCX originally came from somewhere else, although I have made some changes. I'd credit it if I could remember who it was.

    And I'm sorry if my languages are actually wrong - I was just using babelfish to translate the english to german, french and spanish, and I don't think I have taken into account the gender and stuff.

    Try registering and unregistering the DLL's in the plugins directory, and moving them out of the plugins directory to see the plugins in action. Also, have a look at the references held in the main test application

    - gaffa
    Attached Files Attached Files

  6. #6
    Guest
    Hmm, it looks great, but I get:

    Error '48', error in loading dll on this line:
    Code:
    Next lobjInterface
    When I click the Load Plugins button.

    Could it have something to do with the fact that the PluginProvider dir is empty, It does have a MISSING reference to PluginProvider.dll.

    I did register the ILanguage.dll

    Gerco.

  7. #7
    Guest
    Yeah, derefernece the PlugInProvder project. Sorry. That was teh next incarnation of the plugin system, but I haven't finished it properly.

    It's not required, so you can delete all references to the PlugInProvider.

    - gaffa

  8. #8
    Guest
    I have, but I still get the excact same error in the excact same place.

    I use Windows 2000 with VB6 Enterprise SP 4... any ideas?

    Gerco

  9. #9
    Guest
    Yeah, that's the same setup as me. I'll recheck it now and upload it again.

    - gaffa

  10. #10
    Guest
    Ok, here it is again. I just reloaded and it seems to work OK.

    Might be worth unregisteringth ILanguage DLL (and other DLL's), deleting the directories and starting again with this zip file

    - gaffa
    Attached Files Attached Files

  11. #11
    Guest
    YAY!

    It works perfectly now...

    Do you think it is good form to unregister the plugins after you're done with them and re-register them the next time the program starts?

    ppl can (re)move the plugins without your knowing about it and that would leave 'dangling references'. Or is windows smart enough to keep track itself?

    I mean, would the overhead of registering/unregistering the plugins on program start/exit be worth the added convinience of being able to do stuff to the .dll files without 'dangling refences' be worth it?

    Gerco.

  12. #12
    Guest
    One more question...

    What is ILanguage.dll for? What does it do, or where is it used to do what?

    Gerco.

  13. #13
    Guest

    Talking

    Unregistering ins't an issue, since Windopws (supposedly) tracks the registry entries properly. You could unregister all I guess, but that would be more work next time, having to register them each time (and I don't trust the Registry to clean up after itself anyway). Easier to just register them once.

    As to what the ILanguage DLL is - it's sort of the key to the whole thing.

    The main EXE has a reference to the ILanguage DLL. This DLL tells the EXE what the plugin is going to look like when it loads a plugin DLL, This way, you EXE knows that each plugin has a Name propery, and A Langiage Property etc. It also gives you the Intellisense stuff.

    As you can see from the code below, the DLL is instantiated with CreateObject, then cast a variable of type ILanguage:
    Code:
        Dim lobjILang As ILanguage
    
        'This line gets the prog ID of the item selected
        'in the combo box (from the Flexbag collection)    
        Set lobjLang = mcolLanguages.Item("Key_" & cmbLang.ItemData(cmbLang.ListIndex))
        lblDescription.Caption = lobjLang.Description
        
        'Here the object is cast from type object to type ILanguage
        Set lobjILang = CreateObject(lobjLang.ProgID)
        
        'The .Initialise will appear as a dropdown intellisense thing
        lobjILang.Initialise
    The actual language DLL (LangGer.DLL etc) implements the ILanguage DLL - you can see in the LangGer project that the "ILanguage_XXXXX" are the only public methods.

    The interesting thing here is that once the Language DLLs are compiled, and the EXE is compiled, the ILanguage DLL can actually be thrown away. It contains no actual code - merely method stubs.

    Hope that explains it a bit. Look at the code in the four language DLL's to see what I mean.

    I'm thinking about writing a proper article about how to implement plugins, with smaples and explanations etc. cos people seem intererested (I've explained the concept a few times, but this is the first time I've posted the sample program). I gues that will happen when I find enough time.

    - gaffa

  14. #14
    Guest
    I wish I could spell .

    My apologies for the myriad of typos in that last post. I couldn't be bothered trying to fix them though.

    - gaffa

  15. #15
    Guest
    Wouldn't you be able to do the same without the ILanguage.dll?

    You could write an ILanguage class (like you have) and simply include it in everything that needs or implements an ILanguage...

    That would save you one dll, but probably introduce some compatibility issues...

    Gerco Dries.

  16. #16
    Guest
    One really funky reason for using the ILanguage DLL is that in the Language DLL themselves, ther eis not public interface.

    Try creating a project, then add a reference to LangEng.DLL.

    Now try creating a variable of type clsEnglish.

    It doesn't actually work, because the LangEng DLL exposes NO interface. The entire access must be done through the typelib inforation held in the ILanguage DLL.

    This technique means that it is possible to make DLL's that are unusable with an intermediate, non-distributed DLL (in this case ILanguage). So another developer can't use you're DLL unless he knows how to access it properly (Obviously, there's is nothing stopping him using the TypeLibInfo to find out the interface, but the developer would want to be keen).

    The ILanguage DLL also allows for IDisp binding (a form of early binding) instead of late binding. Early binding is faster than late binding, so that's also a good thing.

    - gaffa

  17. #17
    Guest
    I've just created a modified version of the LangEng.DLL, which contains multiple languages in the one plugin (Australian and US English). Basically, both languages load from the one DLL, and work very nicely.

    The only difference between the actual languages is the spelling of "Colour" and "Color"

    Anyway, it demonstrates the multiple plugin support approach.

    - gaffa
    Attached Files Attached Files

  18. #18
    Lively Member
    Join Date
    Dec 2000
    Location
    Indiana
    Posts
    73

    Angry



    Thats cool and all....... but...... How do I implement this into my own project? I dont get this stuff, I thought plugins used dlls, not classes. As far as I can see, its just classes in there. How do I load plugins at run time?

  19. #19
    gaffa
    Guest
    A DLL is just a class, or number of classes, that are compiled in such a way that they expose some standard interfaces that Windows (and subsequently your program) knows about and can access.

    I'll admit it's not a particularly obvious method - there are a lot of seemingly extraneous levels of code (especially the use if the ILanguage interface DLL, which on the face of it seems completely useless)

    Tada, in reference to your other post about plugins, you sort of have two options.

    You can use the compiled DLL approach, which is realistically a 'proper' plugin, as described above, or you could go down the scripting path, which allows the end user to create a script file as plain text, and your application then takes this text file and parses and executes the contents of the text files.

    Applescript is a form of text-based scripting, and the script code is just that, code.

    Photoshop and other proggies like Quark use compiled DLL's as plugins (the Quark ones need to be written in C++ cos of all the callbacks required)

    At some point, your program MUST know at least something about the plugin, if only so you can verify that the plugins author isn't about to do something completely stupid. Either your program knows how to parse up the script file, or it knows what the avaialble functions and methods are (or it can at least get a list of those functions and methods). You can't just run a file at random.

    ActiveX controls are all plugins, and they all expose three methods - AddRef, QueryInterface and Release(?) - without exposing those three methods, it's not and ActiveX component.

    You will need to decide which approach is going to be te best for you, probably based on the sort of market and users that you are aiming for. For less skilled (non-programmer) users, the scripting is probably better, but a lot harder as you have to write a complete parse and code verification engine to make sure that the script can be executed properly.

    A complete alternative would be to incorporate VBA directly into your app, but I've never tried this (the licensing hasn't helped, although aparently that is changeing in VB7).

    Also, my apologies for my dreadful spelling in all all my previous posts...

    - gaffa

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width