GetObject ou GetActiveObject ne parvient pas à trouver une application Office en cours d’exécution

S’applique à : Produits Office

Symptômes


Lorsque vous essayez d’utiliser GetObject (Microsoft Visual Basic) ou GetActiveObject (Microsoft Visual C++) pour automatiser une application Microsoft Office, vous recevez l’un des messages d’erreur suivants, même si l’application Office est en cours d’exécution :
Message d’erreur 1
Erreur au moment de l’exécution' 429 ' : le composant ActiveX ne peut pas créer d’objet
Message d’erreur 2
Erreur : 0x800401e3 "opération non disponible"

Cause


Même si l’application Office est en cours d’exécution, elle risque de ne pas être inscrite dans la table ROT (Running Object Table). Une instance en cours d’exécution d’une application Office doit être inscrite dans la table ROT pour pouvoir être associée à l’utilisation de GetObject (Visual Basic) ou de GetActiveObject (Visual C++). Lors du démarrage d’une application Office, l’application n’inscrit pas immédiatement ses objets en cours d’exécution. Cela optimise le processus de démarrage de l’application. Au lieu de vous inscrire au démarrage, une application Office inscrit ses objets en cours d’exécution dans le ROT une fois qu’il perd le focus. Par conséquent, si vous tentez d’utiliser GetObject ou GetActiveObject pour joindre une instance en cours d’exécution d’une application Office avant que l’application ne perde le focus, vous pouvez recevoir l’une des erreurs ci-dessus.

Résolution


À l’aide de code, vous pouvez modifier le focus de l’application Office vers votre propre application (ou vers une autre application) afin de pouvoir s’inscrire dans la table ROT. Par ailleurs, si votre code lance le fichier exe de l’application Office, il se peut que vous deviez attendre que l’application Office finisse le chargement avant d’essayer de joindre l’instance en cours d’exécution. Un exemple de code est fourni dans le cadre d’une solution de contournement dans la section « informations supplémentaires ».

Statut


Ce comportement est inhérent au produit.

Informations supplémentaires


Dans la plupart des cas, les développeurs qui souhaitent automatiser une application Office doivent utiliser CreateObject (Visual Basic) ou CoCreateInstance (Visual C++) pour lancer une nouvelle instance de l’application Office. Toutefois, dans certains cas, il peut être préférable d’automatiser une application Office en cours d’exécution : par exemple, si l’utilisateur a déjà démarré l’application Office. Ou bien, si vous avez lancé le fichier exécutable de l’application Office à l’aide du code, vous pouvez spécifier des commutateurs de ligne de commande pour l’application. Pour automatiser l’application Office en cours d’exécution, vous devez utiliser GetObject ou GetActiveObject.

Procédure pour reproduire le comportement

  1. Démarrez Microsoft Visual Basic et créez un projet EXE standard. Form1 est créé par défaut.
  2. Ajoutez un contrôle CommandButton à Form1.
  3. Ajoutez le code suivant au module de code du formulaire.
    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. Assurez-vous que l’emplacement du fichier Excel. exe est correct dans l’exemple de code.
  5. Quittez Microsoft Excel s’il est déjà en cours d’exécution.
  6. Appuyez sur F5 pour exécuter le projet, puis cliquez sur Command1.

Solution de contournement

Pour contourner ce problème, vous pouvez :
  • Insistez sur l’application Office en modifiant le second argument de la fonction Shell sur vbMinimizedFocus, vbMaximizedFocusou vbNormalFocus.
  • Donnez le focus à votre formulaire Visual Basic.
  • Essayez de GetObject en tenant compte du temps de chargement de l’application Office.
Le code révisée suivant illustre cette solution de contournement.
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

Solution de contournement pour C++

Si vous programmez en C++, l’exemple de code suivant présente une solution de contournement similaire à celle illustrée dans l’exemple Visual Basic ci-dessus. Notez que la propriété SetForegroundWindow est utilisée pour déplacer le focus d’Excel vers un autre, ce qui permet à l’application d’inscrire ses objets en cours d’exécution.
//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();

Références


Pour plus d’informations, cliquez sur les numéros ci-dessous pour afficher les articles correspondants dans la Base de connaissances Microsoft :
192919 Automatisation d’une base de données Access sécurisée à l’aide de Visual Basic
237338 Message d’erreur avec WordMail : "cette méthode ou propriété n’est pas disponible"
240794 Déterminer le chemin d’une application Office