powershelldllcomquickbooks4d-database

64bit PowerShell calls the 32bit DLL


On a Windows 10 computer, I am calling QuickBooks from a 4th Dimension (4D) database using a PowerShell script. The script calls the QBXMLRP2.dll, a 32bit COM object, to talk to QuickBooks 2019. As I understand, if you call a 32bit dll using a 64bit version of PowerShell, it will fail and vice versa. However, I'm getting different results depending on if I use a 32bit or 64bit version of 4D. This makes no sense to me. Here are my test results:

OS  4D  PowerShell  DLL   Result
64  32  32          32    OK
64  32  64          32    OK //According to my research this should not work!

64  64  32          32    OK
64  64  64          32     X //According to my research this is the expected behavior

Any thoughts on why the 64bit version of PowerShell/32bit dll works with the 32 bit version of 4D? What I really want is for it to work with the 64bit versions of 4D and PowerShell.

In response to questions... Here is what I am doing. 4D first creates a .ps1 script file and saves it to disk, then launches PowerShell in an external process. For example, this would launch 64bit PowerShell (Windows 10) and PowerShell would execute the previously saved script:

"C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -file \""+$ScriptPath+"\""

The PowerShell script looks like this:

[String]$requestXML = '<?xml version="1.0" ?>
<?qbxml version="2.0"?><QBXML>
<QBXMLMsgsRq onError="stopOnError">
<CompanyQueryRq requestID="1">
</CompanyQueryRq>
</QBXMLMsgsRq>
</QBXML>'
$myQBXMLRP = New-Object -com QBXMLRP2.RequestProcessor
$myQBXMLRP.OpenConnection2("qb4D","CCFolioPro",1)
$ticket = $myQBXMLRP.BeginSession("C:\Company Files\Cadinha & Co.,LLC.QBW",$myQBXMLRP.qbFileOpenDoNotCare)
$myQBXMLRP.ProcessRequest($ticket, $requestXML) > $env:_4D_OPTION_OUTPUT_STREAM
$myQBXMLRP.EndSession($ticket)
$myQBXMLRP.CloseConnection()
"Stop" > $env:_4D_OPTION_STOP_TOKEN

As I understand, 4D is out of the picture once PowerShell is launched. 4D does not interact with the dll. It's all PowerShell/dll (COM)/QuickBooks.


Solution

  • With the help off this forum and a bit more research, I understand now that in a 64bit windows operating system, if the OS detects that a 32bit application is making a call to the System32 directory, it will automatically redirect the call to the SysWow64 directory. Thus in my scenario 32bit PowerShell will always run when called from 32bit 4D. Note that this redirect is only in play when the calling app is 32bit on a 64bit machine. So if a 64bit application (4D) cals the 64bit PowerShell in the System32 directory the redirect will not occur. In this case if a 32bit dll is invoked by PowerShell, it will fail. PowerShell/dll must match bitness.

    If one wants to force the 64bit version in the System32 directory to run from a 32bit application, the special "Sysnative" directory can be used instead of the System32 directory. Note that this is a virtual directory. You will not find it in the file system. Again,if you do force the use of the 64bit Powershell and PowerShell tries to invoke a 32bit dll, it will fail.

    The following article is a very good read...

    https://learn.microsoft.com/en-us/windows/desktop/winprog64/file-system-redirector

    Here is my corrected testing chart...

    OS  4D  PowerShell  DLL   Result
    64  32  32          32    OK
    64  32  64-OS->32   32    OK //OS redirected to 32bit PS. Expected behavior!
    
    64  64  32          32    OK
    64  64  64          32     X //No redirect. Expected behaviour