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