Симптоми

Когато се опитате да използвате GetObject (Microsoft Visual Basic) или GetActiveObject (Microsoft Visual C++) за автоматизиране на приложение на Microsoft Office, получавате едно от следните съобщения за грешка, въпреки че приложението на Office се изпълнява:

Съобщение за грешка 1

Грешка на оперативно време "429": ActiveX Компонентът не може да създаде обект

Съобщение за грешка 2

Грешка: 0x800401e3 "операцията е недостъпна"

Причина

Въпреки че приложението на Office се изпълнява, то може да не е регистрирано в таблицата за текущи обекти (ROT). В ROT трябва да е регистриран екземпляр на приложение на Office, преди да може да бъде прикачен към използването на GetObject (Visual Basic) или GetActiveObject (Visual C++). Когато приложението на Office се стартира, то не регистрира незабавно своите текущи обекти. Това оптимизира процеса на стартиране на приложението. Вместо да се регистрира при стартиране, приложение на Office регистрира своите текущи обекти в ГНИЕнето, след като изгуби фокуса си. Следователно, ако се опитате да използвате GetObject или GetActiveObject , за да прикачите към работещ екземпляр на приложение на Office, преди приложението да е изгубило фокуса си, е възможно да получите една от горните грешки.

Решение

С помощта на код можете да промените фокуса от приложението на Office към собственото си приложение (или към друго приложение), за да го разрешите да се регистрира в ROT. Освен това, ако кодът ви стартира exe файла на приложението на Office, може да се наложи да изчакате да завърши зареждането на приложението на Office, преди да се опитате да прикачите към екземпляра за изпълнение. Пример за код се предоставя като заобиколно решение в секцията "повече информация".

Състоянието

Това поведение е по проект.

Повече информация

В повечето ситуации разработчиците, които искат да автоматизират приложение на Office, трябва да използват CreateObject (Visual Basic) или CoCreateInstance (Visual C++), за да стартират нов екземпляр на приложението на Office. Има обаче случаи, в които може да предпочетете да автоматизирате приложение на Office, което вече се изпълнява: например ако потребителят е стартирал приложението на Office. Или, ако сте стартирали изпълнимия файл на приложението на Office чрез код, така че да можете да зададете ключове за командния ред за приложението. За да автоматизирате изпълняваното приложение на Office, трябва да използвате GetObject или GetActiveObject.

Стъпки за възпроизвеждане на поведението

  1. Стартирайте Microsoft Visual Basic и създайте нов стандартен проект на EXE. Формуляр1 се създава по подразбиране.

  2. Добавете контрола CommandButton към формуляр1.

  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. Уверете се, че местоположението на Excel. exe е правилно в образеца за код.

  5. Излезте от Microsoft Excel, ако вече се изпълнява.

  6. Натиснете F5, за да стартирате проекта, и щракнете върху Command1.

Заобиколно решение

За да заобиколите проблема, можете да направите следното:

  • Дайте фокус върху приложението на Office, като промените втория аргумент на функцията Shell на vbMinimizedFocus, vbMaximizedFocusили vbNormalFocus.

  • Дайте на фокуса формуляра си за Visual Basic.

  • Изпробвайте GetObject , докато си запазвате времето за зареждане на приложението на Office.

Следващият коригиран код илюстрира това заобиколно решение.

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 Как да автоматизирате защитена база данни на Access с помощта на Visual Basic

237338 Съобщение за грешка с помощта на WordMail: "този метод или свойство не е наличен"

240794 Как да определите пътя за приложение на Office

Нуждаете се от още помощ?

Разширете уменията си
Преглед на обучението
Получавайте първи новите функции
Присъединете се към Microsoft приобщени

Беше ли полезна тази информация?

Доколко сте доволни от качеството на превода?
Какво е повлияло на вашия потребителски опит?

Благодарим ви за обратната връзка!

×