是否可以在 PowerShell 会话之间传递 com 对象的实时实例

Is it possible to pass a live instance of a com object between PowerShell sessions

我有一个 3rd 方应用程序,到目前为止它使用插件与 quickbooks 交谈。该插件不再适用于 windows OS 的最新版本,因此我使用 PowerShell 脚本替换它。该插件将实例化 QBXMLRP.RequestProcessor com 对象,然后打开连接并开始与 QuickBooks 的会话,处理来自我的应用程序的各种请求,然后关闭并断开与 quickbooks 的连接。当连接打开时,QuickBooks 提供的票证用于处理来自我的应用程序的任意数量的请求。

使用 PowerShell,我执行一个命令行提示符到 "launch" PowerShell 和一个 PowerShell .ps1 脚本文件到 运行。正如插件所做的那样,PS 脚本实例化 com 对象,打开 qb 连接,开始 qb 会话,发送 qb 请求,结束 qb 会话,关闭 qb 连接。

这工作正常,除了与插件不同的是,我无法在与 QuickBooks 的单个打开会话期间从我的应用程序发送多个请求。一旦我发出命令行提示符,PS 脚本就会执行它,然后 PS 退出并且 com 对象丢失。无论如何,他们是否要保留 qb com 对象的活动实例并在后续的 PowerShell 会话中重用它...

我的应用向 运行 PowerShell 发出命令行提示,开始 qb 会话...

(.ps1 script)    
$myqbxmrlp = New-Object -com QBXMLRP.RequestProcessor
$myqbxmrlp.OpenConnection(...)
$ticket = $myqbxmrlp.BeginSession(....) 
$ticket | Export-CliXml $ticket (or set-content)
?? preserve the live $myqbxmrlp com object ??

我的应用程序使用命令行调用打开 PS 会话 2 向 qb 发送请求...

(.ps1 script)    
$myqbxmrlp = ?? get the live com object back ??
$ticket = Import-CliXml $ticket (or get-content)
$myqbxmrlp.ProcessRequest($ticket,....)      

命令行调用以打开 PS 会话 3 和另一个请求...

命令行调用以打开 PS 会话 4 和另一个请求...

命令行调用以打开 PS 会话 5 并结束 qb 会话并关闭 qb 连接...

(.ps1 script)    
$myqbxmrlp = ?? get the com object back ??
$ticket = Import-CliXml $ticket (or get-content)
myqbxmrlp.EndSession($ticket,....)
$myqbxmrlp.CloseConnection

还有其他方法可以使用 powershell 解决这个问题吗?

我无法验证这是否适用于 QuickBooks,但它可能适用于 Excel 和其他 COM 对象。您必须使用 Marshal.GetActiveObject 方法:

# Name of the QuickBooks COM object
$QbComObject = 'QBXMLRP.RequestProcessor'

# Try to get active instance of the QuickBooks COM object
if(-not ($myqbxmrlp = [Runtime.InteropServices.Marshal]::GetActiveObject($QbComObject)))
{
    # If we can't, then create new instance
    $myqbxmrlp = New-Object -ComObject $QbComObject
    $myqbxmrlp.OpenConnection(<#...your code...#>)
}

# Some code to process tickets...
$ticket = $myqbxmrlp.BeginSession(<#...your code...#>) 
$ticket | Export-CliXml $ticket

相关问题:How to connect to existing instance of Excel from PowerShell?

更新#1:

How do I make Marshal.GetActiveObject available. I am getting the following error...Exception calling "GetActiveObject" with "1" argument(s): "Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))"

可能这意味着 the 3rd party app is not registered as an automation server. It is not possible to get a reference to the running instance.. You could try to register file which exposes QBXMLRP.RequestProcessor (it could be dll\tlb\ocx\exe) with regsvr32.exe,但鉴于我对 QuickBooks 的了解为零,我无法为您提供任何具体说明。尝试在 QuickBooks 安装目录中搜索包含字符串 RequestProcessor.

的文件

更新:#2

虽然您似乎无法获得 QuickBooks 对象的实时实例,但这可以通过进程间通信 (IPC) 来缓解:

  1. 一个脚本应该创建一个 QuickBooks 对象,然后等待输入
  2. 所有 QuickBooks 交互都是通过对另一个脚本的后续调用完成的,该脚本只会通过 IPC 将请求传递给第一个脚本。

IPC 可以通过命名管道完成,这里有一些例子: