-
Sep 24th, 2022, 04:12 PM
#1
Registry Free Object Instantiation using DirectCOM & RC6
There are a few variations of this kind of reg-free "bootstrapping" module already circulating, but I wanted to write one that was highly commented in the hope that it will help some newcomers better understand how to write their VB6/RC6 apps in a way that works without requiring their DLLs to be registered, and also how to package their app & DLLs so that everything will work smoothly when deployed on a user's computer without registration.
Source Code
Now includes a demo App, DLL, and RPC DLL, bug-fixes and uses the latest RC6.dll
Latest Version Updated September 3, 2024 - Download here:
Rc6RegFree7.zip
NOTE: This is a work in progress - if there are any parts of the code or comments that you still find confusing, please ask! I'll try my best to clarify and update the comments so that we have a comprehensive document that will be easily understood by newcomers to RC6.
Things are described in much more detail in the module comments, so I suggest you read them all. Here are the basics:
THE PRIMARY GOAL OF THIS MODULE is to be universal and foundational code for VB6 apps using DirectCOM.dll and RC6.dll to instantiate ActiveX objects without requiring the use of regsvr32/installers on your application's end users' computers. This approach will be called "DirectCOM reg-free" or simply "reg-free" for the rest of this post.
By "Universal" I mean that this module should be added to EVERY VB6/RC6 project.
By "Foundational" I mean that this module should be the FIRST THING that you add to every project you create that will be using RC6/DirectCOM reg-free.
TO USE THIS MODULE
When you start writing a new app, add MRegFree.bas to your project via the Project > Add Module menu.
Next, add a reference to RC6.dll via the Project > References menu.
You will now have everything you need to start writing a reg-free VB6/RC6 application. The main thing to understand is that there are now 5 ways to instantiate new objects in your code instead of only the regular 2 ways (New keyword and CreateObject function). The choice of which method to use depends on the type of object you want to create.
Creating Objects Using the VB6 New Keyword
Use the built-in VB6 New keyword to instantiate objects that you know will be registered on the user's computer, or that are built-in to the VB6 runtime or STDOLE. For example, VB6 Collections, StdFont objects, StdPicture objects, etc... should always be instantiated via the New keyword.
Creating Objects Using the VB6 CreateObject Method
Use the built-in VB6 CreateObject method to instantiate objects that you know will be registered on the end user's computer late-bound. This would include things like Excel.Application, Word.Application, Shell objects, etc...
Creating Objects Using the RC6 New_C Method
Use the New_C method to instantiate all RC6 objects excluding Cairo objects. This instantiation will occur without touching the registry, so RC6.dll does not need to be registered on your end user's computer. Example:
Code:
Dim RS As RC6.cRecordset
Set RS = New_C.Recordset ' Creates an RC6.cRecordset object instance in the RS variable without touching the registry. Use this instead of the more familiar "Set RS = New Recordset" approach (which would require a trip to the registry).
Creating Objects Using the RC6 Cairo Method
Use the Cairo method to create new RC6 Cairo objects (as well as use all other Cairo features). Instantiating Cairo objects in this way will will not touch the registry, so RC6.dll does not need to be registered on yur end user's computer.
For example, to create a new image surface to draw against:
Code:
Dim Srf As RC6.cCairoSurface
Set Srf = Cairo.CreateSurface(100, 100) ' Creates a ne RC6.cCairoSurface instance (100x100 pixels) in the Srf variable without touching the registry.
Creating Objects Using the mRegFree CreateObjectRegfree Method
Use the CreateObjectRegfree method to create objects from DLLs that you will distribute with your application (that is, DLLs that aren't distributed by Microsoft with Windows), but that you don't want to register on the user's computer. For example, if you have created your own DLL called MyDll.dll with a class called MyClass, and a method call MySub, you can use it reg-free as follows (make sure you have added a reference to MyDll.dll in the VB6 Project > References menu):
Code:
Dim MC As MyDll.MyClass
Set MC = CreateObjectRegfree("MyDll.dll", "MyClass") ' Creates an instance of MyDll.MyClass in the variable named MC without touching the registry.
MC.MySub
If you stick to the above rules when writing your code, you will be able to distribute your application and all related DLLs without registering the DLLs on your end user's computer. This makes it possible to distribute your app without an installer if you like (for example, in a ZIP archive).
Packaging & Distributing Your Application
This topic is also discussed in more detail in the source comments, but the basics are:
Your main application folder should contain the following:
- The EXE that your users will launch to use your app.
- A folder called System that will include the RC6 DLLs and any other DLLs used by your app.
- Other folders that you want to include with your app, such as a Help (for your documentation).
The System sub-folder should contain the following:
- RC6.dll (available at www.vbrichclient.com)
- cairo_sqlite.dll (available at www.vbrichclient.com)
- DirectCOM.dll (available at www.vbrichclient.com)
- RC6Widgets.dll (optional - only needed for apps that use RC6 Forms instead of VB6 Forms - available at www.vbrichclient.com).
- Any of your own DLLs that your app references.
- Any satellite/helper EXEs that your main app shells out to for any purpose.
- Any third-party DLLs that your main app references, and that aren't already distributed by Microsoft with Windows. For example, Chilkat's DLLs.
- A folder named RPCDlls - this is optional, and only needed for client-server applications that use remote procedure calls (RPC) with the RC6 cRpcListener and cRpcConnection classes.
Your main application folder can then be compressed into a ZIP archive, or packaged into a self-extracting executable for distribution to end users. Users can extract the contents anywhere they like, and launch the main application EXE to start using your software immediately - no registration of components required.
I hope this code proves useful to someone out there. Questions, comments, an criticisms are always welcome.
Last edited by jpbro; Oct 15th, 2024 at 02:47 PM.
-
Sep 24th, 2022, 04:13 PM
#2
Re: Registry Free Object Instantiation using DirectCOM & RC6
MRegFree.bas has the following 13 public methods that you will use to create objects without touching the registry, and to work with files stored in your app's folder and sub-folders.
New_c
Code:
Public Function New_C() As RC6.cConstructor
Returns an RC6.cConstructor object that is used for instantiating new non-Cairo RC6 objects without touching the registry.
Cairo
Code:
Public Function Cairo() As RC6.cCairo
Returns an RC6.cCairo object that can be used for constructing/instantiating new Cairo objects without touching the registry, and for accessing all other Cairo objects/methods.
CreateObjectRegfree
Code:
Public Function CreateObjectRegfree(ByVal p_DllName As String, ByVal p_ClassName As String, Optional ByVal p_ProgId As String = vbNullString) As Object
Returns a newly instated object created from any DLL in the App\System\ folder.
- Pass the file name of the DLL that holds the class you want to create to tThe p_DllName parameter. For example, "MyDll.dll"
- Pass the name of the class that you want to create to the p_ClassName parameter. For example, "cMyClass"
- Optionally pass the ProgID of the class you want to create to the p_ProgId parameter. This is only needed for creating objects where the ProgID does not match the file name of the DLL (less the file extension) and the ClassName. For example, if you have a DLL call MyDllVersion5.dll and a class called cMyClass, but the ProgID for that class is MyDll.cMyClass (no version # in the ProgID), the you should pass "MyDll.cMyClass" to the p_ProgId parameter.
GetOrCreateObjectRegfree
Code:
Public Function GetOrCreateObjectRegfree(ByVal p_DllName As String, ByVal p_ClassName As String, Optional ByVal p_ProgId As String = vbNullString, Optional ByVal p_OverrideCacheKey As String) As Object
Returns a cached object instance (or creates a newly instantiated object and caches it for subsequent use) of any DLL in the App\System\ folder. This can improve performance if you have an class objects that you use throughout your project that you only need a single instance of. For example, a string helpers class, crypto class, or something along those lines. Can also be useful in situations where instantiation is "heavy" (classes that build lookup table on first access for example).
GetOrCreateThreadHandler
Code:
Public Function GetOrCreateCreateThreadHandler(ByVal p_DllFileNameOrPath As String, ByVal p_ClassName As String, Optional ByVal p_ThreadKey As String = vbNullString, Optional ByVal p_ThreadPriority As enmThreadPriority = THREAD_PRIORITY_NORMAL) As RC6.cThreadHandler
Returns an existing RC6.cThreadHandler object if one is found that matches the passed key, or creates a new cThreadHandler object if none is found with the passed key cached object instance or if no thread key is passed. When no thread key is passed a random key will be generated, which is useful for creating throw away thread objects. If a DLL file name is passed with no path portion, then PathAppSystem is assumed.
NOTE that class objects created by this method MUST come from compiled DLLs, and not from classes that exist only in the IDE.
ClearRegfreeObjectCache
Frees all memory/objects held by the regfree objects cache used by GetOrCreateObjectRegfree.
RemoveFromRegfreeObjectCache
Code:
Public Sub RemoveFromRegfreeObjectClass(ByVal p_DllName As String, ByVal p_ClassName As String, Optional ByVal p_OverrideCacheKey As String)
Removes a single object from the regfree objects cache.
PathApp
Code:
Public Function PathApp() As String
Returns the full path to your application's root folder. For example, "C:\Users\Me\Documents\MyApp"
Unlike VB6's built-in App.Path method, this method always returns the main application root folder even when called from a DLL or EXE in a sub-folder of the main app root folder. For example, if you have a DLL in "C:\Users\Me\Documents\MyApp\System", PathApp will return "C:\Users\Me\Documents\MyApp" when called from code in the DLL. App.Path would return the DLL's path (e.g. ""C:\Users\Me\Documents\MyApp\System")
Also unlike VB6's built-in App.Path method, this method always includes a trailing backslash.
This method works with paths with Unicode characters.
PathAppSystem
Code:
Public Function PathAppSystem() As String
This method returns the path to your app's System sub-folder. For example, if your main app is running from "C:\Users\Me\Documents\MyApp", this method will return "C:\Users\Me\Documents\MyApp\System".
This method always returns the path with a trailing backslash, and is compatible with paths containing Unicode characters.
PathAppSystemRpc
Code:
Public Function PathAppSystemRpc() As String
This method returns the path to your app's RPCDlls sub-folder. For example, if your main app is running from "C:\Users\Me\Documents\MyApp", this method will return "C:\Users\Me\Documents\MyApp\System\RPCDlls".
This method always returns the path with a trailing backslash, and is compatible with paths containing Unicode characters.
RegFreeOption
Code:
Public Property Get RegfreeOption(ByVal p_Option As e_RegfreeOption) As String
Public Property Let RegfreeOption(ByVal p_Option As e_RegfreeOption, p_Value As String)
Get/Set regfree options (like folder names & debug printing options). The current options enum is:
Code:
Public Enum e_RegfreeOption
regfreeopt_AppFolderName ' Name of the base folder whe compiled binaries will reside. Default is "Build"
regfreeopt_AppSystemFolderName ' Name of the system folder where compiled RC6 DLLs, non-RPC DLLs, and satellite EXEs will reside (sub folder of the base app folder). Default is "System"
regfreeopt_AppSystemRpcFolderName ' Name of the folder where compiled RPC DLLs will reside (sub folder of the System folder). Default is "RPCDlls"
regfreeopt_DebugPrintOption ' Controls app information output for debug messages
[_regfreeopt_First] = regfreeopt_AppFolderName
[_regfreeopt_Last] = regfreeopt_DebugPrintOption
End Enum
NOTE: By default reg-free options are private and not accessible outside the MRegFree module. If you want to change any options, change the RegfreeOptionsPublic conditional compilation constant to True.
IsRunningInIde
Returns True if running in the IDE. This is a convenience function that is Private by default, but can be made Public by setting the IsRunningInIde conditional compilation constant to True if you want to use it.
DebugPrint
Code:
Public Sub DebugPrint(ByVal p_Message As String, Optional ByVal p_PrintOptions As e_DebugPrintOption = dbgopt_UseDefaultOption)
Prints a message to the Immediate window AND the Windows Debug message stream (where it can be viewed by tools like DbgView), optionally including app info (Name, PID, ThreadID). If you don't want to use this function, you can disable it by setting the IncludeDebugPrint conditional compilation constant to False, but it can be quite handy for debugging, particularly in RPC application scenarios.
Relevant DebugPrint Enums:
Code:
Public Enum e_DebugPrintOption
dbgopt_UseDefaultOption = -1
dbgopt_MessageOnly ' Print passed message only, NO app info like name, PID, ThreadID
dbgopt_PrintAppName = 1 ' Print App Name. Can be combined with other dbgopt_PrintApp* flags
dgbopt_PrintAppPid = 2 ' Print App Process ID (pid#)
dgbopt_PrintAppThreadId = 4 ' Print App Thread ID (tid#)
dgbopt_PrintAll = (dbgopt_PrintAppName Or dgbopt_PrintAppPid Or dgbopt_PrintAppThreadId) ' Print all available App Info
End Enum
Last edited by jpbro; Sep 3rd, 2024 at 07:47 PM.
-
Sep 25th, 2022, 03:25 AM
#3
Fanatic Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
-
Oct 23rd, 2022, 04:02 PM
#4
Re: Registry Free Object Instantiation using DirectCOM & RC6
I've improved the documentation in Post #2.
-
Oct 23rd, 2022, 06:54 PM
#5
Re: Registry Free Object Instantiation using DirectCOM & RC6
Updated to get rid of the LongPtr stuff as it was unnecessary since RC6.dll and DirectCOM.dll are only available as 32-bit libraries so we'll never be using them from a 64-bit process. At least not until/unless 64-bit versions are released.
-
Nov 2nd, 2022, 04:21 PM
#6
Re: Registry Free Object Instantiation using DirectCOM & RC6
Nov 2, 2022 Update (in first post) fixes a problem where a compiled DLL can't find RC6.dll when it is being run from a parent app that is running in the VB6 IDE.
This issue was discovered while working on this demonstration app: https://www.vbforums.com/showthread....mo-With-Source
-
Aug 24th, 2023, 03:14 PM
#7
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
Updated to get rid of the LongPtr stuff as it was unnecessary since RC6.dll and DirectCOM.dll are only available as 32-bit libraries so we'll never be using them from a 64-bit process. At least not until/unless 64-bit versions are released.
This is really excellent work, and we all appreciate your inline documentation and thorough attention to details.
Keep those LongPtr defs nearby, because we will drag RC6 kicking and screaming into 64bit with TwinBasic.
haha only half kidding, don't beat me Olaf
-
Aug 25th, 2023, 09:28 AM
#8
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
I've improved the documentation in Post #2.
A couple of questions:
1. Since I am already using SxS for Krool's VBCCR, an anchor control, and Eduardo's NewTab, can I include RC6 to the SxS as well?
2. Can this method be used to replace the components listed in #1?
3. I'm regrettably not using Cairo on this project, so can I leave the those off the list and only include RC6.DLL and DirectCOM.dll ?
-
Aug 25th, 2023, 10:48 AM
#9
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by taishan
A couple of questions:
1. Since I am already using SxS for Krool's VBCCR, an anchor control, and Eduardo's NewTab, can I include RC6 to the SxS as well?
2. Can this method be used to replace the components listed in #1?
3. I'm regrettably not using Cairo on this project, so can I leave the those off the list and only include RC6.DLL and DirectCOM.dll ?
1) Yes.
2) No.
3) Please always include all of the Dlls of the RC6-package in your deployment
Olaf
-
Aug 25th, 2023, 11:16 AM
#10
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by Schmidt
1) Yes.
2) No.
3) Please always include all of the Dlls of the RC6-package in your deployment
Olaf
Would you recommend putting all the controls and DLLs into a .res resource?
-
Aug 25th, 2023, 10:05 PM
#11
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by taishan
This is really excellent work, and we all appreciate your inline documentation and thorough attention to details.
Thank you, I hope you found it useful.
-
Aug 25th, 2023, 10:14 PM
#12
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by taishan
Would you recommend putting all the controls and DLLs into a .res resource?
No, because your executable then runs a higher risk, to be flagged as a "false positive" by virus-scanners.
There's nothing wrong with a honest \Bin\ Subfolder (which contains all libraries and ocxes your exe needs) -
sitting beside your MyApp.exe (in a simple deployment-zip).
Olaf
-
Aug 25th, 2023, 10:15 PM
#13
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by taishan
A couple of questions:
1. Since I am already using SxS for Krool's VBCCR, an anchor control, and Eduardo's NewTab, can I include RC6 to the SxS as well?
2. Can this method be used to replace the components listed in #1?
3. I'm regrettably not using Cairo on this project, so can I leave the those off the list and only include RC6.DLL and DirectCOM.dll ?
Olaf has answered definitively already, but I will put my own $0.02 in:
1. Yes, but if you are already using SxS for DLLs then I recommend avoiding this DirectCOM reg-free approach.
2. ?? Olaf replied with a firm "no" but I'm not sure what "components listed in #1" you are referring to?
3. Always bring the full set of DLLs along - it's called "cairo_sqlite.dll", so there's more there than just Cairo. It's only a few MB anyway, so not too much to worry about package size-wise.
-
Aug 25th, 2023, 10:20 PM
#14
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
2. ?? Olaf replied with a firm "no" but I'm not sure what "components listed in #1" you are referring to?
I understood it as containing at least 2 OCXes (Krools VBCCR- and Eduardos TabCtl-OCX) -
and the DirectCOM.dll based approach does work only for COM-Dlls (not OCXes).
Olaf
-
Aug 25th, 2023, 10:23 PM
#15
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by taishan
Would you recommend putting all the controls and DLLs into a .res resource?
I do not recommend this for the DirectCOM reg-free approach described above. While others report success with the .res approach, I can only recommend that if you use anything that I've written here, then you should put all your DLLs in the folder that "PathAppSystem" points to.
-
Aug 30th, 2023, 08:02 PM
#16
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
Olaf and jpbro, thanks to both of you for your suggestions, it gives me many options to consider!
-
Aug 31st, 2023, 01:11 AM
#17
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by Schmidt
I understood it as containing at least 2 OCXes (Krools VBCCR- and Eduardos TabCtl-OCX) -
and the DirectCOM.dll based approach does work only for COM-Dlls (not OCXes).
Thank you. I got tripped-up on the "replace" bit and the "can I include RC6" bit.
@taishan: Nothing is being "replaced" component-wise - the components are the components. SxS or DirectCOM are just different ways to give you registry free access to those components/objects. There are pros and cons to either approach, but definitely don't use DirectCOM for OCXes - as Olaf said, it won't work.
-
Mar 20th, 2024, 03:16 PM
#18
Re: Registry Free Object Instantiation using DirectCOM & RC6
Updated March 20, 2024:
Added new public methods:
GetOrCreateObjectRegfree
Code:
Public Function GetOrCreateObjectRegfree(ByVal p_DllName As String, ByVal p_ClassName As String, Optional ByVal p_ProgId As String = vbNullString, Optional ByVal p_OverrideCacheKey As String) As Object
Returns a cached object instance (or creates a newly instated object and caches it for subsequent use) of any DLL in the App\System\ folder. This can improve performance if you have an class objects that you use throughout your project that you only need a single instance of. For example, a string helpers class, crypto class, or something along those lines. Can also be useful in situations where instantiation is "heavy" (classes that build lookup table on first access for example).
ClearRegfreeObjectCache
Frees all memory/objects held by the regfree objects cache used by GetOrCreateObjectRegfree.
RemoveFromRegfreeObjectCache
Code:
Public Sub RemoveFromRegfreeObjectClass(ByVal p_DllName As String, ByVal p_ClassName As String, Optional ByVal p_OverrideCacheKey As String)
Removes a single object from the regfree objects cache.
Also:
Minor code improvements
PathImage now raises an error if you try to get the image filename while in the IDE (not determinable).
Added comments, and improved some wrong/confusing comments.
-
Mar 21st, 2024, 06:12 AM
#19
Re: Registry Free Object Instantiation using DirectCOM & RC6
How does this "DirectCOM.dll" achieve reg-free registration without using SxS manifests? Does it call some undocumented API functions?
My guess is that it isn't an ActiveX DLL since that would defeat the purpose of being reg-free...
-
Mar 21st, 2024, 06:38 AM
#20
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by VanGoghGaming
How does this "DirectCOM.dll" achieve reg-free registration without using SxS manifests? Does it call some undocumented API functions?
My guess is that it isn't an ActiveX DLL since that would defeat the purpose of being reg-free...
Only Olaf can answer that definitively - DirectCOM.dll is closed source. But you're right about it not being an ActiveX DLL, it's a standard DLL with the following magic function that instantiates and returns an object created from a class in an ActiveX DLL:
Code:
Private Declare Function GetInstanceEx Lib "DirectCOM" (spFName As Long, spClassName As Long, Optional ByVal UseAlteredSearchPath As Boolean = True) As Object
-
Mar 21st, 2024, 09:48 AM
#21
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by VanGoghGaming
How does this "DirectCOM.dll" achieve reg-free registration without using SxS manifests? Does it call some undocumented API functions? My guess is that it isn't an ActiveX DLL since that would defeat the purpose of being reg-free...
I now make everything Portable and Registration Free. I believe this should decimate support issues with the end user.
I use LaVolpe's SxS manifest editor for registry free usage of VBCCR and Eduardo's NewTab01.
Edit: Elroy has an excellent tutorial on the mechanics of SxS. He masterfully describes every step, and eliminates the mystery.
I use the "Public Property" reg-free method for RC6 because I cannot get the "Sub Main" method working in both the IDE (registered RC6) and standalone (nothing registered on user machine, with all RC6 DLLs and beforementioned ActiveX controls placed in the \Bin folder.)
I am anxious to test out jpbro's updates! Cheers
Last edited by taishan; Mar 21st, 2024 at 09:16 PM.
-
Mar 21st, 2024, 11:37 AM
#22
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by taishan
I am anxious to test out jpbro's updates! Cheers
Don't get too excited yet, there's still one puzzle I'm working on re: IDE and compiled differences.
The good news: Right now everything works great when compiled, and most things work just as well in the IDE (all the regfree stuff is working perfectly whether in the IDE or compiled in my tests so far).
The bad news: I'm not happy with the differences in what PathApp and PathImage return between the IDE and when compiled. In the IDE the paths are relative to the source code folder, but compiled they are relative to the compiled binary folder. I'd like them to be the same, but I don't know the best way to go about this.
One option would be to force binaries to be compiled to a sibling folder of a source folder, so something like:
Code:
C:\MyApp\Source\ <- Project folders and Source files go here
C:\MyApp\Bin\ <- Main EXE Binary files go here
C:\MyApp\Bin\System <- DLLs and Satellite app binaries go here
C:\MyApp\Bin\System\RPCDlls <- Remotely callable DLLs go here.
Under such a scheme, we can detect if we are in the the IDE and determine the binary folder easily - BUT - not everyone will want to arrange their files this way, and I'm trying to make the code as generic as possible.
Another possibility would be to have some kind of Options methods which would allow you to set the base folder when in the IDE, but this would require devs to configure stuff every time they use the module, which is a bit of a pain.
Anyway, I'm open to ideas here if anyone has any.
-
Mar 21st, 2024, 09:22 PM
#23
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
...One option would be to force binaries to be compiled to a sibling folder of a source folder, so something like:
Code:
C:\MyApp\Source\ <- Project folders and Source files go here
C:\MyApp\Bin\ <- Main EXE Binary files go here
C:\MyApp\Bin\System <- DLLs and Satellite app binaries go here
C:\MyApp\Bin\System\RPCDlls <- Remotely callable DLLs go here.
Under such a scheme, we can detect if we are in the the IDE and determine the binary folder easily - BUT - not everyone will want to arrange their files this way, and I'm trying to make the code as generic as possible.
I think the trade-offs of hard-coding project files so "it just works" is not a bad proposal... Thanks for all of your hard work! Cheers
-
Mar 21st, 2024, 10:16 PM
#24
Re: Registry Free Object Instantiation using DirectCOM & RC6
Thanks taishan. The more I think about it, the more I wonder if it makes more sense to make the Path* methods Private so that they are only used by regfree module, and leave the path handling outside of the regfree stuff to the app.
-
Mar 21st, 2024, 10:59 PM
#25
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
...it makes more sense to make the Path* methods Private so that they are only used by regfree module, and leave the path handling outside of the regfree stuff to the app.
That sounds very accessible for every object/method involved. Interested to see what you come up with! Cheers
-
Mar 22nd, 2024, 09:56 AM
#26
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
Only Olaf can answer that definitively - DirectCOM.dll is closed source. But you're right about it not being an ActiveX DLL, it's a standard DLL with the following magic function that instantiates and returns an object created from a class in an ActiveX DLL:
Code:
Private Declare Function GetInstanceEx Lib "DirectCOM" (spFName As Long, spClassName As Long, Optional ByVal UseAlteredSearchPath As Boolean = True) As Object
I would venture a wild guess that at least some of the secret sauce involves checking the TypeLib information exposed by ActiveX DLLs created with VB6. I've just put together a quick example of a generic "RegFree" function that uses the "LoadTypeLibEx" API function to expose the ITypeLib interface of a VB6 ActiveX DLL. It uses Fafalone's "oleexp" TypeLib to save time with all the API declarations and unnecessary calls to "DispCallFunc":
mdlRegfree BAS module (you need to supply your own ActiveX DLL for reg-free testing)
Code:
Option Explicit
Private Const MEMBERID_NIL As Long = -1, DllGetClassObject As String = "DllGetClassObject"
Private ParamTypes(0 To 10) As Integer, ParamValues(0 To 10) As Long, lParamCount As Long, pInterface As Long, vParams As Variant, _
sCurrentLib As String, lpDllGetClassObject As Long, IID_IClassFactory As oleexp.UUID, IID_IUnknown As oleexp.UUID
Public Function RegFree(sLibName As String, sClassName As String) As Object
Dim RegFreeIUnknown As IUnknown, tliTypeLibInfo As oleexp.ITypeLib, i As Long, lpTypeAttr As Long, sInterfaceName As String, objClassFactory As oleexp.IClassFactory
Set tliTypeLibInfo = LoadTypeLibEx(sLibName, REGKIND_NONE) ' REGKIND_NONE calls LoadTypeLib without the registration process enabled
With tliTypeLibInfo
For i = 0 To .GetTypeInfoCount - 1
If .GetTypeInfoType(i) = TKIND_COCLASS Then ' Loop through the CoClasses exposed by this ActiveX DLL
With .GetTypeInfo(i)
With .GetRefTypeInfo(.GetRefTypeOfImplType(0)) ' Get the type description of the interface implemented by this class
.GetDocumentation MEMBERID_NIL, sInterfaceName, vbNullString, 0, vbNullString
End With
If sClassName = Mid$(sInterfaceName, 2) Then ' InterfaceName is ClassName prefixed with an underscore (_ClassName)
If sLibName <> sCurrentLib Then
sCurrentLib = sLibName: lpDllGetClassObject = GetModuleHandle(ByVal StrPtr(sCurrentLib)) ' Check if the library had already been loaded
If lpDllGetClassObject = 0 Then lpDllGetClassObject = CoLoadLibrary(sCurrentLib, True)
lpDllGetClassObject = GetProcAddress(lpDllGetClassObject, DllGetClassObject)
If IID_IClassFactory.Data1 = 0 Then CopyMemory IID_IClassFactory.Data4(0), 504403158265495.5712@, 8: IID_IUnknown = IID_IClassFactory: IID_IClassFactory.Data1 = 1
End If
lpTypeAttr = .GetTypeAttr
If lpTypeAttr Then InvokeObj Nothing, lpDllGetClassObject, lpTypeAttr, VarPtr(IID_IClassFactory), VarPtr(objClassFactory) ' Call DllGetClassObject to retrieve the class object from the DLL object handler
.ReleaseTypeAttr lpTypeAttr
objClassFactory.CreateInstance Nothing, IID_IUnknown, RegFreeIUnknown ' Create an instance of this class
Set RegFree = RegFreeIUnknown: Exit Function ' Get the IDispatch implementation of this class
End If
End With
End If
Next i
End With
End Function
Private Function InvokeObj(Interface As IUnknown, vtbOffset As Long, ParamArray ParamsArray() As Variant) As Variant
Dim lRet As Long
InvokeObj = S_FALSE: pInterface = ObjPtr(Interface): vParams = ParamsArray
For lParamCount = 0 To UBound(vParams): ParamTypes(lParamCount) = VarType(vParams(lParamCount)): ParamValues(lParamCount) = VarPtr(vParams(lParamCount)): Next lParamCount
If pInterface Then
lRet = DispCallFunc(ByVal pInterface, vtbOffset, CC_STDCALL, vbLong, lParamCount, ParamTypes(0), ParamValues(0), InvokeObj)
ElseIf vtbOffset > 1024 Then
lRet = DispCallFunc(ByVal pInterface, vtbOffset, CC_STDCALL, vbLong, lParamCount, ParamTypes(0), ParamValues(0), InvokeObj)
End If
If lRet Then Debug.Print Hex$(lRet)
End Function
Public Sub Main()
Dim objRegFree As Object
Set objRegFree = RegFree(App.Path & "\Bin\SomeActiveX.dll", "SomeClass")
' Set objRegFree = RegFree2(App.Path & "\Bin\SomeActiveX.dll", "SomeClass")
If objRegFree Is Nothing Then Debug.Print "Object is Nothing!" Else objRegFree.CallSomeMethod
End Sub
mdlRegfree2 BAS module (same version as above but without any dependencies, doesn't require a TypeLib)
Code:
Option Explicit
Private Const MEMBERID_NIL As Long = -1, REGKIND_NONE As Long = 2, CC_STDCALL As Long = 4, S_OK As Long = 0, S_FALSE As Long = 1, PTR_SIZE As Long = 4, DllGetClassObject As String = "DllGetClassObject"
Private Enum vtbInterfaceOffsets
' ITypeLib
ITypeLib_FindName = 11 * PTR_SIZE
' ITypeInfo
ITypeInfo_GetTypeAttr = 3 * PTR_SIZE
ITypeInfo_ReleaseTypeAttr = 19 * PTR_SIZE
' IClassFactory
IClassFactory_CreateInstance = 3 * PTR_SIZE
End Enum
Private Declare Function LoadLibraryW Lib "kernel32" (ByVal lpLibFileName As Long) As Long
Private Declare Function GetModuleHandleW Lib "kernel32" (ByVal lpModuleName As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function DispCallFunc Lib "oleaut32" Alias "#146" (ByVal pvInstance As Long, ByVal oVft As Long, ByVal cc As Long, ByVal vtReturn As VbVarType, ByVal cActuals As Long, prgvt As Any, prgpvarg As Any, pvargResult As Variant) As Long
Private Declare Function LoadTypeLibEx Lib "oleaut32" Alias "#183" (ByVal lpszFile As Long, ByVal RegKind As Long, pptLib As IUnknown) As Long
Private ParamTypes(0 To 10) As Integer, ParamValues(0 To 10) As Long, lParamCount As Long, pInterface As Long, vParams As Variant, _
sCurrentLib As String, lpDllGetClassObject As Long, IID_IClassFactory(0 To 1) As Currency, IID_IUnknown(0 To 1) As Currency
Public Function RegFree2(sLibName As String, sClassName As String) As Object
Dim RegFreeIUnknown As IUnknown, ITypeLib As IUnknown, ITypeInfo As IUnknown, IClassFactory As IUnknown, rgMemId As Long, pcFound As Long, lpTypeAttr As Long
If LoadTypeLibEx(StrPtr(sLibName), REGKIND_NONE, ITypeLib) = S_OK Then ' REGKIND_NONE calls LoadTypeLib without the registration process enabled
pcFound = 1: InvokeObj ITypeLib, ITypeLib_FindName, StrPtr(sClassName), 0&, VarPtr(ITypeInfo), VarPtr(rgMemId), VarPtr(pcFound)
If rgMemId = MEMBERID_NIL Then
If sLibName <> sCurrentLib Then
sCurrentLib = sLibName: lpDllGetClassObject = GetModuleHandleW(StrPtr(sCurrentLib)) ' Check if the library had already been loaded
If lpDllGetClassObject = 0 Then lpDllGetClassObject = LoadLibraryW(StrPtr(sCurrentLib))
lpDllGetClassObject = GetProcAddress(lpDllGetClassObject, DllGetClassObject)
If IID_IClassFactory(1) = 0 Then IID_IClassFactory(0) = 0.0001@: IID_IClassFactory(1) = 504403158265495.5712@: IID_IUnknown(1) = IID_IClassFactory(1)
End If
InvokeObj ITypeInfo, ITypeInfo_GetTypeAttr, VarPtr(lpTypeAttr)
If lpTypeAttr Then InvokeObj Nothing, lpDllGetClassObject, lpTypeAttr, VarPtr(IID_IClassFactory(0)), VarPtr(IClassFactory) ' Call DllGetClassObject to retrieve the class object from the DLL object handler
InvokeObj ITypeInfo, ITypeInfo_ReleaseTypeAttr, lpTypeAttr
InvokeObj IClassFactory, IClassFactory_CreateInstance, 0&, VarPtr(IID_IUnknown(0)), VarPtr(RegFreeIUnknown) ' Create an instance of this class
Set RegFree2 = RegFreeIUnknown ' Get the IDispatch implementation of this class
End If
End If
End Function
Private Function InvokeObj(Interface As IUnknown, vtbOffset As Long, ParamArray ParamsArray() As Variant) As Variant
Dim lRet As Long
InvokeObj = S_FALSE: pInterface = ObjPtr(Interface): vParams = ParamsArray
For lParamCount = 0 To UBound(vParams): ParamTypes(lParamCount) = VarType(vParams(lParamCount)): ParamValues(lParamCount) = VarPtr(vParams(lParamCount)): Next lParamCount
If pInterface Then
lRet = DispCallFunc(ByVal pInterface, vtbOffset, CC_STDCALL, vbLong, lParamCount, ParamTypes(0), ParamValues(0), InvokeObj)
ElseIf vtbOffset > 1024 Then
lRet = DispCallFunc(ByVal pInterface, vtbOffset, CC_STDCALL, vbLong, lParamCount, ParamTypes(0), ParamValues(0), InvokeObj)
End If
If lRet Then Debug.Print Hex$(lRet)
End Function
Here's the demo project for who's interested: RegFree.zip (contains both versions above)
Now since the above code is pretty much "run-of-the-mill", I suspect that Olaf's DirectCOM does something more to warrant it being closed source and all. Maybe he could chime in with some insight, I'm always keen to learn new stuff!
Last edited by VanGoghGaming; Apr 7th, 2024 at 08:48 PM.
-
Mar 22nd, 2024, 01:38 PM
#27
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by VanGoghGaming
I suspect that Olaf's DirectCOM does something more to warrant it being closed source and all.
Yes, on top of that -
it allows stable regfree instancing of COM-Classes on their own threaded STAs also in the VB6-IDE.
(that's the main-reason it comes encapsulated in a Std-Dll).
Olaf
-
Mar 22nd, 2024, 02:33 PM
#28
Re: Registry Free Object Instantiation using DirectCOM & RC6
I did see DirectCOM.dll referencing "CreateThread" and a whole bunch of other "multi-threading" API functions so this confirms what I've been suspecting all along. So I guess this code wouldn't work in a BAS module if you wanted multi-threading in the IDE as well... Cheers!
-
Mar 26th, 2024, 11:32 AM
#29
Re: Registry Free Object Instantiation using DirectCOM & RC6
OK, I finally have something I'm happy with (for my own uses at least), and hopefully the latest version will be useful to others too.
MRc6Base.bas is now MRegFree.bas and it includes a whole slew of bugs fixes, enhancements, and new features.
New features include:
RegFreeOption
Code:
Public Property Get RegfreeOption(ByVal p_Option As e_RegfreeOption) As String
Public Property Let RegfreeOption(ByVal p_Option As e_RegfreeOption, p_Value As String)
Get/Set regfree options (like folder names & debug printing options). The current options enum is:
Code:
Public Enum e_RegfreeOption
regfreeopt_AppFolderName ' Name of the base folder whe compiled binaries will reside. Default is "Build"
regfreeopt_AppSystemFolderName ' Name of the system folder where compiled RC6 DLLs, non-RPC DLLs, and satellite EXEs will reside (sub folder of the base app folder). Default is "System"
regfreeopt_AppSystemRpcFolderName ' Name of the folder where compiled RPC DLLs will reside (sub folder of the System folder). Default is "RPCDlls"
regfreeopt_DebugPrintOption ' Controls app information output for debug messages
[_regfreeopt_First] = regfreeopt_AppFolderName
[_regfreeopt_Last] = regfreeopt_DebugPrintOption
End Enum
NOTE: By default reg-free options are private and not accessible outside the MRegFree module. If you want to change any options, change the RegfreeOptionsPublic conditional compilation constant to True.
IsRunningInIde
Returns True if running in the IDE. This is a convenience function that is Private by default, but can be made Public by setting the IsRunningInIde conditional compilation constant to True if you want to use it.
DebugPrint
Code:
Public Sub DebugPrint(ByVal p_Message As String, Optional ByVal p_PrintOptions As e_DebugPrintOption = dbgopt_UseDefaultOption)
Prints a message to the Immediate window AND the Windows Debug message stream (where it can be viewed by tools like DbgView), optionally including app info (Name, PID, ThreadID). If you don't want to use this function, you can disable it by setting the IncludeDebugPrint conditional compilation constant to False, but it can be quite handy for debugging, particularly in RPC application scenarios.
Relevant DebugPrint Enums:
Code:
Public Enum e_DebugPrintOption
dbgopt_UseDefaultOption = -1
dbgopt_MessageOnly ' Print passed message only, NO app info like name, PID, ThreadID
dbgopt_PrintAppName = 1 ' Print App Name. Can be combined with other dbgopt_PrintApp* flags
dgbopt_PrintAppPid = 2 ' Print App Process ID (pid#)
dgbopt_PrintAppThreadId = 4 ' Print App Thread ID (tid#)
dgbopt_PrintAll = (dbgopt_PrintAppName Or dgbopt_PrintAppPid Or dgbopt_PrintAppThreadId) ' Print all available App Info
End Enum
There is also now a full demo that includes a main application, DLL, and RPC DLL.

To try the demo:
- Make sure you have the latest version (6.0.15 at the time of writing) of RC6 registered on your development machine (available at https://vbrichclient.com/#/en/Downloads.htm)
- Copy the RC6 binaries to \Rc6Regfree\Demo\Build\System\ (DO NOT register them here).
- Open \Rc6Regfree\Demo\Source\MyRc6RpcDll1\MyRc6RpcDll1.vbp and compile the DLL to Demo\Build\System\RPCDlls\
- Open \Rc6Regfree\Demo\Source\MyRc6Dll1\MyRc6Dll1.vbp and compile the DLL to Demo\Build\System\
- Open \Rc6Regfree\Demo\Source\MainRc6App\MainRc6App.vbp and compile the EXE to Demo\Build\ NOTE: Before you can build the main app, you may need to fix a broken reference to MyRc6Dll. This can be done in the Project > References menu.
- Start \Rc6Regfree\Demo\Build\MainRc6App.exe and try out the demo, or open \Rc6Regfree\Demo\Source\Rc6Regfree.vbg to open the full demo project group and step along with the code while you run the demo app.
RC6 Templates
I've also included a Templates folder that includes template projects for RC6 EXE, RC6 ActiveX DLL, and RC6 ActiveX RPC DLL projects. These can be copied to C:\Program Files (x86)\Microsoft Visual Studio\VB98\Template\Projects to add templates to the New Project window in the VB6 IDE if desired.

Enjoy!
Last edited by jpbro; Mar 26th, 2024 at 05:47 PM.
-
Mar 26th, 2024, 06:49 PM
#30
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
Wow! This is really fantastic work!
Can you include instaniating vbWidgets? I am getting Cairo fever... I want to learn a new skill that I can use on all platforms.
I don't want to be a cromagnon and just stick ReexRe's code in here, as you have a whole different inIDE scheme going...
Cheers bro
Code:
Public Function NewWidget(ClassName As String) As Object
If App.LogMode Then 'we run compiled
'// Set NewWidget = New_c.RegFree.GetInstanceEx(App.Path & "\vbRC5BaseDlls\vbWidgets.dll", ClassName)
Set NewWidget = New_C.RegFree.GetInstanceEx(sBinPath & "vbWidgets.dll", ClassName)
Else 'we run in the IDE, so we create the instance from the registered version
Set NewWidget = CreateObject("vbWidgets." & ClassName)
End If
End Function
Last edited by taishan; Mar 28th, 2024 at 07:43 PM.
-
Mar 29th, 2024, 09:56 AM
#31
Re: Registry Free Object Instantiation using DirectCOM & RC6
Thanks taishan, glad you like what you see 
Regarding a way to instantiate vbWidgets, there are a few different approaches - all with their upsides and downsides - and I'm not firmly decided on what approach I prefer yet.
Reexre's function is fine, but I have a bit of a natural aversion (rightly or wrongly) to passing the string class name as there's no intellisense and it is easy to make a typo. Granted even a minimal amount of testing would reveal the typo problem, but it just "feels" wrong to me. Reexre's approach also returns an Object, so you don't get the benefit of Intellisense, which can make it a pain to work with.
One advantage for using string class names is that it is easy to use new widget classes as they become available, just start using the new class name. Another advantage is that the code is short and easy to reason about/audit.
In any case, Reexre's code could be written to handle Firehacker's MakeTrue InIde approach with my MRegFree module like so:
Code:
Public Function NewWidget(ClassName As String) As Object
Dim l_InIde As Boolean
#If UseInlineIdeCheck Then
Debug.Assert MakeTrue(l_InIde)
#Else
l_InIde = IsRunningInIde
#End If
If l_InIde Then
' We run in the IDE, so we create the instance from the registered version
Set NewWidget = CreateObject("vbWidgets." & ClassName)
Else
' Not in the IDE, so we create the instance from the registered version
Set NewWidget = New_C.RegFree.GetInstanceEx(PathAppSystem & "vbWidgets.dll", ClassName)
End If
End Function
Another approach is to have single functions for each widget that return a strongly typed widget variable. This is the approach I use in JPBFileFinder. The advantages are that intellisense works, and you can add extra "constructor" parameters that help you get the widget instantiated with things like position and dimensions set without requiring a bunch of extra property lets for everything. The downsides are that you have to update the codebase every time a new Widget is added to vbWidgets, and the code is comparatively quite verbose.
There may be other approaches too - I'm all ears if anyone has any interesting suggestions.
PS: Looking at the MWidgets.bas code in JPBFileFinder, I see that it could use a rewrite to use the new MRegFree module, so I'll see if I can find that time to do that soon.
-
Apr 2nd, 2024, 08:00 PM
#32
Addicted Member
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
Another approach is to have single functions for each widget that return a strongly typed widget variable. This is the approach I use in JPBFileFinder. The advantages are that intellisense works, and you can add extra "constructor" parameters that help you get the widget instantiated with things like position and dimensions set without requiring a bunch of extra property lets for everything. The downsides are that you have to update the codebase every time a new Widget is added to vbWidgets, and the code is comparatively quite verbose.
Thanks for your detailed response. I now understand what you mean by typo caveats in ClassName. intellisense would be excellent to have! I think it's maybe the most important feature for beginners like me.
 Originally Posted by jpbro
PS: Looking at the MWidgets.bas code in JPBFileFinder, I see that it could use a rewrite to use the new MRegFree module, so I'll see if I can find that time to do that soon.
Hijack thread alert: Is it too much trouble to add a right-click shell extension "Search with JPBFileFinder" - it's the best search tool I've found. I just forget to fire it up when I'm searching...
-
Sep 3rd, 2024, 12:11 PM
#33
Re: Registry Free Object Instantiation using DirectCOM & RC6
I'm now happily using this module in all my new projects (including 32-bit twinBasic projects). Updated first post to include latest changes:
- Updated to latest RC6.dll
- Some bug fixes
- Fixed some misleading/confusing comments and added additional comments for more clarity
-
Sep 3rd, 2024, 12:12 PM
#34
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by taishan
Hijack thread alert: Is it too much trouble to add a right-click shell extension "Search with JPBFileFinder" - it's the best search tool I've found. I just forget to fire it up when I'm searching...
Sorry for the late reply. Kids are back at school, so I should have some time to revisit JPBFileFinder. I've mostly been working on the twinBasic version of it though, so I will probably continue with that.
-
Sep 3rd, 2024, 12:58 PM
#35
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
I'm now happily using this module in all my new projects (including 32-bit twinBasic projects). Updated first post to include latest changes:
- Updated to latest RC6.dll
- Some bug fixes
- Fixed some misleading/confusing comments and added additional comments for more clarity
Hi Jason - couldn't check for myself because the latest attachment-link (in post #1) doesn't work currently...
but I've added a "ModuleName"-function recently to your module:
Code:
Public Function ModuleName(Optional ByVal FullPath As Boolean) As String
Dim S$: S = Space$(260)
S = Left$(S, GetModuleFileName(0, StrPtr(S), Len(S)))
ModuleName = IIf(FullPath, S, Mid$(S, InStrRev(S, "\") + 1))
End Function
... which I then used, to enhance the InIde-condition this way:
Code:
If so_NewC Is Nothing Then
' We have no cConstructor object yet, so let's create one
' We use a Static variable so instantiation only occurs a maximum of ONE-TIME in the app lifetype
If l_InIde Or StrComp(ModuleName, "VB6.EXE", vbTextCompare) = 0 Then
' In the IDE we'll use the normal VB6 New keyword to instantiate via the registry
Set so_NewC = New RC6.cConstructor
Else
This was necessary for threaded Dll-Classes, which internally want to make use of RC6-Classes as well...
Since these threaded Dlls are usually precompiled (also when run in the VB6-IDE) -
they should load their internal RC6-dependencies "non-regfree" as well, as long as their "host-process" is detected as the VB6-IDE.
Regards,
Olaf
-
Sep 3rd, 2024, 03:32 PM
#36
Re: Registry Free Object Instantiation using DirectCOM & RC6
Thanks a lot Olaf, I've made the changes as recommended (will update the first post soon), but I just want to make sure I understand the need for this change:
A) This is needed for developer written VB6 Active DLLs that instantiate RC6 classes via New_c.
B) These DLLs are compiled (and would therefore return False for InIde checks).
C) These DLLs are currently being hosted by VB6.exe (that is, the parent that is creating classes from these DLLs is currently running in the IDE).
D) The DLL Class objects have been instantiated via the RC6 ThreadObjectCreate or ThreadObjectConnect methods.
Is that correct?
Also, if/when you have the time I have another RC6 cThreadHandler question - AFAIK threaded DLL classes that are being referenced by a thread handler must always be compiled (that is, there's nothing similar to the RPC DebugMode method of running threaded classes while uncompiled for debugging in the IDE). Is this also correct?
Thanks for any clarifications.
-
Sep 3rd, 2024, 04:39 PM
#37
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by jpbro
A) This is needed for developer written VB6 Active DLLs that instantiate RC6 classes via New_c.
B) These DLLs are compiled (and would therefore return False for InIde checks).
C) These DLLs are currently being hosted by VB6.exe (that is, the parent that is creating classes from these DLLs is currently running in the IDE).
D) The DLL Class objects have been instantiated via the RC6 ThreadObjectCreate or ThreadObjectConnect methods.
Is that correct?
Yes.
 Originally Posted by jpbro
Also, if/when you have the time I have another RC6 cThreadHandler question - AFAIK threaded DLL classes that are being referenced by a thread handler must always be compiled (that is, there's nothing similar to the RPC DebugMode method of running threaded classes while uncompiled for debugging in the IDE).
Is this also correct?
Yes.
When I develop the Public Methods of such (later threaded) Dlls,
I validate them beforehand in a Testing-Project-Group - and call these Methods directly (for debugging);
making sure they behave "formally correct and stable" (putting their later async-result-delivery aside...).
Olaf
-
Sep 3rd, 2024, 05:08 PM
#38
Re: Registry Free Object Instantiation using DirectCOM & RC6
DirectCOM.dll
rc6.dll,
Are there any plans to release a 64-bit product?
-
Sep 3rd, 2024, 06:04 PM
#39
Re: Registry Free Object Instantiation using DirectCOM & RC6
 Originally Posted by Schmidt
Yes.
When I develop the Public Methods of such (later threaded) Dlls,
I validate them beforehand in a Testing-Project-Group - and call these Methods directly (for debugging);
making sure they behave "formally correct and stable" (putting their later async-result-delivery aside...).
Great, thanks for confirming - that's what I've done myself for the few times I've used cThreadHandler, just wanted to make sure I wasn't missing anything.
-
Sep 3rd, 2024, 07:03 PM
#40
Re: Registry Free Object Instantiation using DirectCOM & RC6
Latest update (in first post) includes the fix that Olaf mentioned in Post #35 (thanks again Olaf!) as well as a new "Test Threaded DLL" button to test a simple thread creation/call to a method that uses the RC6 cCrypt class to ensure regfree stuff is working when objects are running in a thread.

NOTE: for the thread test to work, you must compile MyRc6Dll1.dll that is included with the demo project group to the Build\System folder.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|