На компьютере с Windows 10 я вызываю QuickBooks из базы данных 4-го измерения (4D) с помощью сценария PowerShell. Сценарий вызывает QBXMLRP2.dll
, 32-битный COM-объект, для связи с QuickBooks 2019. Насколько я понимаю, если вы вызываете 32-битную dll с помощью 64-битной версии PowerShell, произойдет сбой, и наоборот. Однако я получаю разные результаты в зависимости от того, использую ли я 32-битную или 64-битную версию 4D. Это не имеет смысла для меня. Вот результаты моего теста:
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
Любые мысли о том, почему 64-битная версия PowerShell/32-битная dll работает с 32-битной версией 4D? Чего я действительно хочу, так это чтобы он работал с 64-битными версиями 4D и PowerShell.
В ответ на вопросы... Вот что я делаю. 4D сначала создает файл сценария .ps1
и сохраняет его на диск, а затем запускает PowerShell во внешнем процессе. Например, это запустит 64-битную версию PowerShell (Windows 10), и PowerShell выполнит ранее сохраненный скрипт:
"C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -file \""+$ScriptPath+"\""
Сценарий PowerShell выглядит следующим образом:
[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
Насколько я понимаю, 4D исчезает после запуска PowerShell. 4D не взаимодействует с dll. Это все PowerShell/dll (COM)/QuickBooks.
Для 4D и DLL 32, powershell 64, я думаю, что DLL не может возвращать дополнительную информацию, и powershell может объяснить это. 64 способен обрабатывать 32, а 4D в любом случае не ожидает 64-битных команд. Однако, когда вы переключаете 4D на 64, powershell может взаимодействовать с ним только с использованием 32-битной версии, поэтому, когда он запускает 64-битную команду powershell и ожидает ответа 64, DLL сокращает ее до 32-битной, вызывая ошибку. С 4D 64, PS и DLL 32 Powershell ожидает всего в 32, поэтому несоответствие между DLL и 4D никогда не проявляется, потому что powershell не пытается отправлять 64-битные команды.
Я обновил пост, чтобы, надеюсь, ответить на ваши вопросы. @Shadowzee Я не уверен, что следую логике твоего ответа. Вы говорите, что PS 64 может работать с 32-битными DLL? Если я попытаюсь запустить скрипт ps вручную в 64-битной версии PowerShell ISE, я получу ошибку «80040154 Class not Registered...», чего я и ожидаю. При запуске формы 4D, если я показываю консоль PowerShell, я вижу красную ошибку, отображаемую все, что нужно для быстрого чтения. Поэтому я почти уверен, что получаю ту же ошибку при запуске 4D.
Я добавил скрипт PowerShell в свой пост.
Позвольте мне перефразировать. Если, когда я запускаю PowerShell из 64-битного 4D с настроенной консолью PS, я вижу красные сообщения об ошибках, отображаемые в консоли, и все это быстро читается. Если я запускаю 64-битный PowerShell из 32-битного 4D, консоль открывается, остается открытой без ошибок в течение нескольких секунд, пока сценарий не завершится успешно. Последнее - то, что я подвергаю сомнению.
Это хороший результат, если бы я собирался использовать 32-битное 4D, но я буду использовать 64-битное 4D. В будущем мне, очевидно, придется использовать 32-битную PowerShell. Если Microsoft когда-нибудь решит отказаться от 32-битной поддержки, я думаю, Intuit предоставит нам 64-битную dll. Однако мне очень интересно, почему это работает при использовании 32-битного 4D.
С помощью этого форума и дополнительных исследований я теперь понимаю, что в 64-битной операционной системе Windows, если ОС обнаружит, что 32-битное приложение выполняет вызов в каталог System32, она автоматически перенаправит вызов в каталог SysWow64. . Таким образом, в моем сценарии 32-битный PowerShell всегда будет запускаться при вызове из 32-битного 4D. Обратите внимание, что это перенаправление работает только в том случае, если вызывающее приложение является 32-разрядным на 64-разрядной машине. Поэтому, если 64-битное приложение (4D) вызывает 64-битную оболочку PowerShell в каталоге System32, перенаправление не произойдет. В этом случае, если PowerShell вызывает 32-битную dll, произойдет сбой. PowerShell/dll должны соответствовать разрядности.
Если кто-то хочет принудительно запустить 64-битную версию в каталоге System32 из 32-битного приложения, можно использовать специальный каталог «Sysnative» вместо каталога System32. Обратите внимание, что это виртуальный каталог. Вы не найдете его в файловой системе. Опять же, если вы принудительно используете 64-битную Powershell, а PowerShell попытается вызвать 32-битную dll, это не удастся.
Следующая статья очень хорошо читается...
https://docs.microsoft.com/en-us/windows/desktop/winprog64/file-system-redirector
Вот моя исправленная тестовая таблица...
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
Было бы неплохо посмотреть, как вы получаете доступ к DLL.