PRB: GetObject or GetActiveObject Cannot Find a Running Office Application

ID: Q238610


The information in this article applies to:
  • Microsoft Office 2000
  • Microsoft Office 97 for Windows
  • Microsoft Visual Basic for Applications versions 5.0, 6.0
  • Microsoft Visual C++, 32-bit Professional Edition, versions 5.0, 6.0


SYMPTOMS

When you try to use GetObject (Microsoft Visual Basic) or GetActiveObject (Microsoft Visual C++) to automate a Microsoft Office application, you get one of the following error messages, even though the Office application is running:

Run-time error '429':
ActiveX component can't create object
-or-
Error: 0x800401e3 "Operation unavailable"


CAUSE

Although the Office application is running, it might not be registered in the Running Object Table (ROT). A running instance of an Office application must be registered in the ROT before it can be attached to using GetObject (Visual Basic) or GetActiveObject (Visual C++).

When an Office application starts, it does not immediately register its running objects. This optimizes the application's startup process. Instead of registering at startup, an Office application registers its running objects in the ROT once it loses focus. Therefore, if you attempt to use GetObject or GetActiveObject to attach to a running instance of an Office application before the application has lost focus, you might receive one of the errors above.


RESOLUTION

Using code, you can change focus from the Office application to your own application (or to some other application) to allow it to register itself in the ROT. Additionally, if your code is launching the Office application's exe file, you might need to wait for the Office application to finish loading before attempting to attach to the running instance. A code sample is provided as a workaround in the "More Information" section below.


STATUS

This behavior is by design.


MORE INFORMATION

In most situations, developers who want to automate an Office application need to use CreateObject (Visual Basic) or CoCreateInstance (Visual C++) to launch a new instance of the Office application.

However, there are cases where you might prefer to automate an Office application that is already running: for example, if the user previously started the Office application. Or, if you launched the Office application's executable using code so that you could specify command-line switches for the application. In order to automate the running Office application, you must use GetObject or GetActiveObject.

Steps to Reproduce Behavior

  1. Start Microsoft Visual Basic and create a new Standard EXE project. Form1 is created by default.


  2. Add a CommandButton control to Form1.


  3. Add the following code to the form's code module:


  4. 
    Private Sub Command1_Click()
        Dim oExcel As Object
        ' Launch a new instance of Microsoft Excel:
        Shell "C:\Program Files\Microsoft Office\Office\Excel.EXE", _
           vbMinimizedNoFocus
        ' An error 429 occurs on the following line:
        Set oExcel = GetObject(, "Excel.Application")
        MsgBox oExcel.Name
        Set oExcel = Nothing
    End Sub 
  5. Make sure the location of the Excel.exe is correct in the code sample.


  6. Quit Microsoft Excel if it is already running.


  7. Press the F5 key to run the project, and click Command1.


Workaround

To work around the problem, you can:
  • Give focus to the Office application by changing the second argument of the Shell function to either vbMinimizedFocus, vbMaximizedFocus, or vbNormalFocus.


  • Give your Visual Basic form the focus.


  • And finally, attempt GetObject while accounting for the Office application's load time.
The following revised code illustrates this workaround:

Private Declare Sub Sleep Lib "kernel32" _
    (ByVal dwMilliseconds As Long)

Private Sub Command1_Click()
    Dim intSection As Integer
    Dim intTries As Integer
    Dim oExcel As Object
    
    ' Enable error handler for this procedure:
    On Error GoTo ErrorHandler
    
    ' Launch Microsoft Excel, giving it focus:
    Shell "C:\Program Files\Microsoft Office\Office\Excel.EXE", _
        vbMinimizedFocus 'other options for starting with
        'focus: vbMaximizedFocus and vbNormalFocus
    
    ' Move focus back to this form. (This ensures the Office
    '  application registers itself in the ROT, allowing
    '  GetObject to find it.)
    Me.SetFocus
    
    ' Attempt to use GetObject to reference the running
    '  Office application:
    intSection = 1 'attempting GetObject...
    Set oExcel = GetObject(, "Excel.Application")
    intSection = 0 'resume normal error handling
    
    ' Now you can automate Microsoft Excel:
    MsgBox oExcel.Name & ": able to GetObject after " & _
        intTries + 1 & " tries.", vbMsgBoxSetForeground
    
    ' Finished with automation so release your reference:
    Set oExcel = Nothing
    
    ' Exit procedure:
    Exit Sub
    
ErrorHandler:
    If intSection = 1 Then 'GetObject may have failed because the
    'Shell function is asynchronous; enough time has not elapsed
    'for GetObject to find the running Office application. Wait
    'wait 1/2 seconds and retry the GetObject. If you try 20 times
    'and GetObject still fails, assume some other reason
    'for GetObject failing and exit the procedure.
        intTries = intTries + 1
        If intTries < 20 Then
            Sleep 500 ' wait 1/2 seconds
            Resume 'resume code at the GetObject line
        Else
            MsgBox "GetObject still failing. Process ended.", _
                vbMsgBoxSetForeground
        End If
    Else 'intSection = 0 so use normal error handling:
        MsgBox Error$
    End If
End Sub 

Workaround for C++

If you are programming in C++, the following code sample demonstrates a similar workaround as shown in the above Visual Basic sample. Notice that SetForegroundWindow() is used to move focus away from Excel, allowing it to register its running objects:

//Store the handle of the currently active window...
HWND hwndCurrent = ::GetForegroundWindow();

//Launch Excel and wait until it is waiting for
//user input...
STARTUPINFO Start;
PROCESS_INFORMATION ProcInfo;
ZeroMemory(&Start,sizeof(STARTUPINFO));
Start.cb=sizeof(Start);
Start.dwFlags = STARTF_USESHOWWINDOW;
Start.wShowWindow = SW_SHOWMINIMIZED;

//Change the path to Excel as needed...
LPSTR pszExcelPath = 
      "c:\\program files\\microsoft office\\office\\excel.exe";

::CreateProcess(NULL, pszExcelPath, 0, 0, 1,
       NORMAL_PRIORITY_CLASS, 0, NULL, &Start, &ProcInfo);

if((::WaitForInputIdle(ProcInfo.hProcess, 10000))==WAIT_TIMEOUT)
{
    ::MessageBox(NULL, "Timed out waiting for Excel.", NULL,  
                 MB_OK);
}

//Restore the active window to the foreground...
//  NOTE: If you comment out this line, the code will fail!
::SetForegroundWindow(hwndCurrent);

//Initialize COM library...
::CoInitialize(NULL);

//Attach to the running instance...
CLSID clsid;
CLSIDFromProgID(L"Excel.Application", &clsid);  
IUnknown *pUnk = NULL;
IDispatch *pDisp = NULL;

for(int i=1;i<=5;i++) //try attaching for up to 5 attempts
{
   HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
   if(SUCCEEDED(hr)) 
   {
       hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp);
       break;
   }
   ::Sleep(1000);
}
        
if (!pDisp) {
    ::MessageBox(NULL, "Failed to find instance!!", "Error", 
                 MB_ICONHAND);
}
else {
    ::MessageBox(NULL, "Got instance of Excel!", "Success", MB_OK);
}

//Release the no-longer-needed IUnknown...
if (pUnk) 
    pUnk->Release();

//... Add your automation code for Excel here ...

//Release pDisp when no longer needed...
if (pDisp)
    pDisp->Release();

//Cleanup COM...
CoUninitialize(); 


REFERENCES

For related information, please click the article numbers below to view the articles in the Microsoft Knowledge Base:

Q192919 HOWTO: Automate a Secured Access Database Using Visual Basic

Q237338 WD2000: ErrMsg: "This method or property is not available"

Q240794 HOWTO: Determine the Path for an Office Application

Additional query words: error 429

Keywords : kbAccess kbAutomation kbExcel kbFrontPage kbOutlook KbVBA kbVBp kbVC kbPowerPt kbWord kbGrpDSO kbDSupport
Version : WINDOWS:2000,5.0,6.0,97; winnt:5.0,6.0
Platform : WINDOWS winnt
Issue type : kbprb


Last Reviewed: November 25, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.