Applies ToOffice Products

증상

GetObject(Microsoft Visual Basic) 또는 GetActiveObject(Microsoft Visual C++)를 사용하여 Microsoft Office 애플리케이션을 자동화하려고 하면 Office 응용 프로그램이 실행되고 있더라도 다음 오류 메시지 중 하나가 표시됩니다.

오류 메시지 1

런타임 오류 '429': ActiveX 구성 요소가 개체를 만들 수 없습니다.

오류 메시지 2

오류: 0x800401e3 "작업을 사용할 수 없음"

원인

Office 응용 프로그램이 실행 중이지만 ROT(실행 중인 개체 테이블)에 등록되지 않을 수 있습니다. GetObject(Visual Basic) 또는 GetActiveObject(Visual C++)를 사용하여 연결하려면 먼저 OFFICE 애플리케이션의 실행 중인 instance ROT에 등록해야 합니다.Office 애플리케이션이 시작되면 실행 중인 개체를 즉시 등록하지 않습니다. 이렇게 하면 애플리케이션의 시작 프로세스가 최적화됩니다. Office 애플리케이션은 시작 시 등록하는 대신 포커스가 끊어지면 ROT에 실행 중인 개체를 등록합니다. 따라서 응용 프로그램이 포커스를 잃기 전에 GetObject 또는 GetActiveObject를 사용하여 Office 애플리케이션의 실행 중인 instance 연결하려고 하면 위의 오류 중 하나가 나타날 수 있습니다.

해결 방법

코드를 사용하면 포커스를 Office 애플리케이션에서 사용자 고유의 애플리케이션(또는 다른 응용 프로그램)으로 변경하여 ROT에 자체 등록할 수 있습니다. 또한 코드가 Office 애플리케이션의 exe 파일을 시작하는 경우 실행 중인 instance 연결하기 전에 Office 응용 프로그램이 로드가 완료될 때까지 기다려야 할 수 있습니다. 코드 샘플은 "추가 정보" 섹션에서 해결 방법으로 제공됩니다.

상태

이것은 의도적으로 설계된 동작입니다.

추가 정보

대부분의 경우 Office 애플리케이션을 자동화하려는 개발자는 CreateObject(Visual Basic) 또는 CoCreateInstance(Visual C++)를 사용하여 Office 애플리케이션의 새 instance 시작해야 합니다.그러나 사용자가 이전에 Office 애플리케이션을 시작한 경우와 같이 이미 실행 중인 Office 애플리케이션을 자동화하는 것이 좋습니다. 또는 애플리케이션에 대한 명령줄 스위치를 지정할 수 있도록 코드를 사용하여 Office 애플리케이션의 실행 파일을 시작한 경우 실행 중인 Office 애플리케이션을 자동화하려면 GetObject 또는 GetActiveObject를 사용해야 합니다.

동작을 재현하는 단계

  1. Microsoft Visual Basic을 시작하고 새 표준 EXE 프로젝트를 만듭니다. Form1은 기본적으로 만들어집니다.

  2. Form1에 CommandButton 컨트롤을 추가합니다.

  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을 클릭합니다.

해결 방법 

이 문제를 해결하려면 다음을 수행할 수 있습니다.

  • 셸 함수의 두 번째 인수를 vbMinimizedFocus, vbMaximizedFocus 또는 vbNormalFocus로 변경하여 Office 애플리케이션에 포커스를 지정합니다.

  • Visual Basic 양식에 포커스를 지정합니다.

  • Office 애플리케이션의 로드 시간을 고려하면서 GetObject를 시도합니다.

다음 수정된 코드는 이 해결 방법을 보여 줍니다.

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 애플리케이션의 설치 경로를 찾는 방법

도움이 더 필요하세요?

더 많은 옵션을 원하세요?

구독 혜택을 살펴보고, 교육 과정을 찾아보고, 디바이스를 보호하는 방법 등을 알아봅니다.

커뮤니티를 통해 질문하고 답변하고, 피드백을 제공하고, 풍부한 지식을 갖춘 전문가의 의견을 들을 수 있습니다.