Sümptomid
Kui proovite Microsoft Office ' i rakenduse automatiseerimiseks kasutada GetObject (Microsoft Visual Standard) või GetActiveObject (Microsoft Visual C++), kuvatakse üks järgmistest tõrketeadetest, isegi kui Office ' i rakendus töötab.
Tõrketeade 1
Run-time error "429": ActiveX-komponent ei saa objekti luua
Tõrketeade 2
Tõrge: 0x800401e3 "toiming pole saadaval"
Põhjus
Kuigi Office ' i rakendus töötab, ei pruugi see olla registreeritud objekti tabelis (ROT). Office ' i rakenduse käitav eksemplar peab olema registreeritud MÄDANEma, enne kui seda saab manustada GetObject (Visual Standard) või GetActiveObject (Visual C++) abil. Kui Office ' i rakendus käivitub, ei registreeri ta jooksvaid objekte kohe. See optimeerib rakenduse käivitamise protsessi. Selle asemel, et registreeruda käivitamisel, registreerib Office ' i rakendus oma jooksvad objektid MÄDA, kui fookuse kaotab. Kui proovite GetObject või GetActiveObject kasutada Office ' i rakenduse töötava eksemplariga manustamiseks enne, kui rakendus on fookuse kaotanud, võidakse kuvada üks ülaltoodud tõrketeadetest.
Lahendus
Kasutades koodi, saate Office ' i rakenduse fookust muuta oma rakenduseks (või mõnele muule rakendusele), et lubada tal end MÄDANEma registreerida. Lisaks, kui teie kood käivitab Office ' i rakenduse exe-faili, peate võib-olla ootama, kuni Office ' i rakendus peab laadimise lõpule viima enne, kui proovite käivitada eksemplari. Koodi näidis on toodud jaotises "Lisateavet" toodud vastukaaluna.
Olek
Selline käitumine on kujundatud.
Lisateave
Enamikel juhtudel peab Office ' i rakenduse uue eksemplari käivitamiseks arendajad, kes soovivad Office ' i rakendust automatiseerida, kasutada CreateObject (Visual Standard) või CoCreateInstance (Visual C++). Siiski on juhtumeid, kus võite soovida automatiseerida juba käivitatud Office ' i rakendust: näiteks kui kasutaja on varem Office ' i rakenduse käivitanud. Kui olete käivitanud Office ' i rakenduse käivitatava koodi abil, et saaksite määrata rakenduse käsurea lüliteid. Töötava Office ' i rakenduse automatiseerimiseks peate kasutama GetObject või GetActiveObject.
Käitumise reprodutseerimise juhised
-
Käivitage Microsoft Visual Basic ja looge uus standard EXE-projekt. Form1 on loodud vaikimisi.
-
Lisage Form1 CommandButton juhtelement.
-
Lisage vormi koodi moodulile järgmine kood.
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
-
Veenduge, et Exceli. exe asukoht oleks koodiga proovis õige.
-
Sulgege Microsoft Excel, kui see on juba käivitatud.
-
Projekti käivitamiseks vajutage klahvi F5 ja klõpsake nuppu Command1.
Lahendus
Probleemi lahendamiseks saate teha järgmist.
-
Saate fookuse panna Office ' i rakendusele, muutes funktsiooni Shell teise argumendiks kas vbMinimizedFocus, vbMaximizedFocusvõi vbNormalFocus.
-
Keskenduge visuaalsele põhivormile.
-
Proovige GetObject , kui arvestada Office ' i rakenduse laadimise ajal.
Järgmine muudetud kood illustreerib seda lahendust.
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++ jaoks mõeldud lahendus
Kui olete programmeeritud c + +-s, näitab järgmine kood valimi sarnast lahendust ülaltoodud Visual põhiproovis näidatud lahendusele. Pange tähele, et SetForegroundWindow kasutatakse fookuse viimiseks Excelist eemale, mis võimaldab tal oma jooksvaid objekte registreerida.
//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();
Viited
Lisateabe saamiseks klõpsake Microsofti teabebaasi (Knowledge Base) artiklite kuvamiseks järgmisi artiklinumbreid:
192919 Turvatud Accessi andmebaasi automatiseerimine Visual algteadmised kasutades
237338 Tõrketeade WordMaili abil: "See meetod või atribuut pole saadaval"
240794 Office ' i rakenduse tee määratlemine