Paul E. Schoen
2006-12-23 06:38:10 UTC
I posted something on this 6/30/06, but now I am revisiting it and I hope
someone can help.
I am making a client program which connects to an Automation Server of a
running application. I can make the connection, but it fails if I
disconnect and reconnect. Actually I have found that my application creates
another instance of the running application (as a process reported by
Windows Task Manager). I must close and reopen the running application
before my client can reconnect. The sample programs I have available are in
VB (in Excel) and C.
The applicable Delphi code is as follows:
=======================================================================
var
powerLogicApp: IPowerLogicApp;
powerLogicDoc: IPowerLogicDoc; // was Variant;
procedure Connect;
begin
if( powerLogicApp = nil ) then begin
powerLogicApp := CoApplication_.Create;
powerLogicDoc := powerLogicApp.ActiveDocument; end;
end;
procedure Disconnect;
begin
// powerLogicApp.Quit; // This closes the application
powerLogicApp := nil;
powerLogicDoc := nil;
end;
======================================================================
The visual basic code in Excel is as follows:
======================================================================
Dim WithEvents powerLogicApp As PowerLogic.Application
Dim WithEvents powerLogicDoc As PowerLogic.Document
Private Sub Connect()
On Error GoTo OnErrorGetObject ' Enable error-handling routine.
Set powerLogicApp = GetObject(, "PowerLogic.Application") ' Connect to
a running instance of PowerLogic server
Set powerLogicDoc = powerLogicApp.ActiveDocument
Exit Sub ' Exit to avoid handler.
Private Sub Disconnect()
Set powerLogicDoc = Nothing
Set powerLogicApp = Nothing ' Disconnect from PowerLogic server
End Sub
======================================================================
The VB routine seems to be able to connect to the running application even
when my Delphi routine no longer can. It does not help to exit and restart
the Delphi program. The Delphi help is confusing with Dispatch and Dual
interfaces, and using OleVariants.
The C examples use Windows function calls to access the registry and obtain
a CLSID:
======================================================================
// Get the CLSID from the PowerLogic name string ID (system registry
query)
hResult = ::CLSIDFromProgID(OLESTR("PowerLogic.Application"), &clsID);
// Try to get an active instance of PowerLogic. The ::GetActiveObject()
function
// will query the Running Object Table and search for a registered
PowerLogic
// instance currently running on the system. If the return value of
::GetActiveObject()
// is not S_OK, it means that the server is not running on the system at
this time.
hResult = ::GetActiveObject(clsID, NULL, &pUnknown);
// Get IDispatch interface of the PowerLogic application object.
LPDISPATCH pDispatch = NULL;
hResult = pUnknown->QueryInterface(IID_IDispatch, (void **) &pDispatch);
// Allocate the interface
m_pPowerLogicApplication = (IPowerLogicApp *) new IPowerLogicApp;
The code for disconnect:
// Disconnect sink
SetSink(FALSE);
// Delete the connection with PowerLogic by deleting it's reference.
delete m_pPowerLogicApplication;
m_pPowerLogicApplication = NULL;
======================================================================
I'm not very clear how the automation interface works, although it seems
fairly straightforward once I am connected. I am using this to implement a
periodic save function for the application, as its own backup routine is
not always reliable. I got this to work by using the system timer to call
the SAVE function in the application. I also had the application pop up a
message box to indicate the save, which I could do only by a call to
RunMacro, where the macro runs a VB script. Klunky but it works. Maybe it
would be better to use a system modal DialogBox within Delphi. If I can get
the connect/disconnect reliable, then I can add the bells and whistles.
Thanks, and Happy Holidays!
Paul
someone can help.
I am making a client program which connects to an Automation Server of a
running application. I can make the connection, but it fails if I
disconnect and reconnect. Actually I have found that my application creates
another instance of the running application (as a process reported by
Windows Task Manager). I must close and reopen the running application
before my client can reconnect. The sample programs I have available are in
VB (in Excel) and C.
The applicable Delphi code is as follows:
=======================================================================
var
powerLogicApp: IPowerLogicApp;
powerLogicDoc: IPowerLogicDoc; // was Variant;
procedure Connect;
begin
if( powerLogicApp = nil ) then begin
powerLogicApp := CoApplication_.Create;
powerLogicDoc := powerLogicApp.ActiveDocument; end;
end;
procedure Disconnect;
begin
// powerLogicApp.Quit; // This closes the application
powerLogicApp := nil;
powerLogicDoc := nil;
end;
======================================================================
The visual basic code in Excel is as follows:
======================================================================
Dim WithEvents powerLogicApp As PowerLogic.Application
Dim WithEvents powerLogicDoc As PowerLogic.Document
Private Sub Connect()
On Error GoTo OnErrorGetObject ' Enable error-handling routine.
Set powerLogicApp = GetObject(, "PowerLogic.Application") ' Connect to
a running instance of PowerLogic server
Set powerLogicDoc = powerLogicApp.ActiveDocument
Exit Sub ' Exit to avoid handler.
Private Sub Disconnect()
Set powerLogicDoc = Nothing
Set powerLogicApp = Nothing ' Disconnect from PowerLogic server
End Sub
======================================================================
The VB routine seems to be able to connect to the running application even
when my Delphi routine no longer can. It does not help to exit and restart
the Delphi program. The Delphi help is confusing with Dispatch and Dual
interfaces, and using OleVariants.
The C examples use Windows function calls to access the registry and obtain
a CLSID:
======================================================================
// Get the CLSID from the PowerLogic name string ID (system registry
query)
hResult = ::CLSIDFromProgID(OLESTR("PowerLogic.Application"), &clsID);
// Try to get an active instance of PowerLogic. The ::GetActiveObject()
function
// will query the Running Object Table and search for a registered
PowerLogic
// instance currently running on the system. If the return value of
::GetActiveObject()
// is not S_OK, it means that the server is not running on the system at
this time.
hResult = ::GetActiveObject(clsID, NULL, &pUnknown);
// Get IDispatch interface of the PowerLogic application object.
LPDISPATCH pDispatch = NULL;
hResult = pUnknown->QueryInterface(IID_IDispatch, (void **) &pDispatch);
// Allocate the interface
m_pPowerLogicApplication = (IPowerLogicApp *) new IPowerLogicApp;
The code for disconnect:
// Disconnect sink
SetSink(FALSE);
// Delete the connection with PowerLogic by deleting it's reference.
delete m_pPowerLogicApplication;
m_pPowerLogicApplication = NULL;
======================================================================
I'm not very clear how the automation interface works, although it seems
fairly straightforward once I am connected. I am using this to implement a
periodic save function for the application, as its own backup routine is
not always reliable. I got this to work by using the system timer to call
the SAVE function in the application. I also had the application pop up a
message box to indicate the save, which I could do only by a call to
RunMacro, where the macro runs a VB script. Klunky but it works. Maybe it
would be better to use a system modal DialogBox within Delphi. If I can get
the connect/disconnect reliable, then I can add the bells and whistles.
Thanks, and Happy Holidays!
Paul