Thanks a lot Joe.
I'm working to finish and release a new thinBasic version I'm working on
After that I will have a look and study at the method you described.
I have created COM DLLs using PowerBASIC,
and Visual Basic 6.0,
and Visual FoxPro 9.0,
that I use with 64-bit applications,
such as 64-bit PowerShell and 64-bit JScript.
I do this by creating a DLLSurrogate for my 32-bit COM DLLs.
Ref: https://jpsoft.com/forums/threads/32...com-dll.11296/
It would be great if thincore.dll could be wrapped in a COM DLL,
so that thincore.dll could be used from 64-bit applications,
such as 64-bit PowerShell and 64-bit JScript,
via a DLLSurrogate.
Joe
Thanks a lot Joe.
I'm working to finish and release a new thinBasic version I'm working on
After that I will have a look and study at the method you described.
Last edited by ErosOlmi; 30-01-2025 at 20:58.
www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000
Here is PowerBASIC 10 source code to create a 32-bit COM DLL;
Make sure NOT to use these GUIDs in the code.
Replace the GUIDs with GUIDs that you generate on your own system.
It is important that,#COMPILE DLL "pstest" #DIM ALL #REGISTER NONE #RESOURCE TYPELIB, 1, "pstest.tlb" #COM NAME "pstest", 1.0 #COM GUID GUID$("{D8D29A89-A3ED-4DE5-A101-2DAEDB367343}") #COM TLIB ON #INCLUDE "WIN32API.inc" '32-bit regsvr32 /u pstest.dll 'Alt-F9 to compile '32-bit regsvr32 pstest.dll ' 'Source code for pstest.vbs ' 'Dim Math: Set Math = CreateObject("pbUtils_clsMath") 'dim fso: set fso=CreateObject("Scripting.FileSystemObject") 'dim stdout: set stdout=fso.GetStandardStream(1) 'stdout.WriteLine Math.ppp(6.59) 'stdout.WriteLine Math.Plus2(0) 'stdout.WriteLine Math.Plus2(10) 'Set stdout = Nothing 'set fso = Nothing 'Set Math = Nothing ' 2.99185997486114 ' 2 ' 12 '************************************************************************************************* CLASS pbUtils_clsMath GUID$("{F5786800-F9B6-4990-97D1-6DC07AAB9294}") AS COM '************************************************************************************************* ' '************************************************************************************************* INTERFACE ifcMath GUID$("{A4316390-54E3-4D15-8613-BFBBC7A28EA3}") INHERIT IDISPATCH '************************************************************************************************* METHOD ppp(ppk AS STRING) AS STRING '************************************************************************************************* ' '************************************************************************************************* ppk = ACODE$(ppk) METHOD = UCODE$(STR$(VAL(ppk) * 0.454)) END METHOD '************************************************************************************************* METHOD Plus2(theNumber AS STRING) AS STRING '************************************************************************************************* ' '************************************************************************************************* theNumber = ACODE$(theNumber) METHOD = UCODE$(STR$(VAL(theNumber) + 2)) END METHOD '************************************************************************************************* END INTERFACE '************************************************************************************************* END CLASS '************************************************************************************************* '************************************************************************************************* '*************************************************************************************************
before compiling,
you un-register this 32-bit COM DLL,
using the 32-bit Registration Server,
located in C:\Windows\SysWOW64\regsvr32.exe
I do not use cmd.exe for my console.regsvr32.exe /s /u %FileName.dll
Instead, I use TCC.exe for my console.
Here is a batch file (.btm) that I created to;
unregister the 32-bit COM DLL,
compile the 32-bit COM DLL,
register the 32-bit COM DLL,
create a DLLSurrogate for the 32-bit COM DLL,
so that it can be used from 64-bit applications,
run a test 64-bit VBScript against the 32-bit COM DLL.
This is a very simple example.@setlocal @echo off set FileName=pstest set basName=%FileName.bas set ProgID=PBUtils_clsMath REGDIR /D /F /P /V HKCR\%ProgID Gosub RegUninstall if exist pstest.log del /q pstest.log echo Compiling %basName... e:\pbwin10\bin\pbwin.exe /I"E:\pbwin10\winapi" /l /q %basName iff %? ne 0 then iff exist %FileName.log then type %FileName.log else echo Could not find %FileName.log endiff quit else dir %FileName.dll endiff Gosub RegInstall REGDIR /D /F /P /V HKCR\%ProgID Gosub MainProc drawhline %_row 0 80 2 green on black echo. :: Use CScript.exe instead of script :: if not using this .BTM from TCC script pstest.vbs endlocal quit :MainProc alias ClsID=`echo %@regquery[HKEY_CLASSES_ROOT\%ProgID\clsid\]` function ClsID=`%@regquery[HKEY_CLASSES_ROOT\%ProgID\clsid\]` iff %@ClsID[%ProgID] eq -1 then echo %ProgID is an invalid ProgID quit endiff drawhline %_row 0 80 2 green on black echo. echo Creating .reg file with DllSurrogate for Registry Gosub RegScript drawhline %_row 0 80 2 green on black echo. type surrogate.reg %_wow64dir\regedit.exe surrogate.reg Return :RegScript type <<- endtext > surrogate.reg Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\AppID\%@ClsID[%ProgID]] "DllSurrogate"="" [HKEY_CLASSES_ROOT\CLSID\%@ClsID[%ProgID]] "AppID"="%@ClsID[%ProgID]" endtext Return :RegUnInstall drawhline %_row 0 80 2 green on black echo. %_wow64dir\regsvr32.exe /s /u %FileName.dll iff %? eq 0 then echo pstest.dll has been un-registered. else echo Error with regsvr32 /u pstest.dll quit endiff drawhline %_row 0 80 2 green on black echo. Return :RegInstall drawhline %_row 0 80 2 green on black echo. %_wow64dir\regsvr32.exe /s %FileName.dll iff %? eq 0 then echo %FileName.dll has been registered. else echo Error with regsvr32 %FileName.dll quit endiff drawhline %_row 0 80 2 green on black echo. Return
Hoping that you can use it as a starting point to turn thincore.dll into ThinCoreCOM.dll
Joe
Thanks Joe,
yes, I tested that method some years ago to wrap thinCore.dll into a thinCoreX.dll COM library, but I had some problems still not resolved.
As soon as I will release current new thinBasic version I'm working on, I will retry it and post here sources, so we can work together maybe.
Ciao
Eros
www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000
Hi Eros,
No rush with this,
I know that you are busy,
but here's the PowerBASIC 10 code that I have created
which wraps the thincore.dll into a COM file,
which I can call from a 64-bit application.
This is just a concept, work-in-progress.
Much more needs to be added to make it truly useful.
I have a thinBASIC script;#COMPILE DLL "thinCoreCOM" #DIM ALL #REGISTER NONE #RESOURCE TYPELIB, 1, "thinCoreCOM.tlb" #COM NAME "thinCoreCOM", 1.0 #COM GUID GUID$("{CC2EED1A-FA8D-4C21-8CE8-4647ED56D11D}") #COM TLIB ON #INCLUDE "Win32Api.inc" #INCLUDE "ThinCore.inc" '32-bit regsvr32 /u thinCoreCOM.dll 'Alt-F9 to compile '32-bit regsvr32 thinCoreCOM.dll 'surrogate.btm thinCore_COMClass ' 'Dim tc 'Set tc = CreateObject("thinCore_COMClass") 'WScript.Echo tc.tcInit() 'WScript.Echo tc.tcRunScript("U:\kount.tbasicc") 'WScript.Echo tc.tcRelease() 'Set tc = Nothing '************************************************************************************************* ' ' wrapper for OutputDebugString SUB OutputDebug(strMsg AS STRING) EXPORT LOCAL strDebugMsg AS STRING strDebugMsg = strMsg & CHR$(13, 10) OutputDebugString BYCOPY strDebugMsg ' Use DebugView from SysInternals to view OutputDebugString END SUB CLASS thinCore_COMClass GUID$("{9611C234-B1AD-4901-9F31-8580FDE604A6}") AS COM '************************************************************************************************* ' '************************************************************************************************* INTERFACE ifcthinCore GUID$("{0672D338-45B5-433D-AC87-65E119F48DCC}") INHERIT IDISPATCH '************************************************************************************************* 'METHOD ppp(ppk AS STRING) AS STRING ''************************************************************************************************* '' ''************************************************************************************************* ' ppk = ACODE$(ppk) ' ' METHOD = UCODE$(STR$(VAL(ppk) * 0.454)) 'END METHOD ''************************************************************************************************* ' 'METHOD Plus2(theNumber AS STRING) AS STRING ''************************************************************************************************* '' ''************************************************************************************************* ' theNumber = ACODE$(theNumber) ' ' METHOD = UCODE$(STR$(VAL(theNumber) + 2)) 'END METHOD '************************************************************************************************* ' Initialize the thinCore engine METHOD tcInit() AS BYTE OutputDebug "[PBWIN] thinCore_Init()" thinBasic_Init(0, 0, "thinbasic") METHOD = 1 END METHOD ' Run a thinBasic script METHOD tcRunScript(theScript AS STRING) AS BYTE theScript = ACODE$(theScript) OutputDebug "[PBWIN] thinBasic_RunScript(theScript)" OutputDebug "[PBWIN] theScript: " + theScript thinBasic_Run(0&, theScript, %thinBasic_BufferType_IsFile,0,%FALSE, %FALSE, %FALSE, 1&,%FALSE) OutputDebug "[PBWIN] thinBasic_GetLastError()" + STR$(thinBasic_GetLastError()) METHOD = 1 END METHOD ' Release the thinCore engine METHOD tcRelease() AS BYTE OutputDebug "[PBWIN] thinCore_Release()" thinBasic_Release(0) METHOD = 1 END METHOD END INTERFACE '************************************************************************************************* END CLASS '************************************************************************************************* '************************************************************************************************* '*************************************************************************************************
...which runs fine from the console;uses "console" dim kount as integer FOR kount = 1 TO 10 PRINTl kount NEXT kount
This is my VBScript code,E:\...\thincore>e:\thinbasic\thinbasicc.exe u:\kount.tbasicc 1 2 3 4 5 6 7 8 9 10
to use the thinCore COM Wrapper,
...which runs fine using 32-bit cscript.exeE:\...\thincore>type tctest.vbs Dim tc Set tc = CreateObject("thinCore_COMClass") WScript.Echo tc.tcInit() WScript.Echo tc.tcRunScript("U:\kount.tbasicc") WScript.Echo tc.tcRelease() Set tc = Nothing
When I run it using the 64-bit cscript.exe,E:\...\thincore>cscript32 tctest.vbs 1 2 3 4 5 6 7 8 9 10 E:\...\thincore>which cscript32 cscript32 is an alias : C:\Windows\SysWOW64\cscript.exe //nologo %$
it runs, but nothing is output.
Output from DebugView...E:\...\thincore>cscript.exe //nologo tctest.vbs 1 1 1
So, no errors, and my kount.tbasicc script executes,[13988] [PBWIN] thinCore_Init() [13988] [PBWIN] thinBasic_RunScript(theScript) [13988] [PBWIN] script$: U:\kount.tbasicc [13988] [PBWIN] thinBasic_GetLastError() 0 [13988] [PBWIN] thinCore_Release()
and produces the output,
when run via the thinCore Com Wrapper,
using a 32-bit application,
such as 32-bit cscript.exe
The problem is running it from a 64-bit app,
as the program is run,
but no output is produces.
I'm not sure what is going on,
but preliminary debugging points to the use of the DLLSurrogate.
I have other PowerBASIC COM Servers that I have developed,
and I have had no problem with them being called from a 64-bit app.
I think the best direction to take,
would be to put the source code from thinCore.dll
directly into thinCoreCOM.bas
and eliminate the thinCore.dll completly.
Not now,
but when you have time.
As it is,
I can now run a thinBASIC script from
32-bit Visual Basic 6.0,
32-bit VBScript,
32-bit JScript,
32-bit Visual FoxPro 9.0,
32-bit PowerShell,
via the thinCoreCOM COM Server,
which is what I have wanted to do for some time now.
Joe
The DLLSurrogate applies only to the COM dll it is assigned in the registry.
In this case,
thinCoreCOM.DLL
thinCoreCOM.DLL is treated as a 64-bit dll now,
but when thinCoreCOM.DLL attempts to call a 32-bit dll,
in this case thinCore.dll,
it cannot.
Thus,
all of the thinCore.dll code will have to be placed into thinCoreCOM.DLL,
so that thinCoreCOM.DLL does not have to call an external dll.
Joe
No, I was incorrect.
The 32-bit thinCore.dll can be called from the 64-bit thinCoreCOM.dll
I put a WAITKEY in my thinBASIC code,
which showed that the c:\windows\SysWOW64\DLLHost.exe is called,
a new console is created,
and the output is displayed there,
not on the console from where 64-bit CScript.exe was started.
Without the WAITKEY,
it was so fast,
that I never saw what was happening.
Not sure why a new console is created when running from 64-bit CScript.exe,
but the existing console is used with 32-bit CScript.exe.
Still, having all of the code in one place,
thinCoreCOM.dll,
should hopefully fix the console issue with 64-bit activation.
Joe
Of course!
When running the thinCoreCOM.dll from a 32-bit application,
no dllSurrogate is required,
which is why output goes to the console from which CScript.exe was started.
When running the thinCoreCOM.dll from a 64-bit application,
a dllSurrogate is required,
which is why output does not go to the console from which CScript.exe was started,
and instead,
goes to a new console that has to be created.
Joe
Last edited by Joe Caverly; 03-02-2025 at 22:06.
I've added a new method to thinCoreCOM...
As an example, from VBScript, I can do the following...' Run a thinBasic scriptline METHOD tcRunScriptLine(theScript AS STRING) theScript = ACODE$(theScript) OutputDebug "[PBWIN] thinBasic_RunScriptLine(theScript)" OutputDebug "[PBWIN] thescript: " + theScript thinBasic_Run(0&, theScript, %thinBasic_BufferType_IsScript,0,%FALSE, %FALSE, %FALSE, 1&,%FALSE) OutputDebug "[PBWIN] thinBasic_GetLastError()" + STR$(thinBasic_GetLastError()) END METHOD
...which displays 10 on the console.WScript.Echo tc.tcRunScriptLine("uses " + CHR(34) + "console" + CHR(34) + " : dim a as long = 10 : print a")
DebugView output...
Joe[13104] [PBWIN] thinCore_Init() [13104] [PBWIN] thinBasic_RunScriptLine(theScript) [13104] [PBWIN] thescript: uses "console" : dim a as long = 10 : print a [13104] [PBWIN] thinBasic_GetLastError() 0 [13104] [PBWIN] thinCore_Release()
Last edited by Joe Caverly; 04-02-2025 at 20:57.
In my build.btm I have changed to using the 32-bit CScript.exe instead of the 64-bit CScript.exe
Joe:: which cscript32 :: cscript32 is an alias : C:\Windows\SysWOW64\cscript.exe //nologo %$ cscript32 tcTest.vbs
Bookmarks