GetObject of GetActiveObject kan geen actieve Office-toepassing vinden

Van toepassing: Office Products

Symptomen


Wanneer u GetObject (Microsoft Visual Basic) of GetActiveObject (Microsoft Visual C++) probeert te gebruiken om een Microsoft Office-toepassing te automatiseren, krijgt u een van de volgende foutberichten, ook als de Office-toepassing wordt uitgevoerd:
Foutbericht 1
Runtimefout ' 429 ': ActiveX-onderdeel kan geen object maken
Foutbericht 2
Fout: 0x800401e3 "bewerking niet beschikbaar"

Oorzaak


Hoewel de Office-toepassing wordt uitgevoerd, is de toepassing mogelijk niet geregistreerd in de objectenlijst (ROT). U moet een actief exemplaar van een Office-toepassing registreren in de ROT voordat deze kan worden bijgevoegd met GetObject (Visual Basic) of GetActiveObject (Visual C++). Wanneer een Office-toepassing wordt gestart, registreert de toepassing niet onmiddellijk. Hiermee wordt het opstartproces van de toepassing geoptimaliseerd. In plaats van te registreren bij opstarten, registreert een Office-toepassing de objecten waarop de focus wordt uitgevoerd in de ROT, wanneer deze de focus verliest. Als u het gebruik van GetObject of GetActiveObject wilt toevoegen aan een actief exemplaar van een Office-toepassing voordat de focus verloren gaat, kunt u ook een van de bovenstaande fouten weergegeven.

Oplossing


Door code te gebruiken, kunt u de focus van de Office-toepassing wijzigen in uw eigen toepassing (of naar een andere toepassing), zodat u deze kunt registreren in de ROT. Als uw code het bestand van de Office-toepassing start, moet u mogelijk wachten tot de Office-toepassing is geladen voordat u probeert een verbinding te maken met het actieve exemplaar. Een voorbeeld van een code wordt weergegeven als een tijdelijke oplossing in de sectie meer informatie.

Status


Dit gedrag is inherent aan het ontwerp van het product.

Meer informatie


In de meeste gevallen kunnen ontwikkelaars die een Office-toepassing willen automatiseren gebruikmaken van CreateObject (Visual Basic) of CoCreateInstance (Visual C++) om een nieuw exemplaar van de Office-toepassing te starten. Er zijn echter situaties waarin u een Office-toepassing die al wordt uitgevoerd, kunt automatiseren, bijvoorbeeld als de gebruiker eerder de Office-toepassing heeft gestart. Of als u het uitvoerbare bestand van de Office-toepassing met een code hebt gestart, zodat u opdrachtregelopties voor de toepassing kunt opgeven. Om de actieve Office-toepassing te automatiseren, moet u GetObject of GetActiveObjectgebruiken.

Stappen om het gedrag te reproduceren

  1. Start Microsoft Visual Basic en maak een nieuw Standard EXE-project. Formulier1 wordt standaard gemaakt.
  2. Voeg een CommandButton -besturingselement toe aan Form1.
  3. Voeg de volgende code toe aan de codemodule van het formulier.
    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. Zorg ervoor dat de locatie van Excel. exe in het codevoorbeeld klopt.
  5. Sluit Microsoft Excel af als dit al wordt uitgevoerd.
  6. Druk op F5 om het project uit te voeren en klik op Command1.

Workaround

U kunt dit probleem omzeilen door het volgende te doen:
  • De focus naar de Office-toepassing verplaatsen door het tweede argument van de shell-functie te wijzigen in een vbMinimizedFocus, vbMaximizedFocusof vbNormalFocus.
  • De focus van uw Visual Basic-formulier geven
  • Probeer het met GetObject tijdens de accounting voor de laadtijd van de Office-toepassing.
Aan de hand van de volgende gewijzigde code wordt deze tijdelijke oplossing getoond.
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

Tijdelijke oplossing voor C++

Als u programmeert in C++, ziet u in het volgende codevoorbeeld een vergelijkbare tijdelijke oplossing die wordt weergegeven in het bovenstaande Visual Basic-voorbeeld. U ziet dat SetForegroundWindow wordt gebruikt om de focus te verplaatsen van Excel, zodat de focus objecten kan worden geregistreerd.
//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();

Verwijzingen


Klik op de volgende artikelnummers in de Microsoft Knowledge Base voor meer informatie:
192919 Een beveiligde Access-database automatiseren met Visual Basic
237338 Foutmelding bij het gebruik van WordMail: ' deze methode of eigenschap is niet beschikbaar '.
240794 Het pad vaststellen voor een Office-toepassing