使用 Microsoft 登入
登入或建立帳戶。
您好:
選取其他帳戶。
您有多個帳戶
選擇您要用來登入的帳戶。

徵兆

當您嘗試使用 GetObject (Microsoft Visual Basic) 或 GetActiveObject (Microsoft Visual C++) 來自動化 Microsoft Office 應用程式時,即使 Office 應用程式正在執行,您還是會收到下列其中一個錯誤訊息:

錯誤訊息 1

執行時間錯誤 '429':
ActiveX 元件無法建立物件

錯誤訊息 2

錯誤:0x800401e3無法使用作業]

原因

雖然 Office 應用程式正在執行,但它可能未在 [執行物件資料表] (ROT) 中註冊。 執行中的 Office 應用程式實例必須先在 ROT 中註冊,才能附加至使用 GetObject (Visual Basic) 或 GetActiveObject (Visual C++) 。

Office 應用程式啟動時,並不會立即註冊其執行物件。 這會優化應用程式的啟動程式。 Office 應用程式會在失去焦點後,于 ROT 中註冊其執行物件,而不是在啟動時註冊。 因此,如果您嘗試在應用程式失去焦點之前使用 GetObject 或 GetActiveObject 附加到執行中的 Office 應用程式實例,您可能會收到上述其中一個錯誤。

解決方案

您可以使用程式碼,將焦點從 Office 應用程式變更為您自己的應用程式 (或某些其他應用程式) 允許它在 ROT 中註冊。 此外,如果您的程式碼啟動 Office 應用程式的 exe 檔案,您可能需要等候 Office 應用程式完成載入,然後再嘗試附加至執行中的實例。 程式碼範例是提供為「其他資訊」一節中的因應措施。

狀態

產生此錯誤是系統刻意為之。

其他相關資訊

在大多數情況下,想要自動化 Office 應用程式的開發人員必須使用 CreateObject (Visual Basic) 或 CoCreateInstance (Visual C++) 來啟動新的 Office 應用程式實例。

不過,在某些情況下,您可能會想要自動化已在執行中的 Office 應用程式:例如,如果使用者先前已啟動 Office 應用程式。 或者,如果您使用程式碼啟動 Office 應用程式的可執行檔,以便指定應用程式的命令列參數。 若要將執行中的 Office 應用程式自動化,您必須使用 GetObject 或 GetActiveObject。

重現行為的步驟

  1. 啟動 Microsoft Visual Basic 並建立新的標準 EXE 專案。 表單1 預設為建立。

  2. 將 CommandButton 控制項新增至 Form1。

  3. 將下列程式碼新增至表單的程式碼模組。

    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. 確認代碼樣本中 Excel.exe 的位置正確無誤。

  5. 如果 Microsoft Excel 已經在執行中,請結束它。

  6. 按 F5 以執行專案,然後按一下 [命令1]。

因應措施 

若要解決此問題,您可以:

  • 將 Shell 函數的第二個引數變更為 vbMinimizedFocus、vbMaximizedFocus 或 vbNormalFocus,將焦點放在 Office 應用程式。

  • 讓 Visual Basic 表單成為焦點。

  • 在計算 Office 應用程式的載入時間時嘗試 GetObject。

下列修訂的程式碼說明此因應措施。

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

C++ 的因應措施

如果您是在 C++中進行程式設計,下列程式碼範例會示範與上述 Visual Basic 範例中所示的類似因應措施。 請注意,SetForegroundWindow 是用來將焦點移離 Excel,允許它註冊其執行中的物件。

//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();

參考

如需詳細資訊,請按一下下列文章編號以檢視文章:

如何尋找 Office 應用程式的安裝路徑

需要更多協助嗎?

想要其他選項嗎?

探索訂閱權益、瀏覽訓練課程、瞭解如何保護您的裝置等等。

社群可協助您詢問並回答問題、提供意見反應,以及聆聽來自具有豐富知識的專家意見。

這項資訊有幫助嗎?

您對語言品質的滿意度如何?
以下何者是您會在意的事項?
按下 [提交] 後,您的意見反應將用來改善 Microsoft 產品與服務。 您的 IT 管理員將能夠收集這些資料。 隱私權聲明。

感謝您的意見反應!

×