Accedi con Microsoft
Accedi o crea un account.
Salve,
Seleziona un altro account.
Hai più account
Scegli l'account con cui vuoi accedere.

Sintomi

Quando si prova a usare GetObject (Microsoft Visual Basic) o GetActiveObject (Microsoft Visual C++) per automatizzare un'applicazione di Microsoft Office, viene visualizzato uno dei messaggi di errore seguenti, anche se l'applicazione di Office è in esecuzione:

Messaggio di errore 1

Errore di runtime '429':
Il componente ActiveX non può creare un oggetto

Messaggio di errore 2

Errore: 0x800401e3 "Operazione non disponibile"

Causa

Anche se l'applicazione di Office è in esecuzione, potrebbe non essere registrata nella tabella degli oggetti in esecuzione (ROT). Un'istanza in esecuzione di un'applicazione di Office deve essere registrata in ROT prima che possa essere collegata usando GetObject (Visual Basic) o GetActiveObject (Visual C++).

All'avvio di un'applicazione di Office, non registra immediatamente gli oggetti in esecuzione. In questo modo viene ottimizzato il processo di avvio dell'applicazione. Invece di registrarsi all'avvio, un'applicazione di Office registra gli oggetti in esecuzione in ROT quando perde lo stato attivo. Pertanto, se si tenta di usare GetObject o GetActiveObject per connettersi a un'istanza in esecuzione di un'applicazione di Office prima che l'applicazione abbia perso lo stato attivo, è possibile che venga visualizzato uno degli errori precedenti.

Risoluzione

Usando il codice, è possibile spostare lo stato attivo dall'applicazione di Office alla propria applicazione (o ad altre applicazioni) per consentire la registrazione in ROT. Inoltre, se il codice avvia il file exe dell'applicazione di Office, potrebbe essere necessario attendere il completamento del caricamento dell'applicazione di Office prima di tentare di connettersi all'istanza in esecuzione. Un esempio di codice viene fornito come soluzione alternativa nella sezione "Altre informazioni".

Stato

Si tratta di un comportamento correlato alla progettazione del prodotto.

Ulteriori informazioni

Nella maggior parte dei casi, gli sviluppatori che vogliono automatizzare un'applicazione di Office devono usare CreateObject (Visual Basic) o CoCreateInstance (Visual C++) per avviare una nuova istanza dell'applicazione di Office.

In alcuni casi, tuttavia, si potrebbe preferire automatizzare un'applicazione di Office già in esecuzione, ad esempio se l'utente ha avviato l'applicazione di Office in precedenza. In alternativa, se è stato avviato il file eseguibile dell'applicazione di Office usando il codice in modo da poter specificare le opzioni della riga di comando per l'applicazione. Per automatizzare l'applicazione di Office in esecuzione, è necessario usare GetObject o GetActiveObject.

Procedura per riprodurre il problema

  1. Avviare Microsoft Visual Basic e creare un nuovo progetto Standard EXE. Form1 viene creato per impostazione predefinita.

  2. Aggiungere un controllo CommandButton a Form1.

  3. Aggiungere il codice seguente al modulo di codice del modulo.

    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. Verificare che la posizione del Excel.exe sia corretta nell'esempio di codice.

  5. Chiudere Microsoft Excel se è già in esecuzione.

  6. Premere F5 per eseguire il progetto e fare clic su Comando1.

Soluzione alternativa

Per risolvere il problema, è possibile:

  • Per spostare lo stato attivo sull'applicazione di Office, modificare il secondo argomento della funzione Shell in vbMinimizedFocus, vbMaximizedFocus o vbNormalFocus.

  • Spostare lo stato attivo sulla maschera Visual Basic.

  • Tentativo di GetObject durante la gestione del tempo di caricamento dell'applicazione di Office.

Il codice modificato seguente illustra questa soluzione alternativa.

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

Soluzione alternativa per C++

Se si esegue la programmazione in C++, nell'esempio di codice seguente viene illustrata una soluzione alternativa simile a quella illustrata nell'esempio di Visual Basic precedente. Si noti che SetForegroundWindow viene usato per spostare lo stato attivo da Excel, consentendo di registrare gli oggetti in esecuzione.

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

Riferimenti

Per altre informazioni, fare clic sui numeri dell'articolo seguente per visualizzare l'articolo:

Come trovare il percorso di installazione di un'applicazione di Office

Serve aiuto?

Vuoi altre opzioni?

Esplorare i vantaggi dell'abbonamento e i corsi di formazione, scoprire come proteggere il dispositivo e molto altro ancora.

Le community aiutano a porre e a rispondere alle domande, a fornire feedback e ad ascoltare gli esperti con approfondite conoscenze.

Queste informazioni sono risultate utili?

Come valuti la qualità della lingua?
Cosa ha influito sulla tua esperienza?
Premendo Inviare, il tuo feedback verrà usato per migliorare i prodotti e i servizi Microsoft. L'amministratore IT potrà raccogliere questi dati. Informativa sulla privacy.

Grazie per il feedback!

×