Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

GetObject or GetActiveObject cannot find a running Office application


View products that this article applies to.

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:
Error message 1
Run-time error '429':
ActiveX component can't create object
Error message 2
Error: 0x800401e3 "Operation unavailable"

↑ Back to the top


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.

↑ Back to the top


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.

↑ Back to the top


Status

This behavior is by design.

↑ Back to the top


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 the 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.
    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
  4. Make sure the location of the Excel.exe is correct in the code sample.
  5. Quit Microsoft Excel if it is already running.
  6. Press F5 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.
  • 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 to that 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();

↑ Back to the top


References

For more information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

192919 How to automate a secured Access database using Visual Basic

237338 Error message using WordMail: "This method or property is not available"

240794 How to determine the path for an Office application

↑ Back to the top


Keywords: kboffice12yes, kbfreshness2006, kbbillprodsweep, kboffice2003yes, kbvs2003swept, kbautomation, kbdsupport, kbprb, kb, kbswept

↑ Back to the top

Article Info
Article ID : 238610
Revision : 6
Created on : 8/20/2020
Published on : 8/20/2020
Exists online : False
Views : 541