Re: Unable to get meaningful error info from VB dll
Josh Passenger <[email protected]> Fri, 9 Jun 2006 00:02:10 +1000
| Newsgroups | gmane.comp.windows.devel.jawin |
|---|---|
| Message-ID | <[email protected]> |
LOL thats why I always try to code as little COM as possible.... =\ Are people using the type browser in earnest, any successes / failures? Josh >From: Claude Eisenhut <[email protected]> >Reply-To: Discussion of Java/Win32/COM integration with Jawin ><[email protected]> >To: [email protected] >Subject: Re: [JAWIN] Unable to get meaningful error info from VB dll >Date: Thu, 8 Jun 2006 11:53:51 +0200 >MIME-Version: 1.0 >Received: from bay0-mc2-f5.bay0.hotmail.com ([65.54.244.45]) by >bay0-imc3-s19.bay0.hotmail.com with Microsoft SMTPSVC(6.0.3790.1830); Thu, >8 Jun 2006 02:54:14 -0700 >Received: from discuss.develop.com ([66.129.110.38]) by >bay0-mc2-f5.bay0.hotmail.com with Microsoft SMTPSVC(6.0.3790.1830); Thu, 8 >Jun 2006 02:54:13 -0700 >Received: from develop-lserv (66.129.110.38) by discuss.develop.com (LSMTP >for Windows NT v1.1b) with SMTP id <[email protected]>; Thu, 8 >Jun 2006 5:50:49 -0400 >Received: from DISCUSS.DEVELOP.COM by DISCUSS.DEVELOP.COM (LISTSERV-TCP/IP > release 1.8e) with spool id 4719934 for [email protected]; > Thu, 8 Jun 2006 05:50:49 -0400 >Received: from kunigunde.ehi.ch (213.239.193.3) by discuss.develop.com >(LSMTP for Windows NT v1.1b) with SMTP id ><[email protected]>; Thu, 8 Jun 2006 5:50:48 -0400 >Received: from lemon (static-pro-212-101-28-57.adsl.solnet.ch >[212.101.28.57]) (authenticated (0 bits)) by kunigunde.ehi.ch >(8.11.6/8.11.6) with ESMTP id k588VZ225134 for ><[email protected]>; Thu, 8 Jun 2006 10:31:39 +0200 >X-Message-Info: LsUYwwHHNt2L0xhB6t2pymsCT85oNu6ibiySs0d2mGE= >References: <[email protected]> >X-MSMail-Priority: Normal >X-Mailer: Microsoft Outlook Express 6.00.2800.1106 >X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 >Precedence: list >Return-Path: [email protected] >X-OriginalArrivalTime: 08 Jun 2006 09:54:13.0729 (UTC) >FILETIME=[7F750D10:01C68AE1] > >I have the same problem and investigated it a little bit. > >I think the problem is in the C++ part near the GetErrorInfo() call. >According to the MS doc, befor you can call GetErrorInfo, you have to call >pObjectWithError->QueryInterface(IID_ISupportErrorInfo,...) >and >InterfaceSupportsErrorInfo(...) > >see "Retrieving Error Information (Component Automation) " >http://msdn.microsoft.com/library/default.asp?url=/library/en-us/automat/htm >l/0bd640a4-e93f-4201-8789-61ba7178ce15.asp > >And also >// Do not test the return of GetErrorInfo. It can succeed and return >// a NULL pointer in pIErrorInfoAll. Simply test the pointer. >At http://msdn2.microsoft.com/en-us/library/ms131391.aspx > >So far, I didn't have time to try this. > >Claude > >----- Original Message ----- >From: "Brian Hirsch" <[email protected]> >To: <[email protected]> >Sent: Wednesday, June 07, 2006 11:54 PM >Subject: [JAWIN] FOLLOWUP: Re: [JAWIN] Unable to get meaningful error info >from VB dll > > > > First, thanks Sean for responding. I appreciate the ideas to try. We >are >still having the same problem, however. > > > > Taking a slightly different approach, is there anyone who has a >working >example of a simple VB class causing an error and you receive good >information back? If we had that, perhaps we could work from there. > > > > Also, if anyone has ideas on what we could try or what we're missing, >it >would be greatly appreciated. > > > > Thanks > > Brian > > > > Brian Hirsch <[email protected]> wrote: > > Changing the method to the following make no difference. > > Public Function DivisionByZeroError() As Long > > DivisionByZeroError = 1 / 0 > > End Function > > I have tried Err.Raise and that also make no difference. This is a very >simple test for the purpose of asking the question - the result is the same >for all VB dlls. > > Have also tried using the setErrorInfo and GetErrorInfo methods - result >is the same. > > I have tried wrapping a C++ DLL and without any additional work the >error >is correctly reported, similar to the case for ADODB. > > I have stepped through the code and the difference between the C++ >result >and the VB result occurs inside the call to the Native method >dispatchInvoke0. When the error information is passed up correctly the call >to the COMException constructor differ as follow: > > > > In the working case (C++ and example shown ADODB) the >dispatchInvoke0method calls the following constructor for COMException. As >shown this calls back into the verbose Exception constructor as >COMException >extends Exception > > public COMException(int hresult, String desc, String source, String >guid) >{ > > super (desc + "[src=" + source + ",guid=" + guid+ "]"); > > this.hresult = hresult; } > > > > However, in the failure case (VB) the dispatchInvoke0 method calls to a >different constructor for COMException. This calls into a more limited >constructor on Exception. > > public COMException(int hresult, String text) { > > super(text); > > this.hresult = hresult; } > > The problem I have is that I do not know what happens inside >dispatchInvoke0 that causes different constructors to be called. > > For anyone familiar with C++, the method in question is > > /** > > * java marshalling/unmarshalling, before/after the invocation of a >native >dispatch based COM method > > */ > > JNIEXPORT jbyteArray JNICALL >Java_org_jawin_marshal_GenericStub_dispatchInvoke0 > > (JNIEnv* env, jclass, jstring instString, jint stackSize, jint >requestSize, jbyteArray request, > > jstring jmeth, int flags, jint peer, jint unknown) > > { > > se_translator translator; > > try { > > string str; > > JNIComUtil::jstostr(env, instString, str); > > IStreamOnMemory instructions(str.c_str(), str.length() + 1); > > CComBSTR meth; > > meth.Attach(JNIComUtil::jstobs(env, jmeth)); > > BatchReleaser br; > > > > IStreamOnMemory javaIn(request, requestSize, env); > > jint stackSizeWithRet = stackSize + 1; > > > > // Allocate memory for variants > > size_t vntsSize = sizeof(VARIANT) * stackSizeWithRet; > > VARIANT* vnts = (VARIANT*)MarshalAllocator::SafeMalloc(vntsSize, NULL); >// >should we pass the BatchReleaser? > > for (int i = 0; i < stackSizeWithRet; ++i) { > > ::VariantInit(vnts + i); > > } > > > > OStreamOnMemory comIn(vnts, vntsSize, true, true); > > Transform tin(env, &br, javaIn, instructions, comIn, NULL); > > callDisp(meth, stackSize, flags, peer, unknown, (void*) comIn.getMem()); > > > > IStreamOnMemory result((byte*)comIn.getMem() + >stackSize*sizeof(VARIANT), >sizeof(VARIANT)); > > IStreamOnMemory comOut((byte*)comIn.getMem(), >stackSize*sizeof(VARIANT)); > > OStreamOnMemory javaOut(calloc(sizeof(VARIANT), 1), sizeof(VARIANT), >true, >true); > > //write retval into stream > > Transform tret(env, &br, result, instructions, javaOut, NULL); > > //write out params into stream > > Transform tout(env, &br, comOut, instructions, javaOut, NULL); > > > > // call the batch releaser explicit since we would otherwise be unable >to >call > > // VariantClear below on SafeArrays, as they would be locked -> >VariantClear would > > // return DISP_E_ARRAYISLOCKED and we would leak. > > br.~BatchReleaser(); > > > > // If return type is neither IDispatch nor IUnknown, then > > // free the Variant to avoid a memory leak. In the case of > > // IDispatch or IUnknown, the object would be released causing > > // Java to have a reference to a freed object > > > > // FIXME - what are the "memory ownership"-rules for IDispatch > > // what should we do with any [out] VARIANTS? - from the performance >tests, it > > // doesn't look like we are leaking. > > VARIANT* tmp = vnts + stackSize; > > if ((tmp->vt != VT_DISPATCH) && (tmp->vt != VT_UNKNOWN)) { > > ::VariantClear(tmp); // pt. we ignores any fails here - as we can't >really >do anything but leak? > > } > > > > if (javaOut.getPos() == 0) { > > return 0; > > } > > return MarshalAllocator::allocateByteArray(env, javaOut.getMem(), >javaOut.getPos()); > > } > > HANDLE_WIN32_EXCEPTIONS() > > HANDLE_JNI_EXCEPTIONS() > > return 0; > > } > > > > > > > > "Mcnamara, Sean D" wrote: Brian, > > > > Perhaps the line > > > > CreateObject("DebugTools_80.Helper").LogAndReRaiseVBError Err, App, Erl, >sThisProject, sThisComponent, sThisFunction > > > > is incorrectly using the Err object? I've never worked with a >DebugTools_80.Helper object, but you need to use the Err.Raise method with >the correct parameters, including the number: > > > > Dim desiredNum As Integer > > Err.Raise number:=vbObjectError + desiredNum, etc1, etc2, etc3, etc4 > > > > Also, make sure your VB DLL is not compiled with options to eliminate >div/0 checks! Otherwise the VBVM60.DLL will, itself, divide by zero and >cause your module to crash. > > > > Is your LogAndReRaiseVBError function "logging" this error anywhere? Try >and verify that this line of code is actually being executed. For instance, >try displaying a MsgBox before you call this statement, to make sure that >your error handler is executed. JAWIN should have no problem displaying >message boxes without modifying your code, if I recall correctly... > > > > > > > > > > -----Original Message----- > > From: Discussion of Java/Win32/COM integration with Jawin >[mailto:[email protected]] On Behalf Of Brian Hirsch > > Sent: Thursday, June 01, 2006 8:25 AM > > To: [email protected] > > Subject: [JAWIN] Unable to get meaningful error info from VB dll > > > > We've been unable to get meaningful error information back from a method >call to a VB dll. My configuration is Windows XP, Java 1.4, Jawin 2.0, >Visual Studio SP 6. We've created a simple VB class with one method: >DivisionByZeroError. As you'd guess, this method tries to divide by zero. >I've included all the source code at the bottom. Wrapper classes have been >created for the VB class and are used to access the VB class. > > When we call the method, it is executing the code and is coming back >with >an COMException, but all the detailed message says is: Exception occurred. >Here's the output from the calling java class: > > The return was error Info :-2147024809 > > org.jawin.COMException: 80020009: Exception occurred. > > at org.jawin.marshal.GenericStub.dispatchInvoke0(Native Method) > > at org.jawin.marshal.GenericStub.dispatchInvoke(GenericStub.java:84) > > at org.jawin.DispatchPtr.invokeN(DispatchPtr.java:473) > > at org.jawin.DispatchPtr.invokeN(DispatchPtr.java:433) > > at com.cognos.baia.dtptest.DTP.DivisionByZeroError(DTP.java:18) > > at com.cognos.baia.ado.Test.main(Test.java:88) > > > > We get an hresult (-2147352567), but no good exception information. > > As another test, we set up wrappers to access an ADODB dll. When we try >to >open a connection with an incorrect connection string, we get this in the >detailed message: > > [Microsoft][ODBC Driver Manager] Data source name not found and no >default >driver specified[src=Microsoft OLE DB Provider for ODBC >Drivers,guid={0C733A8B-2A1C-11CE-ADE5-00AA0044773D}] > > > > Good stuff! > > > > the stack trace looks like this: > > org.jawin.COMException: 80020009: [Microsoft][ODBC Driver Manager] Data >source name not found and no default driver specified[src=Microsoft OLE DB >Provider for ODBC Drivers,guid={0C733A8B-2A1C-11CE-ADE5-00AA0044773D}] > > The return was error Info from Connection:-2147024809 > > at org.jawin.marshal.GenericStub.dispatchInvoke0(Native Method) > > at org.jawin.marshal.GenericStub.dispatchInvoke(GenericStub.java:84) > > at org.jawin.DispatchPtr.invokeN(DispatchPtr.java:473) > > at org.jawin.DispatchPtr.invokeN(DispatchPtr.java:433) > > at org.jawin.DispatchPtr.invoke(DispatchPtr.java:377) > > at com.cognos.baia.ado.Connection.Open(Connection.java:85) > > at com.cognos.baia.ado.Test.getCommand(Test.java:48) > > at com.cognos.baia.ado.Test.main(Test.java:104) > > > > So, we get good error information from the ADODB call, but minimal from >the VB call. What are we doing wrong? Why can't we get better error >information back from this VB dll? > > > > Thanks > > Brian > > > > Here's the code from the VB class: > > Public Function DivisionByZeroError() As Long > > ' > > On Error GoTo ErrorHandler > > Const sThisProject As String = "Project1": Const sThisComponent As >String >= "DTP": Const sThisFunction As String = "DivisionByZeroError": Const >sThisProcedure As String = sThisProject & "." & sThisComponent & "." & >sThisFunction > > ' > > > > 100 DivisionByZeroError = 1 / 0 > > > > > > ' > > Exit Function > > ErrorHandler: > > CreateObject("DebugTools_80.Helper").LogAndReRaiseVBError Err, App, Erl, >sThisProject, sThisComponent, sThisFunction > > ' > > End Function > > > > Here's how we call it in Java: > > try { > > Ole32.CoInitialize(); > > DTP dtp = new DTP(); > > dtp.DivisionByZeroError(); > > Ole32.CoUninitialize(); > > } catch (COMException e) { > > // TODO Auto-generated catch block > > int errorInfo = getErrorInfo(); > > System.out.println("The return was error Info :" + errorInfo); > > e.printStackTrace(); > > } > > Here's how we're calling the ADODB dll: > > try { > > String connectStr = args[0]; > > String queryStr = "select * from authors"; > > getCommand(connectStr, queryStr); > > // getRS(connectStr, queryStr); > > } catch (Throwable t) { > > int errorInfo = getErrorInfo(); > > System.out.println("The return was error Info from Connection:" + >errorInfo); > > t.printStackTrace(); > > } > > public static void getCommand(String con, String query) throws >COMException // throws > > // Exception > > { > > System.out.println("Command+Connection -> Recordset"); > > Connection c = new Connection("ADODB.Connection"); > > c.setConnectionString(con); > > c.Open(); > > Command comm = new Command("ADODB.Command"); > > comm.setActiveConnection(c); > > comm.setCommandType(CommandTypeEnum.adCmdText); > > comm.setCommandText(query); > > Recordset rs = comm.Execute(); > > printRS(rs); > > comm.close(); > > c.Close(); > > } > > Here's how we're going after the error information: > > private static int getErrorInfo() { > > int ret = 0; > > try { > > FuncPtr getErrInfo = new FuncPtr("OLEAUT32.DLL", "GetErrorInfo"); > > ret = getErrInfo.invoke(0, 0, ReturnFlags.FAIL_ON_FALSE); > > } catch (COMException e) { > > // TODO Auto-generated catch block > > e.printStackTrace(); > > } > > return ret; > > } > > > > > > > > --------------------------------- > > Talk is cheap. Use Yahoo! Messenger to make PC-to-Phone calls. Great >rates >starting at 1ยข/min. > > > > > > > > --------------------------------- > > How low will we go? Check out Yahoo! Messenger's low PC-to-Phone call >rates. > > > > > > __________________________________________________ > > Do You Yahoo!? > > Tired of spam? Yahoo! Mail has the best spam protection around > > http://mail.yahoo.com