GetObject- eller GetActiveObject kan ikke finne et program som kjører Office

Symptomer

Når du prøver å bruke GetObject (Microsoft Visual Basic) eller GetActiveObject (Microsoft Visual C++) til å automatisere en Microsoft Office-program, får du en av følgende feilmeldinger, selv om Office-programmet kjører:

Feilmelding 1

Kjøretidsfeil '429':
ActiveX-komponent kan ikke opprette objekt

Feilmelding 2

Feil: 0x800401e3 "Operasjonen er ikke tilgjengelig"

Årsak

Selv om Office-programmet kjører, det er kanskje ikke registrert i den kjører objektet tabell (RÅTE). En forekomst av et Office-program, må være registrert i RÅTE før den kan knyttes til å bruke GetObject (Visual Basic) eller GetActiveObject (Visual C++).

Når du starter et Office-program, registrerer det umiddelbart ikke kjører objektene. Dette optimaliserer programmets oppstartsprosessen. I stedet for registrering ved oppstart, registrerer et Office-program kjører objektene i RÅTE når det mister fokus. Hvis du prøver å bruke GetObject eller GetActiveObject til å koble til en forekomst av et Office-program før programmet har mistet fokus, kan du derfor får en av feilmeldingene ovenfor.

Løsning

Ved hjelp av koden, kan du endre fokus fra Office-programmet på din egen program (eller et annet program) slik at det å registrere seg i RÅTE. I tillegg, hvis koden starter Office-programmet exe-fil, kanskje må du vente til Office-programmet å fullføre innlastingen før du prøver å koble til forekomsten som kjørte. Et kodeeksempel leveres som en midlertidig løsning i delen "Mer informasjon".

Status

Denne virkemåten er standard.

Hvis du vil ha mer informasjon

I de fleste situasjoner må utviklere som vil automatisere et Office-program til å bruke CreateObject (Visual Basic) eller CoCreateInstance (Visual C++) for å starte en ny forekomst av Office-programmet.

Det finnes imidlertid tilfeller der du kanskje foretrekke å automatisere et Office-program som allerede kjører: for eksempel hvis brukeren startet tidligere Office-programmet. Eller, hvis du starte Office-programmets kjørbare filen ved hjelp av kode, slik at du kan angi kommandolinjebryterne for programmet. Hvis du vil automatisere kjører Office-programmet, må du bruke GetObject - eller GetActiveObject.

Slik gjenskaper du virkemåten

  1. Start Microsoft Visual Basic og Opprett et nytt Standard EXE-prosjekt. Form1 opprettes som standard.

  2. Legg til en CommandButton -kontroll i Form1.

  3. Legge til følgende kode i kodemodulen for skjemaet.

    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. Kontroller at plasseringen av Excel.exe er riktig i kode-eksemplet.

  5. Avslutt Microsoft Excel hvis det allerede kjøres.

  6. Trykk F5 for å kjøre prosjektet, og klikk Command1.

Løsning

Hvis du vil omgå problemet, kan du gjøre følgende:

  • Gi fokus til Office-programmet ved å endre det andre argumentet i Shell-funksjonen til vbMinimizedFocus, vbMaximizedFocuseller plasserer vbNormalFocus.

  • Gi Visual Basic-skjema som har fokus.

  • Prøve GetObject mens regnskap for Office-programmet laste gang.

Revidert koden nedenfor illustrerer denne midlertidige løsningen.

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

Løsning for C++

Hvis du programmerer i C++ viser følgende kodeeksempel en lignende løsning som vist i eksemplet ovenfor Visual Basic. Legg merke til at SetForegroundWindow brukes til å flytte fokuset fra Excel, slik at det å registrere kjører objektene.

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

Referanser

Hvis du vil ha mer informasjon, kan du klikke følgende artikkelnumre for å vise artiklene i Microsoft Knowledge Base:

192919 hvordan du automatiserer en sikret Access-database ved hjelp av Visual Basic

237338 -feilmelding ved hjelp av WordMail: "Denne metoden eller egenskapen er ikke tilgjengelig"

240794 hvordan du kan fastslå banen til et Office-program

Trenger du mer hjelp?

Utvid ferdighetene dine
Utforsk opplæring
Vær først ute med de nye funksjonene
Bli med i Microsoft Insiders

Var denne informasjonen nyttig?

Takk for tilbakemeldingen!

Takk for tilbakemeldingen! Det høres ut som det kan være lurt å sette deg i kontakt med én av våre Office-kundestøtteagenter.

×