Results 1 to 37 of 37

Thread: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Think, that this topic is an important one - and deserves its own article.

    Hmm, how to begin...

    Once there was a time,
    in the dark ages,
    long before "Manifestos" became available to human beings,
    that VB-Developers fought all kinds of Dll-Hell...


    Erm, all of them? ...No...

    So this is about an approach which is an alternative to the Manifest-triggered SxS-Services
    we can use today, reliably and succesfully in usage for nearly two decades now (it was working
    already on Win95/Win98 - and still works up to the recent Win8.1 or Win10).

    It is IMO the more flexible approach - and relative easy to incorporate into your Apps,
    by dropping-in a simple *.bas Module which can remain constant, codewise (no Manifests
    to keep in sync with your COM-Dlls TypeLib-informations, in case one recompiles these
    Dlls without Binary-Compatibility).

    Ok, let's come to the point:
    (will try to roll this out a bit, in a style which is hopefully more Newbie-friendly to read).

    You plan, to ship your own 'MyActiveX.dll' alongside your 'MyApp.exe' -
    in addition to 'ForeignActiveX.dll', which you made use of in your App too.

    Well, first thing I would suggest when you plan to ship your App regfree is, to do it "orderly" - by
    ensuring a certain Folder-Structure (in your Zip, or whatever you will use for packaging in the end).

    What I usually go with is a Folder-Structure as:
    \MyApp\
    .... \Bin\
    .... \Res\
    .... MyApp.exe

    Aside from MyApp.exe (and maybe a MyAppSettings.ini) not much more in the Apps Root-Folder.

    This way the user (after unpacking your regfree deployed App into his own Target-Foder)
    can immediately see, "where the Startup-Point is" (and what to click).

    Well, forgot to congratulate you first, because when you read this article, you already did the mental step from:
    "I need to compile everything into a single Executable"
    to:
    "I'm far more flexible, when I have certain things in my own, dedicated Dll-Binaries"
    accompanied hopefully by:
    "I'm also more efficient, when I re-use good work of others, avoiding re-inventions of the wheel"

    So, what would reside in your relative Subfolder \Bin\ now? All the Dlls of course:
    \MyApp\
    .... \Bin\
    ........ MyActiveX.dll
    ........ ForeignActiveX.dll
    .... \Res\
    .... MyApp.exe

    To make the approach I'm talking about work, what you need in addition is a Helper-Dll, which is a
    Standard-Dll that needs no registering: DirectCOM.dll - so, adding it - your Folder-Structure should look then:
    \MyApp\
    .... \Bin\
    ........ DirectCOM.dll
    ........ MyActiveX.dll
    ........ ForeignActiveX.dll
    .... \Res\
    .... MyApp.exe

    With such a Folder-Structure in place (and the Bin-Folder filled with the right Binaries),
    what you need now in your App is a *.bas Module with the following content:

    (in my Demo-Zip for this article, I named this Module: modRegfreeDlls.bas
    Code:
    'A readymade "PlugIn-Module" you can include into your Projects, to be able to load Classes from COM-Dlls
    'without registering them priorily - and just to be clear - there is no "dynamic re-registering" involved -
    'DirectCOM.dll will load the appropriate Class-Instances without touching the Systems Registry in any way...
    '
    'There's 3 Functions exposed from this Module:
    '- GetInstanceFromBinFolder ... loads Classes from Dlls located in a SubFolder, relative to your Exe-Path
    '- GetInstance              ... same as above - but allowing absolute Dll-Paths (anywhere in the FileSystem)
    '- GetExePath               ... just a small helper, to give the correct Exe-Path, even when called from within Dlls
    '
    'the approach is *very* reliable (in use for nearly two decades now, it works from Win98 to Windows-10)
    'So, happy regfree COM-Dll-loading... :-) (Olaf Schmidt, in Dec. 2014)
    
    Option Explicit
    
    'we need only two exports from the small DirectCOM.dll Helper here
    Private Declare Function GetInstanceEx Lib "DirectCOM" (spFName As Long, spClassName As Long, Optional ByVal UseAlteredSearchPath As Boolean = True) As Object
    Private Declare Function GETINSTANCELASTERROR Lib "DirectCOM" () As String
    
    Private Declare Function LoadLibraryW& Lib "kernel32" (ByVal lpLibFileName&)
    Private Declare Function GetModuleFileNameW& Lib "kernel32" (ByVal hMod&, ByVal lpFileName&, ByVal nSize&)
     
    'a convenience-function which loads Classes from Dlls (residing in a SubFolder below your Exe-Path)
    'just adjust the Optional RelBinFolderName-Param to your liking (currently specified as "Bin")
    Public Function GetInstanceFromBinFolder(ByVal ShortDllFileName As String, ClassName As String, _
                                             Optional RelBinFolderName$ = "Bin") As Object
      Select Case LCase$(Right$(ShortDllFileName, 4))
        Case ".dll", ".ocx" 'all fine, nothing to do
        Case Else: ShortDllFileName = ShortDllFileName & ".dll" 'expand the ShortFileName about the proper file-ending when it was left out
      End Select
    
      Set GetInstanceFromBinFolder = GetInstance(GetExePath & RelBinFolderName & "\" & ShortDllFileName, ClassName)
    End Function
    
    'the generic Variant, which needs a full (user-provided), absolute Dll-PathFileName in the first Param
    Public Function GetInstance(FullDllPathFileName As String, ClassName As String) As Object
      If Len(FullDllPathFileName) = 0 Or Len(ClassName) = 0 Then Err.Raise vbObjectError, , "Empty-Param(s) were passed to GetInstance"
      
      EnsureDirectCOMDllPreLoading FullDllPathFileName 'will raise an Error, when DirectCOM.dll was not found in "relative Folders"
      
      On Error Resume Next
        Set GetInstance = GetInstanceEx(StrPtr(FullDllPathFileName), StrPtr(ClassName), True)
      If Err Then
        On Error GoTo 0: Err.Raise vbObjectError, Err.Source & ".GetInstance", Err.Description
      ElseIf GetInstance Is Nothing Then
        On Error GoTo 0: Err.Raise vbObjectError, Err.Source & ".GetInstance", GETINSTANCELASTERROR()
      End If
    End Function
    
    'always returns the Path to the Executable (even when called from within COM-Dlls, which resolve App.Path to their own location)
    Public Function GetExePath(Optional ExeName As String) As String
    Dim S As String, Pos As Long: Const MaxPath& = 260
    Static stExePath As String, stExeName As String
      If Len(stExePath) = 0 Then 'resolve it once
        S = Space$(MaxPath)
        S = Left$(S, GetModuleFileNameW(0, StrPtr(S), Len(S)))
        Pos = InStrRev(S, "\")
        
        stExeName = Mid$(S, Pos + 1)
        stExePath = Left$(S, Pos) 'preserve the BackSlash at the end
        Select Case UCase$(stExeName) 'when we run in the VB-IDE, ...
          Case "VB6.EXE", "VB5.EXE": stExePath = App.Path & "\" 'we resolve to the App.Path instead
        End Select
      End If
      
      ExeName = stExeName
      GetExePath = stExePath
    End Function
    
    Private Sub EnsureDirectCOMDllPreLoading(FullDllPathFileName As String)
    Static hDirCOM As Long
      If hDirCOM Then Exit Sub  'nothing to do, DirectCOM.dll was already found and pre-loaded
      If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(GetExePath & "DirectCOM.dll"))
      If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(GetExePath & "Bin\DirectCOM.dll"))
      If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(GetExePath & "RC5Bin\DirectCOM.dll"))
      If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(App.Path & "\DirectCOM.dll"))
      If hDirCOM = 0 Then hDirCOM = LoadLibraryW(StrPtr(Left$(FullDllPathFileName, InStrRev(FullDllPathFileName, "\")) & "DirectCOM.dll"))
      If hDirCOM = 0 Then Err.Raise vbObjectError, Err.Source & ".GetInstance", "Couldn't pre-load DirectCOM.dll"
    End Sub
    With that module in place, you have now two globally reachable (Public) Functions available:
    - GetInstanceFromBinFolder(...)
    - GetInstance(...)

    The first one is the more conveniently usable one, because it saves you from giving
    "Full explicit Paths to your Dll-Binaries", so for ActiveX-Dlls in your own Bin-Folder,
    all you need to instantiate a Class from one of them is e.g.:

    Code:
    Dim oMyClass
    Set oMyClass = GetInstanceFromBinFolder("MyActiveX", "cMyClass")
        oMyClass.DoSomething
    Note, how the above Form resembles the well-known ProgID-based instancing per CreateObject:
    Code:
    Dim oMyClass
    Set oMyClass = CreateObject("MyActiveX.cMyClass")
        oMyClass.DoSomething
    And in fact, both versions accomplish the same thing - both create a new Object-Instance - just that
    CreateObject needs a registered version of 'MyActiveX.dll', whilst GetInstanceFromBinFolder does not.

    The second available Function from the *.bas Module (GetInstance) is just the explicit form,
    which you can give a full absolute path into the FileSystem, to specify a certain Dll ...
    otherwise the behaviour (and results) are the same as those from GetInstanceFromBinFolder.

    Well, that's it already - a Helper-*.bas Module (in conjunction with a Helper-Dll in your Bin-Folder)
    can ensure regfree loading, over a relative easy to use function (GetInstanceFromBinFolder).

    You have to make sure though, that you use this Function now consequently throughout
    your whole App, when it comes to the instantiation of Classes from your regfree shipped Dlls.

    To ensure that, you should scan through your whole App, using a project-wide Code-search for
    the String: [New ] (.... leaving out the brackets of course - but include the space-char at the end).

    This will stop at all code-lines where you do an Object-Instantiation - change all New MyClass
    occurences then into the appropriate GetInstanceFromBinFolder(...) replacements - of course
    only for Classes which are defined in those Dlls - one doesn't need to replace the instantiation
    of a normal VB-Collection - or an ADO-Recordset, since those are always available directly
    (contained in the VB-Runtime or in case of ADO - coming preinstalled on a given System).

    I know - if your Project is not a small one, this is quite a boring "Identify-And-Paste"-task
    but not that time-consuming as one might think (I never needed more than 3-10 minutes for
    those replacements, even in larger projects and with "double-checking").

    So, that's it with regards to describing the usage of a regfree-alternative to SxS-Manifests.

    <removed link to external site hosting compiled dlls>

    What remains is a few words to the following Demo, in case you want to use this as a first
    Code-base for your own tests:RegfreeDeployment.zip

    I've tried to make it a real-world example, which involves also your own compiled ActiveX-Dll.

    So, before starting the Demo Project-File: RegfreeDeploymentOfDlls.vbp ...
    You should go one Folder-Deeper into: \TestDllProject\ ...
    Start-up the ActiveX-Dll-Project: MyTest.vbp there ...
    And compile the appropriate Dll from it into the \Bin\ Folder we already talked about above.

    What this Demo shows in addition, is a scenario including some these "ForeignActiveX.dlls" which
    were mentioned earlier already (using the 3 Base-Dlls of the vbRichClient-framework as an example -
    since one of these Dlls, DirectCOM.dll, is needed anyways for the approach to work).

    So, after downloading the vbRC5BaseDlls.zip - make sure you copy all 3 Dlls it contains:
    DirectCOM.dll
    vbRichClient5.dll
    vb_cairo_sqlite.dll
    Into the Demos \Bin\ Folder too.

    So, what you will need to end up with, before starting the Main-Project: RegfreeDeploymentOfDlls.vbp
    is the following FolderStructure (reusing the Schema I've introduced above):

    \RegfreeDeployment\
    .... \Bin\
    ........ DirectCOM.dll
    ........ MyTest.dll
    ........ vbRichClient5.dll
    ........ vb_cairo_sqlite.dll
    .... \Res\
    ........ BackGround.jpg
    ........ SomeSvgIcon.svg
    ........ SomePngIcon.png
    .... RegfreeDeploymentOfDlls.vbp
    .... modRegfreeDlls.bas
    .... modMain.bas
    .... fTest.frm

    If that above Folder-Structure is given, then you will succeed in running the Demo, which
    then should come up this way:



    Olaf
    Last edited by FunkyDexter; May 27th, 2015 at 11:42 AM.

  2. #2
    New Member
    Join Date
    Dec 2014
    Posts
    3

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Hello Schmidt,

    Good job and thanks very much for sharing this dll.
    I have just a question concerning Interfaces that are defined in an activeX DLL.


    Example:
    ----------

    An interface Iinterface is defined in an AX.dll,
    with one method as :

    Public Function fn ( a as Integer ) as Long
    End Function


    How can we implement above interface in a userform ,
    using "Implements" statement,

    ...
    Implements Iinterface
    ...

    as this is not the regular form,
    Dim o as CClass
    Set o= New CClass

    Thanks per advance
    --Kokou

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by aklougbo View Post
    I have just a question concerning Interfaces that are defined in an activeX DLL.

    Example:
    ----------

    An interface Iinterface is defined in an AX.dll,
    with one method as :

    Public Function fn ( a as Integer ) as Long
    End Function


    How can we implement above interface in a userform ,
    using "Implements" statement,

    ...
    Implements Iinterface
    ...

    as this is not the regular form,
    Dim o as CClass
    Set o= New CClass
    Not sure, if Office-Forms (since you used the term 'UserForm') are "regular Classes"
    (which VBA supports BTW, including the Implements-Keyword) - and if thus the
    Implements Keyword is usable in those Form-Modules.

    If the VBA-PCode-compiler doesn't complain, then you would just need to fully
    implement these interfaces (in that case your: Iinterface) - and then cast your
    UserForm-ObjectVariable (which holds a valid instance at that point in time) appropriately:

    e.g. if MyUserForm1 As UserForm is a given in Office-VBA - and you already implemented
    Iinterface in MyUserForm1, then you should be able to cast this instance to Iinterface:
    Code:
    Dim UserformOtherInterface As Iinterface
    Set UserformOtherInterface = MyUserForm1
    Though that's drifting a bit offtopic here in this thread - maybe ask either in the Office/VBA-forum,
    or in the regular VB6-forum (with a broader audience then, able to give suggestions).

    Olaf

  4. #4
    Member
    Join Date
    Sep 2015
    Posts
    46
    wrong post sorry
    Last edited by Monster4869; Sep 13th, 2015 at 01:12 PM.

  5. #5
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    341

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Useful Helper Module.

    I tried it in my VB6 project. It worked great.
    I also modified the lines a bit and ported it into my VBA projects that referenced my ActiveX DLLs, it kept working.


    A few concerns:

    1, Does this method work well in 64bit OSes.

    2, I can see it works with scrrun.dll already but how about others. How about RegExp from vbscript.dll and WinHttpRequest from winhttp.dll. I tried but got an error message: "Automation Error".

    3, IF this method works well with all types of COM/ActiveX DLLs, does it mean I can build my projects entirely on top of it. Therefore users can get my app in a zip distribution and it's gonna be convenient to include a lot useful OCXes/DLLs without registration. Is it an advisable practice.
    Last edited by bPrice; Dec 12th, 2015 at 02:57 AM.

  6. #6
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by bPrice View Post
    2, I can see it works with scrrun.dll already but how about others. How about RegExp from vbscript.dll and WinHttpRequest from winhttp.dll. I tried but got an error message: "Automation Error".
    Including system components in Regfree process is just plain wrong. I don't understand a reason behind this, but you got the error because that files are dependent from the other ones and etc. so there is no possibility to make them free from registering.

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by bPrice View Post
    A few concerns:

    1, Does this method work well in 64bit OSes.
    Yes.

    Quote Originally Posted by bPrice View Post
    2, I can see it works with scrrun.dll already but how about others. How about RegExp from vbscript.dll and WinHttpRequest from winhttp.dll. I tried but got an error message: "Automation Error".
    As MikiSoft already wrote - COM-Dlls which already come preinstalled with the System
    don't need any regfree instancing, because they *are* already registered...

    Just using CreateObject would be enough in these cases (or VBs normal New-Statement
    in case you included a reference to the COM-binary in question into your VB-Project).

    I've used scrrun.dll only, "because it's there" - and to demonstrate that DirectCOM
    works with any COM-lib (not only the RichClient-stuff).

    Quote Originally Posted by bPrice View Post
    3, IF this method works well with all types of COM/ActiveX DLLs, does it mean I can build my projects entirely on top of it.
    Therefore users can get my app in a zip distribution and it's gonna be convenient to include a lot useful OCXes/DLLs without registration.
    Is it an advisable practice.
    From my point of view, yes - though OCXes are currently not supported by this method
    (because there's a bit more complexity involved with them, due to "siting requirements".
    For OCXes I'd use SxS-manifests, which should work from XP onwards too.

    Dlls on the other hand, should work fine with either SxS or the DirectCOM-based method above.

    Olaf

  8. #8
    Hyperactive Member
    Join Date
    Sep 2014
    Posts
    341

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Thanks MikiSoft and Olaf for the comments. I guess now I am fully capable of using this method when I need.

    Shall come back and ask again, if there are other problems about it.

  9. #9
    Hyperactive Member Daniel Duta's Avatar
    Join Date
    Feb 2011
    Location
    Bucharest, Romania
    Posts
    397

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Hi Olaf,
    I am also interested in your method but I didn't manage to replicate it in my small sample. I followed your suggestions regarding the folder structure and inside the bin folder I put both DirectCOM.dll and my ActiveX file (for my demo I chose the AnimatedGif.ocx, which is a registerable library as any ocx file). My main issue is I don't now how to use properly GetInstanceFromBinFolder function as long as I don't know the second parameter, all ocx classes remaining unknown until the ocx itself is registered... Should be these classes already known by user ? Thank you.
    "VB code is practically pseudocode" - Tanner Helland
    "When you do things right, people won't be sure you've done anything at all" - Matt Groening
    "If you wait until you are ready, it is almost certainly too late" - Seth Godin
    "Believe nothing you hear, and only one half that you see" - Edgar Allan Poe

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by Daniel Duta View Post
    Hi Olaf,
    I am also interested in your method but I didn't manage to replicate it in my small sample. I followed your suggestions regarding the folder structure and inside the bin folder I put both DirectCOM.dll and my ActiveX file (for my demo I chose the AnimatedGif.ocx, which is a registerable library as any ocx file). My main issue is I don't now how to use properly GetInstanceFromBinFolder function as long as I don't know the second parameter, all ocx classes remaining unknown until the ocx itself is registered... Should be these classes already known by user ? Thank you.
    One has to keep two things (two modes) straight whilst working with regfree methods:
    - "development-mode" (in the IDE)
    - and "deployment-mode" (when running compiled)

    Only in the latter (compiled) mode, should instances be "drawn" from the \Bin\-Folder.
    Whilst in IDE-Mode, instances should be drawn from true, registered versions of the Dlls
    (which should reside in a different location from the unregistered copies in App.Path & "\Bin\..."

    That means, that whilst working inside the IDE, no LateBound-Mode for said Dlls is required,
    you can put references to said Dlls over the appropriate References-Dialogue into you project -
    and work entirely normally (early-bound) there.

    And working this way means, that any Class publically exposed by those "checked-in references",
    is visible (with its name and methods) in the VB-IDEs ObjectBrowser.

    And one doesn't have to "check-out" any references whilst preparing for "compiled deployment-mode".

    You can leave any Dll-references in there as they were (the whole project still working early-bound),
    the only things you will have to ensure, before running the compiled version are:
    1) the Dll's in the Bin-Folder have to be exact copies of the Dlls in their "registered location" on your Dev-Machine
    .. (if in doubt, check the paths to the registered Dll-Versions in the References-Dialogue)
    2) you have to ensure, that all Class-instantiations you did in IDE-Debug-Mode per New Operator, are in compile-mode
    .. done over one of the regfree methods.

    To ensure #2, I usually have a small "Instantiation-Helper"-Function for each Dll -
    e.g. for vbWidgets.dll I usually do it this way:

    Code:
    Public Function New_w(ClassName As String) As Object
      If App.LogMode Then 'we run compiled - and draw a regfree instance from the Dll in our Bin-FOlder
        Set New_w = New_c.regfree.GetInstanceEx(App.Path & "\Bin\vbWidgets.dll", ClassName)
      Else 'we run in the IDE - and use the registered version on our Dev-machine
        Set New_w = CreateObject("vbWidgets." & ClassName)
      End If
    End Function
    HTH

    Olaf

  11. #11
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    508

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Hi, very good job, I have a question.
    How do i receive events from the dll.
    That I have to put in the dll to be able to send events.

    Code:
    Private WithEvents key As capturekey
    
    Public sub add()
      Dim key As Object
      Set key = GetInstanceFromBinFolder("capturekey", "plugin")
    End Sub
    
    Private Sub key_done()
        MsgBox "done"
    End Sub
    
    Private Sub key_error()
        MsgBox "error"
    End Sub
    Could you show me a complete example?

  12. #12

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by yokesee View Post
    Hi, very good job, I have a question.
    How do i receive events from the dll.
    That I have to put in the dll to be able to send events.

    Code:
    Private WithEvents key As capturekey
    
    Public sub add()
      Dim key As Object
      Set key = GetInstanceFromBinFolder("capturekey", "plugin")
    End Sub
    
    Private Sub key_done()
        MsgBox "done"
    End Sub
    
    Private Sub key_error()
        MsgBox "error"
    End Sub
    Could you show me a complete example?
    In case your Dll (when named plugin.dll) contains a Class named CaptureKey -
    and that Class-Module has these EventDefinitions in its Declaration-Section:
    Code:
    Option Explicit
    
    Event Done()
    Event Error()
    
    '...more code in that Class
    ...then the regfree consuming-code should look like (e.g. in a Form):
    Code:
    Option Explicit
    
    Private WithEvents Key As CaptureKey
    
    Private Sub Form_Load()
      Set Key = GetInstanceFromBinFolder("plugin.dll", "CaptureKey")
    End Sub
    
    Private Sub Key_Done()
        MsgBox "done"
    End Sub
    
    Private Sub Key_Error()
        MsgBox "error"
    End Sub
    It's really not that complicated - just ensure, that you use the Helper-Function
    with the correct Parameters (the first one being the Dll, the second one being the Name of the Class)

    Olaf

  13. #13
    Hyperactive Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    508

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    But I get the "User-defined type not defined" error.
    Since the class only exists in the dll not in project.
    I'm sorry I'm not an expert on the dll.
    You could attach an example

  14. #14
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,452

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    You must reference plugin.dll in your project and then you will not get the error. Note that the plugin.dll only needs to be registered on your development machine, not any of your target machines.

  15. #15
    Hyperactive Member
    Join Date
    Jul 2017
    Posts
    362

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    ----
    Last edited by tmighty2; Apr 28th, 2018 at 04:35 PM.

  16. #16
    Junior Member
    Join Date
    Oct 2017
    Posts
    19

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Hi All

    Thanks again Olaf for these extremely useful tools you are providing to us.

    I am facing a problem I am not able to solve. Following your regfree approach, and exactly the same same example you are providing, imagine you want to share a UDT between you library and your main application so your MyTest.dll code in class cMyClass would have this look

    Code:
    Option Explicit 'just a simplified example for ones own Dll-Class - a few lines, wrapped around a VB-Collection
    
    Private mCol As New VBA.Collection
    
    
    
    Public Type vector
        x As Single
        y As Single
        z As Single
    End Type
    
    Public Property Get myVector() As vector
        myVector.x = 1
    End Property
    
    
    Public Property Get Count() As Long
      Count = mCol.Count
    End Property
    
    Public Sub Add(Item, Key)
      mCol.Add Item, Key
    End Sub
    
    Public Property Get Items() As VBA.Collection
      Set Items = mCol
    End Property
    Everithing works fine compiling the dll. But now when I run the "RegfreeDeploymentOfDlls.exe" executable in another machine i get an error of

    Name:  screenshot.2367.jpg
Views: 4042
Size:  34.7 KB

    I suppose there is an extra effort to do to be able to share UDT in a dll in a regfree application, does anyone have any clue on how to do that?

    Thank you in advance

    Nicolas

  17. #17
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,452

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    AFAIK Olaf's reg-free approach doesn't work with UDTs. I think you'll have to either use classes instead (possibly lightweight classes would be suitable), or maybe have a single .BAS module with the UDT definitions that you share with all of your projects (although I'm not sure what this would mean for passing them functions in Public classes - you might have to pass them as Variants).

  18. #18
    Junior Member
    Join Date
    Oct 2017
    Posts
    19

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Thank you jpbro for your reply! I will have a try on that

    As a fast solution I always have the common heavy vb objects as I don't use intensively these objects, but I was quite curious if there was a specific way to solve this problem via regfree type libs or other solutions (just talking without any idea on what I am saying)

  19. #19
    PowerPoster
    Join Date
    Aug 2010
    Location
    Canada
    Posts
    2,452

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Olaf will know best if there are other ways that UDTs can be handled via his RegFree approach - I think typelibs may be a solution, but I'm not sure about that (I've never actually compiled my own typelibs, so unfortunately I'm not the person to ask about that).

  20. #20
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    For most uses, typelibs don't even need to be deployed on the target machine. So just use a typelib (registered on the dev machine) in both projects and you should be all set.

  21. #21

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by jpbro View Post
    Olaf will know best if there are other ways that UDTs can be handled via his RegFree approach ...
    Nope, there are none - when I *have* to pass UDTs like this Vector3D-type into Public VB6-Dll-Classes, I usually pass:
    - the Pointer to the UDT (in a plain VB-Long-argument, then copying it over via MemCopy)
    - and if it's Arrays of UDTs, then I do it "C-Style" as well (passing a Pointer to the first element, and a second argument for the count)

    And as suggested by you already - a Lightweight-COM-Object-Instance for the Vector3D-type would only need 16-20Bytes per instance.
    Only for such a lightweight-COM-Class-Interface, a *.tlb definition would make sense (which then does not need to be shipped)...

    @nicopeis
    Whereas (on the other hand) a *.tlb for your UDT would not help to solve the problem of UDT-passing (to a COM-Dll-interface in a regfree context).
    When DEXWERX writes: "For most uses, typelibs don't even need to be deployed on the target machine..:"
    then "most uses" definitely excludes COM-Dlls, because as soon as an UDT-definition is exposed in an Interface-Def of such a Dll,
    (when contained in a Public Method-Def in a Public Class of the COM-Dll in question), you will have to ship and register the *UDT-typelib*
    on all machines your Dll is deployed to (if that UDT - and/or the Method which uses that UDT is defined in that *.tlb)

    VB6 always does an "extra Registry-Lookup", when it detects UDT-defs in an external COMponents interface
    (no matter if the loading-attempt is made in a regfree manner via DirectCOM.dll or not).
    If the Dll (or typelib) which contains the UDT is already registered, then your are fine of course,
    but for regfree usage you will have to stick to one of the already outlined recommendations:
    - either use SxS (in conjunction with a proper manifest-description, since that approach kinda "simulates a process-local registry")
    - or use regfree loading without SxS (as e.g. via DirectCOM.dll) - but then you will have to get rid of the exposed UDT in the public interface

    That said, with a bit of thought, it is often easy enough to avoid passing such "finegranular, detailed stuff" via
    a COM-Dll-interface (when the Dll gets passed an "aggregating object, one step higher in the Element-Hierarchy").

    E.g. in your case of the 3D-vector-UDT, the elements "one level up in the hierarchy" are certainly some
    "aggregations of 3D-vectors" (which then describe certain elements of your "scene", like e.g. "a cube" or "a sphere", etc.)...
    So why not pass these aggregations into your Dll (in higher order-Classes, or directly via Resource-containers like Recordsets or Collections) -
    "as a whole group of 3D-vectors in an easy to read, common container" (which then gets "split-up" and handled within the Dll internally).

    So that approach basically boils down to "rethink, where you draw the line" between your App-exe and your Helper-Dlls.
    I see my own "App-executables" mostly as "resource-managers" (responsible to load satellite-worker-binaries -
    which then also manage the "loading and distribution of resource-data" (as e.g. your 3D-point-aggregations) to these workers
    (and since these resources are usually sitting in a file or DB anyways, transferring them via Recordsets or JSON-Collections makes sense).

    HTH

    Olaf
    Last edited by Schmidt; May 6th, 2018 at 01:45 AM.

  22. #22
    Junior Member
    Join Date
    Oct 2017
    Posts
    19

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Whoa!!

    Once again, thanks a lot for these detailed explanations. I did not have any idea on the SxS approach that I will for sure investigate (following Elroy SxS tutorial)

    I think this is out of the threat discussion, but I will just give you an idea about the reason of asking

    I am writing a little library on NURBS (standard curves and surface parametrization for CAD), and I wanted to make as "light" as possible the point/vector object/UDT. I need to pass this "granularity" level data because external applications constantly will ask for these values as results of any operations (intersections, projections, etc etc). I wanted to follow DirectX8/9 approach, as they use the D3DVECTOR, D3DVECTOR2, D3DVECTOR4, D3DQUATERNION, all in UDT, but I wanted to generalize in a common N_Vector with a coordinate array that will englobe all these UDT

    Code:
    Type N_Vector
      Xi() as Single
    End Type
    That also makes a little more tricky to pass to Variant as the size of the UDT is unknown. I don't know if I will have the skills to manage it with the Lightweight Obj approach (but I will try it for sure). For the moment, due to lack of time I just solved the problem making this UDT to Object, it works and solves my problem

    When I will have something "showable" little more tested and better commented, I will upload it. May be I will help somebody as you guys help us so much

    Sorry for this out of the box answer but after you detailed answer I felt I had to tell you a bit more what I was doing

    Cheers
    Last edited by nicopeis; May 7th, 2018 at 05:51 AM.

  23. #23

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by nicopeis View Post
    ... they use the D3DVECTOR, D3DVECTOR2, D3DVECTOR4, D3DQUATERNION, all in UDT, but I wanted to generalize in a common N_Vector with a coordinate array that will englobe all these UDT

    Code:
    Type N_Vector
      Xi() as Single
    End Type
    In that case - if you want to be able to pass a variable amount of "Singles" or "Doubles",
    why not pass the SafeArrays directly into your Lib?
    (then using the Parameter-Naming, to signal to the outside, how many of them you expect to be passed).

    [code]
    'as e.g. with Method-Signatures like (3 Singles are expected):
    Public Sub DoSomethingWithVector( V3() As Single )

    'or in a return-value (4 Singles are expected in the returned result)::
    Public Function GetVectorV4(Some, Other, Params) As Single()
    [code]

    SafeArrays of simple Types (non-UDTs) conform nicely with COM-interface-specs -
    and are directly passable (or "marshallable") at the COM-Level (thus don't require extra-registry-lookups).

    Allocating (Diming, ReDiming) a little SafeArray of Singles outperforms VB6-Class-Instantiation or -Destruction speed-wise.

    If you enrich your Lib with a few "Constructor"-routines for those Saferrays, then the Client-Code can still be written efficiently:
    Code:
    Public Function NewV3(Optional ByVal x!, Optional ByVal y!, Optional ByVal z!) As Single()
       Redim NewV3(0 to 2)
       NewV3(0) = x:  NewV3(1) = y: NewV3(2) = z
    End Function
    ClientCode:
    Code:
       'init a new V3 array (with all members at zero)
       V3 = MyHelperClass.NewV3()
    Olaf

  24. #24
    Junior Member
    Join Date
    Oct 2017
    Posts
    19

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    That was my initial approach. But there are many algorithms that uses arrays of vectors.

    for example
    In a curves the control points are stored in a 1D vector array and for surfaces in 2D vectors array.
    Representing vectors as arrays of singles, would mean representing the curves control point with a 2D array of single, and for surfaces a 3D array of singles, that can be for sure doable but it is starting of being really complex to "humanely" follow the code

    That is why I decided (maybe a bad solution) to store the coordinates into a UDT and being able to manage arrays of vectors, so the control points will be for a curve Cps(x) as N_Vector and for surfaces Cps(x, x) as N_Vector independently of the dimension of these vectors

  25. #25
    Lively Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    72

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Goodmorning everyone.
    I have a VB6 application that I wrote many years ago.
    The client asked me if it was possible to allow installation without administrator privileges.
    I remembered that Olaf had developed directCom.
    I have read the posts in this thread, but I still have a doubt as to whether I can apply it to my app.
    The objects that need registration are these:
    Code:
    comct232.ocx 
    comdlg32.ocx 
    levelm.ocx 
    mscomct2.ocx 
    mscomctl.ocx 
    msdatgrd.ocx 
    MSDBRPTR.dll
    msmapi32.ocx 
    msstdfmt.dll 
    MSWINSCK.OCX 
    RICHTX32.OCX
    scrrun.dll
    STDFTIT.DLL; 
    tabctl32.ocx 
    teditbox.ocx 
    tpslave.dll 
    tskschd.dll
    vbRichClient5.dll
    I ask anyone who has used directCom, can I apply it to my case.
    ps:The activeX that I have highlighted, a visual object
    Thank you all

  26. #26

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by oldVBDev View Post
    Goodmorning everyone.
    I have a VB6 application that I wrote many years ago.
    The client asked me if it was possible to allow installation without administrator privileges.
    I remembered that Olaf had developed directCom.
    I have read the posts in this thread, but I still have a doubt as to whether I can apply it to my app.
    The objects that need registration are these:
    Code:
    comct232.ocx 
    comdlg32.ocx 
    levelm.ocx 
    mscomct2.ocx 
    mscomctl.ocx 
    msdatgrd.ocx 
    MSDBRPTR.dll
    msmapi32.ocx 
    msstdfmt.dll 
    MSWINSCK.OCX 
    RICHTX32.OCX
    scrrun.dll
    STDFTIT.DLL; 
    tabctl32.ocx 
    teditbox.ocx 
    tpslave.dll 
    tskschd.dll
    vbRichClient5.dll
    I ask anyone who has used directCom, can I apply it to my case.
    ps:The activeX that I have highlighted, a visual object
    Thank you all
    DirectCOM.dll can only be used for AX-Dlls (not for OCXes).

    But looking at your list above, most ot the things I see there could be replaced with Krools VBCCRP-tools
    (which comes with regfree-support via Manifest - and does not require a Setup).

    HTH Olaf

  27. #27
    Lively Member oldVBDev's Avatar
    Join Date
    Aug 2018
    Posts
    72

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Hi.
    Thanks to Olaf. I will follow your suggestion.

  28. #28
    Frenzied Member
    Join Date
    Nov 2010
    Posts
    1,245

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Does this continue to be viable for Windows 11?

  29. #29

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by webbiz View Post
    Does this continue to be viable for Windows 11?
    Yes, of course.

    Olaf

  30. #30
    Frenzied Member
    Join Date
    Nov 2010
    Posts
    1,245

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by Schmidt View Post
    Yes, of course.

    Olaf
    From another thread (or two) I noted some concern that Microsoft will at some point not have "just works" compatibility with VB6 apps.

    I'm only hoping that when that day comes I no longer breathe air. Getting too old to have to redo my suite of VB6 apps into another language/foundation. Perhaps my users will precede me in death? Perish the thought! ;-b

  31. #31
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    all DirectCom.dll export functions from Olaf
    Code:
    Private Type tThreadInit
      Param As Long         'User-Param (given into the ThreadMain-Method of the COM-Dll)
      hThread As Long       'filled from Thread (instantly, after STARTCOMOBJECT() returns)
      ThreadID As Long      'filled from Thread (if fully initialized, some msec after STARTCOMOBJECT())
      Reserved(511) As Byte 'reserved for Thread-Internal usage (don't touch this)
      'put your own, additional Members here...
    End Type
    
    'regfree instancing-stuff
    Declare Function GetInstanceEx Lib "DirectCOM" (StrPtr_FName&, StrPtr_ClassName&, Optional ByVal UseAlteredSearchPath As Boolean = True) As Object
    Declare Function GETINSTANCE Lib "DirectCOM" (FName$, ClassName$) As Object
    Declare Function GETINSTANCELASTERROR$ Lib "DirectCOM" () 
    Declare Function GETDLLCLASSOBJECT Lib "DirectCOM" (FName$, ClsId_16Bytes As Any) As IUnknown 'returns an IClassFactory-instance
    Declare Function UNLOADCOMDLL& Lib "DirectCOM" (FName$, ClassName$)
    
    'refree instancing on STAs (threading-stuff)
    Declare Function STARTCOMOBJECT Lib "DirectCOM" (FName$, ClassName$, TI As Any) As Long 'please pass TI "ByVal VarPtr(MyTI)", in case of User-Strings in the tThreadInit-UDT
    Declare Function GETTHREADCOUNT Lib "DirectCOM" () As Long 'threads created from within this Dll-instance
    Declare Function GETTHREADSTATUS Lib "DirectCOM" (ByVal hThread&) As Long '259=Thread running; 258=Couldn't create ThreadObj (Threadfunc. already exited); all other Values are set by the exiting ThreadMain()-Method
    Declare Function CLOSETHREADHANDLE Lib "DirectCOM" (hThread&) As Long
    'helper-routines which made it into the Exports
    Declare Function DEREF Lib "DirectCOM" (ByVal pSrc As Long) As Long
    Declare Sub ASSIGN Lib "DirectCOM" (pDst As Any, pSrc As Any)
    Declare Sub ASSIGNSWAP Lib "DirectCOM" (pDst As Any, pSrc As Any)
    Declare Sub ASSIGNADDREF Lib "DirectCOM" (pDst As Any, pSrc As Any)
    Declare Sub READTSC Lib "DirectCOM" (TSC As Currency) 'reads the CPU-TSC-register

  32. #32
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    and one problem found:
    when we use this:
    Dim o as object
    set o = GetInstance("c:\windows\sysWOW64\vbscript.dll", "RegExp")
    the ide crash, do not know why.

  33. #33

    Thread Starter
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,255

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by loquat View Post
    and one problem found:
    when we use this:
    Dim o as object
    set o = GetInstance("c:\windows\sysWOW64\vbscript.dll", "RegExp")
    the ide crash, do not know why.
    GetInstance(Ex) only scans the first TLB-resource-blob of a given Dll-file.
    The (co)class-info for "regexp" is sitting in a secondary (or third) resource-blob.

    So DirectCOM-dll will not work for the RegExp-Class in vbscript.dll ...
    but why not use CreateObject in this case (it's a system-lib, where you don't need regfree loading).

    Olaf

  34. #34
    Hyperactive Member
    Join Date
    Jan 2015
    Posts
    323

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by Schmidt View Post
    GetInstance(Ex) only scans the first TLB-resource-blob of a given Dll-file.
    The (co)class-info for "regexp" is sitting in a secondary (or third) resource-blob.

    So DirectCOM-dll will not work for the RegExp-Class in vbscript.dll ...
    but why not use CreateObject in this case (it's a system-lib, where you don't need regfree loading).
    Olaf
    just do some test, and have found both DirectCom and RC can only scan the first tlb res.

  35. #35
    New Member
    Join Date
    May 2022
    Posts
    2

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    hi, I'm using with success the directcom dll, but I have one problem, If I load a dll, then I cant replace it with a new one until I close the app or VB6 IDE. Windows says the file is already in use.

    In my project for each dll I have at least a class that wraps the dll methods, so in the class in the terminate event I set the obj loaded with the dll to nothing.

    Sometimes I also have a module that use the class I mentioned before

    class ( someDllClass ) :

    Code:
    Private obj As Object
    
    Private Sub Class_Initialize()
    
      Set obj = LoadFromDLL("somedll")
    
    End Sub
    
    public Function method()
     method = obj.method()
    end Function
    
    Private Sub Class_Terminate()
      Set obj = Nothing
    End Sub

    and in the module :

    class :

    Code:
    Private mySomeDll As SomeDllClass
    
    public function DllMethod () as string
    
    mySomeDll = new SomeDllClass
    
    DllMethod = mySomeDll.method()
    
    set mySomeDll = nothing
    
    End Sub
    
    Private Sub Class_Terminate()
      Set obj = Nothing
    End Sub
    There is any way to remove the dll from memory wihtout having to close the APP? I guess directCom is keeping the file in use ?

    In the dll, I've already unchecked the option to keep the dll in memory.

    Thanks in advance for any help !

    Marcos

  36. #36
    New Member
    Join Date
    May 2022
    Posts
    2

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    sorry, the module code has wrong code, the correct is just this :

    Code:
    Private mySomeDll As SomeDllClass
    
    public function DllMethod () as string
    
        mySomeDll = new SomeDllClass
    
        DllMethod = mySomeDll.method()
    
        set mySomeDll = nothing
    
    End Sub

  37. #37
    Addicted Member
    Join Date
    Apr 2017
    Location
    India
    Posts
    234

    Re: VB6 Regfree-Usage of your own VB- and other COM-Dlls per DirectCOM-Helper

    Quote Originally Posted by Schmidt View Post
    Think, that this topic is an important one - and deserves its own article.

    Hmm, how to begin...
    ... .. .
    ..
    .
    If that above Folder-Structure is given, then you will succeed in running the Demo, which
    then should come up this way:



    Olaf
    You are unmatchable, Olaf. You are incredibly unmatchable. Someone being an expert is one thing. But, for that 'someone' to present their expertise in such a simple manner in such a detailedly documented manner is another thing. Only a passionately kindhearted person like you can do that. My humble salutes to you from the very bottom of my heart.

    Well, recently, I needed to effect a regfree call to vbpcre2.dll (Great many Thanks to Jpbro and Tanner) and faced some hiccups. At that time, I searched in net to read more on your DirectCom.dll and it directed me to this page straightaway. Written more than 9 years ago by you but fresh like a breeze for people like me. . Helped me get more and more clarity. Thanks a TON, as always. Special thanks to the "New_w" tip in post #10 (https://www.vbforums.com/showthread....=1#post5099497).

    Kind Regards.
    Last edited by softv; Dec 28th, 2023 at 08:41 AM.

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