徵狀

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

錯誤訊息 1

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

錯誤訊息 2

錯誤: 0x800401e3 "操作無法使用中"

原因

雖然 Office 應用程式正在執行,但它可能沒有在執行中的物件資料表(ROT)中註冊。 若要使用 GetObject (visual Basic)或 GetActiveObject (visual c + +),就必須先在 ROT 中登錄 Office 應用程式的執行實例。 啟動 Office 應用程式時,不會立即註冊其執行中的物件。 這會優化應用程式的啟動程式。 Office 應用程式不會在啟動時登錄,只要它失去焦點,就會在 ROT 中註冊其執行中的物件。 因此,如果您嘗試使用 GetObject 或 GetActiveObject ,在應用程式失去焦點前,附加至 Office 應用程式的正在執行的實例,您可能會收到上述其中一個錯誤。

解決方案

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

狀態

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

其他相關資訊

在大部分的情況下,想要自動化 Office 應用程式的開發人員需要使用 CreateObject (visual Basic)或 CoCreateInstance (Visual c + +)來啟動 office 應用程式的新實例。 不過,在某些情況下,您可能會想要將已執行的 Office 應用程式自動化:例如,如果使用者先前已啟動 Office 應用程式。 或者,如果您使用程式碼啟動 Office 應用程式的可執行檔,以便為應用程式指定命令列參數。 您必須使用 GetObject 或 GetActiveObject,才能自動化執行中的 Office 應用程式。

再現行為的步驟

  1. 啟動 Microsoft Visual Basic,然後建立新的標準 EXE 專案。 預設會建立 Form1。

  2. 在 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 = NothingEnd Sub
  4. 在程式碼範例中,請確定 at.exe 的位置正確無誤。

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

  6. 按 F5 來執行專案,然後按一下 [ Command1]。

因應措施

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

  • 將 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 IfEnd 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();

參考

如需詳細資訊,請按一下下面的文章編號,檢視「Microsoft 知識庫」中的文章:

192919 如何使用 Visual Basic 自動化受保護的 Access 資料庫

237338 使用 WordMail 的錯誤訊息:「這個方法或屬性無法使用」

240794 如何判斷 Office 應用程式的路徑

需要更多協助?

擴展您的技能
探索訓練
優先取得新功能
加入 Microsoft 測試人員

這項資訊有幫助嗎?

您對語言品質的滿意度如何?
以下何者是您會在意的事項?

感謝您的意見反應!

×