Перейти к основному контенту
Поддержка
Войдите с помощью учетной записи Майкрософт
Войдите или создайте учетную запись.
Здравствуйте,
Выберите другую учетную запись.
У вас несколько учетных записей
Выберите учетную запись, с помощью которой нужно войти.

Проблемы

При попытке автоматизировать приложение Microsoft Office с помощью GetObject (Microsoft Visual Basic) или GetActiveObject (Microsoft Visual C++) вы получаете одно из следующих сообщений об ошибке, даже если приложение Office запущено:

Сообщение об ошибке 1

Ошибка времени выполнения "429":
Компоненту ActiveX не удается создать объект

Сообщение об ошибке 2

Ошибка: 0x800401e3 "Операция недоступна"

Причина

Хотя приложение Office запущено, оно может не быть зарегистрировано в таблице выполняющихся объектов (ROT). Запущенный экземпляр приложения Office должен быть зарегистрирован в ROT, прежде чем его можно будет подключить с помощью GetObject (Visual Basic) или GetActiveObject (Visual C++).

Когда приложение Office запускается, оно не сразу регистрирует свои запущенные объекты. Это оптимизирует процесс запуска приложения. Вместо регистрации при запуске приложение Office регистрирует свои запущенные объекты в rot после потери фокуса. Поэтому при попытке использовать 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. Форма Form1 создается по умолчанию.

  2. Добавьте элемент управления CommandButton в Form1.

  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 = Nothing
    End Sub
    
  4. Убедитесь, что в примере кода правильно расположен Excel.exe.

  5. Закройте Microsoft Excel, если он уже запущен.

  6. Нажмите клавишу F5, чтобы запустить проект, и нажмите кнопку Command1.

Обходное решение

Чтобы обойти проблему, вы можете:

  • Переключите внимание на приложение Office, изменив второй аргумент функции оболочки на 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 If
End 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();

Ссылки

Для получения дополнительных сведений щелкните следующие номера статей, чтобы просмотреть статью:

Поиск пути установки приложения Office

Нужна дополнительная помощь?

Нужны дополнительные параметры?

Изучите преимущества подписки, просмотрите учебные курсы, узнайте, как защитить свое устройство и т. д.

В сообществах можно задавать вопросы и отвечать на них, отправлять отзывы и консультироваться с экспертами разных профилей.

Были ли сведения полезными?

Насколько вы удовлетворены качеством перевода?
Что повлияло на вашу оценку?
После нажатия кнопки "Отправить" ваш отзыв будет использован для улучшения продуктов и служб Майкрософт. Эти данные будут доступны для сбора ИТ-администратору. Заявление о конфиденциальности.

Спасибо за ваш отзыв!

×