Results 1 to 10 of 10

Thread: Using thincore.dll with 64-bit applications

  1. #1
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6

    Using thincore.dll with 64-bit applications

    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

  2. #2
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,828
    Rep Power
    10
    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

  3. #3
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6
    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.
    #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
    
    '*************************************************************************************************
    '*************************************************************************************************
    '*************************************************************************************************
    
    It is important that,
    before compiling,
    you un-register this 32-bit COM DLL,
    using the 32-bit Registration Server,
    located in C:\Windows\SysWOW64\regsvr32.exe

    regsvr32.exe /s /u %FileName.dll
    
    I do not use cmd.exe for my console.

    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.

    @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
    
    This is a very simple example.

    Hoping that you can use it as a starting point to turn thincore.dll into ThinCoreCOM.dll

    Joe

  4. #4
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,828
    Rep Power
    10
    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

  5. #5
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6
    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.

    #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
    '*************************************************************************************************
    '*************************************************************************************************
    '*************************************************************************************************
    
    I have a thinBASIC script;
    uses "console"
    dim kount as integer
    FOR kount = 1 TO 10
      PRINTl kount
    NEXT kount
    
    ...which runs fine from the console;
    E:\...\thincore>e:\thinbasic\thinbasicc.exe u:\kount.tbasicc 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    This is my VBScript code,
    to use the thinCore COM Wrapper,
    E:\...\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
    
    ...which runs fine using 32-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 %$
    
    When I run it using the 64-bit cscript.exe,
    it runs, but nothing is output.
    E:\...\thincore>cscript.exe //nologo tctest.vbs
    1
    1
    1
    
    Output from DebugView...
    [13988] [PBWIN] thinCore_Init()
     [13988] [PBWIN] thinBasic_RunScript(theScript) 
    [13988] [PBWIN] script$: U:\kount.tbasicc 
    [13988] [PBWIN] thinBasic_GetLastError() 0 
    [13988] [PBWIN] thinCore_Release()
    
    So, no errors, and my kount.tbasicc script executes,
    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

  6. #6
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6
    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

  7. #7
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6
    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

  8. #8
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6
    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.

  9. #9
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6
    I've added a new method to thinCoreCOM...
    ' 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
    
    As an example, from VBScript, I can do the following...
    WScript.Echo tc.tcRunScriptLine("uses " + CHR(34) + "console" + CHR(34) + " : dim a as long = 10 : print a")
    
    ...which displays 10 on the console.

    DebugView output...
    [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()
    
    Joe
    Last edited by Joe Caverly; 04-02-2025 at 20:57.

  10. #10
    Member
    Join Date
    Feb 2023
    Location
    London, Ontario, Canada
    Posts
    47
    Rep Power
    6
    In my build.btm I have changed to using the 32-bit CScript.exe instead of the 64-bit CScript.exe
    :: which cscript32
    :: cscript32 is an alias : C:\Windows\SysWOW64\cscript.exe //nologo %$
    cscript32 tcTest.vbs
    
    Joe

Similar Threads

  1. Using thincore.dll with Visual Basic 6.0
    By Joe Caverly in forum thinBasic General
    Replies: 19
    Last Post: 13-01-2025, 11:40
  2. Where is latest thincore.inc file?
    By gddeluca in forum thinBasic General
    Replies: 4
    Last Post: 05-07-2021, 00:39
  3. Getting to controls of existing applications
    By RPrinceton711 in forum UI (User Interface)
    Replies: 1
    Last Post: 28-04-2019, 10:17
  4. ARM-Based Windows 8 Will Not Run x86 Applications.
    By ErosOlmi in forum Technology
    Replies: 2
    Last Post: 20-09-2011, 07:06
  5. About your applications
    By ErosOlmi in forum Web and Forum
    Replies: 0
    Last Post: 03-05-2009, 12:01

Members who have read this thread: 9

Posting Permissions

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