【问题标题】:Is it possible to pass a live instance of a com object between PowerShell sessions是否可以在 PowerShell 会话之间传递 com 对象的实时实例
【发布时间】:2015-04-19 20:43:00
【问题描述】:

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

使用 PowerShell,我执行命令行提示符以“启动”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 Session 2 向 qb 发送请求...

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

使用另一个请求打开 PS Session 3 的命令行调用...

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

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

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

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

【问题讨论】:

    标签: powershell quickbooks


    【解决方案1】:

    我无法验证这是否适用于 QuickBooks,但它适用于 Excel 和其他 COM-Objects。你必须使用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:

    如何使 Marshal.GetActiveObject 可用。我得到了 以下错误...使用“1”调用“GetActiveObject”的异常 参数:“操作不可用(来自 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.。您可以尝试使用regsvr32.exe 注册公开QBXMLRP.RequestProcessor(可能是dll\tlb\ocx\exe)的文件,但鉴于我对QuickBooks 的了解为零,我无法给您任何具体说明。尝试在 QuickBooks 安装目录中搜索包含字符串 RequestProcessor 的文件。

    更新:#2

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

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

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

    【讨论】:

    • 如何使 Marshal.GetActiveObject 可用。我收到以下错误...使用“1”参数调用“GetActiveObject”的异常:“操作不可用(来自 HRESULT 的异常:0x800401E3(MK_E_UNAVAILABLE))”
    • @user278859 查看更新,不确定是否有帮助,但这是我能做的最好的了。
    • 感谢您对此的帮助。我认为是时候继续前进并接受我将不得不为每个查询打开和关闭连接。它会起作用,只是如果我要提出多个请求,它似乎有点慢。我想知道我应该怎么回答这个问题。将其标记为已回答、不回答或删除?
    • @user278859 绝对不要删除它。如果您 100% 确定我是对的,则标记为已回答,或者只是不回答,让其他人有机会回答。即使没有答案,问题本身也可以使其他一些 QuickBooks 用户免于徒劳地尝试使其工作。顺便说一句,看看更新,也许这个解决方法对你有用。
    • IPC 看起来确实可行,但我已经继续前进了。只是没有时间保证进一步追求这一点。再次感谢您的建议。我暂时不回答这个问题。如果其他人能够证明 IPC 可以工作,那么我会将其标记为已回答。再次感谢。
    猜你喜欢
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 2017-06-16
    • 2017-12-12
    • 2011-06-17
    • 1970-01-01
    • 2015-12-14
    相关资源
    最近更新 更多