Sign in with Microsoft
Sign in or create an account.
Hello,
Select a different account.
You have multiple accounts
Choose the account you want to sign in with.

徵兆

當您嘗試使用 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 應用程式的安裝路徑

Need more help?

Want more options?

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

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

Was this information helpful?

How satisfied are you with the translation quality?
What affected your experience?
By pressing submit, your feedback will be used to improve Microsoft products and services. Your IT admin will be able to collect this data. Privacy Statement.

Thank you for your feedback!

×