0

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.

deralbert
  • 856
  • 2
  • 15
  • 33
JohnBDH
  • 11
  • 3
  • It would be nice to see how you're accessing the dlls. – montonero May 31 '19 at 07:33
  • For the 4D and DLL 32, powershell 64, I think the DLL cannot return extra information and powershell can account for this.64 is capable of handling 32 and 4D isn't expecting 64 bit commands anyway. When you switch the 4D to 64 however, powershell can only interact with it using 32 bit, so when it runs a 64 bit powershell command and expects a 64 reply, the DLL shortens it to 32 bit causing an error. With the 4D 64, PS and DLL 32, powershell is expecting everything in 32 so the mismatch between the DLL and 4D never comes into play because powershell doesn't try to send any 64 bit commands. – Shadowzee May 31 '19 at 07:35
  • I updated the post to hopefully answer your questions. @Shadowzee I'm not surre I follow the logic of your answer. Are you saying that PS 64 is capable of handling 32 bit DLLs? If I try to run the ps script manually in the 64bit version of PowerShell ISE I get the "80040154 Class not registered..." error, which is what I expect. When launching form 4D, if I show the PowerShell Console I can see the red error displayed all beit to quick to read. So I am prettry sure I am getting the same errror when being launched by 4D. – JohnBDH May 31 '19 at 17:47
  • I added the PowerShell script to my post. – JohnBDH May 31 '19 at 18:32
  • Let me rephrase. If when I launch PowerShell from 64bit 4D with the PS Console set to display I can see the red error mesages display in the console, all beit to quick to read. If I launch 64bit PowerShell from 32bit 4D, the console opens up, remains open, without error, for a few seconds until the script completes successfully. The latter is what I am questioning. – JohnBDH May 31 '19 at 20:10
  • It's a good result if I were going to be using 32bit 4D, but I will be using 64bit 4D. Going forward I will obviously have to use 32bit PowerShell. Should microsoft ever decide to drop 32bit support I guess it will be up to Intuit to provide us with a 64bit dll. I am very interested, however, into why it works when using 32bit 4D. – JohnBDH May 31 '19 at 20:10

1 Answers1

1

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
JohnBDH
  • 11
  • 3