היכנס דרך Microsoft
היכנס או צור חשבון.
שלום,
בחר חשבון אחר.
יש לך חשבונות מרובים
בחר את החשבון שברצונך להיכנס באמצעותו.

תופעות

כאשר אתה מנסה להשתמש ב- GetObject (Microsoft Visual Basic) או GetActiveObject (Microsoft Visual C++) כדי להפוך יישום של Microsoft Office לאוטומטי, אתה מקבל אחת מהודעות השגיאה הבאות, למרות שהיישום של 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 וצור פרוייקט חדש מסוג Standard EXE. Form1 נוצר כברירת מחדל.

  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 = Nothing
    End 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 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

זקוק לעזרה נוספת?

מעוניין באפשרויות נוספות?

גלה את יתרונות המנוי, עיין בקורסי הדרכה, למד כיצד לאבטח את המכשיר שלך ועוד.

קהילות עוזרות לך לשאול שאלות ולהשיב עליהן, לתת משוב ולשמוע ממומחים בעלי ידע עשיר.

האם מידע זה היה שימושי?

עד כמה אתם מרוצים מאיכות השפה?
מה השפיע על החוויה שלך?
בלחיצה על 'שלח', אתה מאפשר למשוב שלך לשפר מוצרים ושירותים של Microsoft. מנהל ה-IT שלך יוכל לאסוף נתונים אלה. הצהרת הפרטיות.

תודה על המשוב!

×