يتعذر علي GetObject أو جيتاكتيفيوبجيكت العثور علي تطبيق Office قيد التشغيل

ينطبق على: منتجات Office

الأعراض


عند محاولة استخدام GetObject (Microsoft visual Basic) أو جيتاكتيفيوبجيكت (microsoft visual c #) لاتمته تطبيق microsoft Office ، تحصل علي أحدي رسائل الخطا التالية ، حتى لو كان تطبيق Office قيد التشغيل:
رسالة الخطأ 1
خطا وقت التشغيل ' 429 ': يتعذر علي مكون ActiveX إنشاء عنصر
رسالة الخطأ ٢
الخطا: 0x800401e3 "العملية غير متوفرة"

السبب


علي الرغم من ان تطبيق Office قيد التشغيل ، فقد لا يكون مسجلا في جدول كائنات التشغيل (روت). يجب ان يتم تسجيل مثيل قيد التشغيل لتطبيق Office في روت قبل ان يتم إرفاقه باستخدام GetObject (visual Basic) أو جيتاكتيفيوبجيكت (visual c + +). عند بدء تشغيل أحد تطبيقات Office ، لا يقوم فورا بتسجيل الكائنات التي يتم تشغيلها. يؤدي ذلك إلى تحسين عمليه بدء تشغيل التطبيق. بدلا من التسجيل عند بدء التشغيل ، يسجل تطبيق Office الكائنات التي يتم تشغيلها في روت بمجرد فقدان التركيز عليه. ولذلك ، إذا حاولت استخدام GetObject أو جيتاكتيفيوبجيكت لإرفاقه بمثيل قيد التشغيل لأحد تطبيقات Office قبل ان يكون التطبيق قد فقد التركيز ، فقد تتلقي أحدي الأخطاء المذكورة أعلاه.

الحل


باستخدام التعليمات البرمجية ، يمكنك تغيير التركيز من تطبيق Office إلى التطبيق الخاص بك (أو إلى تطبيق آخر) للسماح له بتسجيل نفسه في روت. بالاضافه إلى ذلك ، إذا كانت التعليمات البرمجية تقوم بتشغيل ملف exe لتطبيق Office ، فقد تحتاج إلى الانتظار حتى ينتهي تطبيق Office من التحميل قبل محاولة الإرفاق بالمثيل الحالي. يتم توفير نموذج التعليمات البرمجية كحل بديل في القسم "مزيد من المعلومات".

الحالة


هذا السلوك مرتبط بالتصميم.

مزيد من المعلومات


في معظم الحالات ، سيحتاج المطورون الذين يريدون أتمته تطبيق Office إلى استخدام كريتيوبجيكت (visual Basic) أو CoCreateInstance (visual c + +) لتشغيل مثيل جديد من تطبيق Office. ومع ذلك ، توجد بعض الحالات التي قد تفضل فيها استخدام تطبيق Office الذي يعمل بالفعل: علي سبيل المثال ، إذا قام المستخدم ببدء تشغيل تطبيق Office مسبقا. أو ، إذا قمت بتشغيل الملف التنفيذي لتطبيق Office باستخدام التعليمات البرمجية بحيث يمكنك تحديد رموز تبديل سطر الأوامر الخاصة بالتطبيق. من أجل أتمته تطبيق Office الذي يتم تشغيله ، يجب استخدام GetObject أو جيتاكتيفيوبجيكت.

خطوات أعاده إنشاء السلوك

  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 = NothingEnd Sub
  4. تاكد من ان موقع ملف Excel صحيح في نموذج التعليمات البرمجية.
  5. قم بإنهاء Microsoft Excel إذا كان قيد التشغيل بالفعل.
  6. اضغط علي F5 لتشغيل المشروع ، وانقر فوق Command1.

الحل البديل

لحل هذه المشكلة ، يمكنك:
  • قم بالتركيز علي تطبيق Office من خلال تغيير الوسيطة الثانية للدالة Shell إلى اما فبمينيميزيدفوكوسأو فبماكسيميزيدفوكوسأو فبنورمالفوكوس.
  • قم بتسميه التركيز بشكل مرئي.
  • حاول تطبيق 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. لاحظ ان سيتفوريجروندويندوو يتم استخدامه لنقل التركيز بعيدا عن 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