Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a 3rd party app that up to now talked to quickbooks using a plug-in. That plug-in no longer works with the latest versions of the windows OS, so I am replacing it using PowerShell scripts. The plug-in would instanstiate the QBXMLRP.RequestProcessor com object then open a connection and begin a session with QuickBooks, process various requests from my app then close and disconnect the connection with quickbooks. While the connection is open, a ticket provided by QuickBooks is used to process any number of requests from my app.

Using PowerShell, I execute a command line prompt to "launch" PowerShell with a PowerShell .ps1 script file to run. As the plug-in did, the PS script instantiates the com object, opens a qb connection, begins a qb session, sends a qb Request, ends the qb session, closes the qb connection.

This works fine except that unlike with the plug-in I cannot send multiple requests from my app during a single open session with QuickBooks. Once I issue the command line prompt the PS script does it's thing and PS quits and the com object is lost. Is their anyway to preserve the live instance of the qb com object and reuse it in subsequent PowerShell sessions...

My app issues a command line prompt to run PowerShell that begins a qb session...

(.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 ??

My app issuse a command line call to open PS Session 2 send a request to qb...

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

Command line call to open PS Session 3 with another request...

Command line call to open PS Session 4 with another request...

Command line call to open PS Session 5 and end the qb session and close the qb connection...

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

Is there another way to approach this using powershell?

like image 806
user278859 Avatar asked Oct 20 '22 14:10

user278859


1 Answers

I can't verify that this will work for QuickBooks, but it's possible for Excel and other COM-Objects. You have to use Marshal.GetActiveObject method:

# 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

Realated question: How to connect to existing instance of Excel from PowerShell?

UPDATE #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))"

Probably this means that 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, but given my zero knowledge of QuickBooks I can't give you any concrete instructions. Try searching QuickBooks installation directory for files containing string RequestProcessor.

UPDATE: #2

While it seems that you can't get a live instance of the QuickBooks object, this could be mitigated via interprocess communication (IPC):

  1. One script should create a QuickBooks object and then wait for input
  2. All QuickBooks interaction is done via subsequent calls to another script, that will just pass requests to the first script via IPC.

IPC could be done via Named Pipes, here is some examples:

  • Interprocess Communication in Powershell
  • Windows PowerShell and Named Pipes
like image 55
beatcracker Avatar answered Oct 24 '22 09:10

beatcracker