Exceptions with OLE

Hagrinas
2008-05-14
2012-08-14
  • Hagrinas
    Hagrinas
    2008-05-14

    I'm trying to write a program that gets to SAS with OLE. ooRexx is blowing up with an exception when I invoke some methods, and I'm not sure what is going on.

    I tried getKnownMethods and walked through the results for the relevant method, and found that for the second parameter, it's showing VT_PTR, which is not in the ooRexx documentation's list of variants. For that parameter, I'm supposed to pass an array of four items, the first of which is a number, and the rest of which are supposed to be for output.

    This is what getKnownMethods spit out:

    InvokeMethod
    method InvokeMethod
    SCRIPTOLib
    Scripto 1.1 Type Library
    IScripto
    IScripto Interface
    1
    VT_VARIANT
    00000003
    2
    methodName
    VT_BSTR
    [in]
    inParams
    VT_PTR
    [in,out]

    This is a sample program in VB that does what mine should do. It's the FlushLogLines method that's the problem:

    set obSAS = CreateObject("SAS.Workspace.1.0")
    Set obScripto = CreateObject("SASScripto.Scripto")
    obSAS.LanguageService.Submit "proc options;run;"
    obScripto.SetInterface obSAS.LanguageService

    ' This example uses Scripto to invoke the FlushLogLines method
    ' instead of invoking the method directly from VBScript
    ' as shown in the following statement:
    ' obSAS.LanguageService.FlushLogLines 1000, carriageControls,_
    ' linetypes, logLines

    Dim flushLogLinesParams(3)
    ' Note that the FlushLogLines method takes 4 parameters:
    ' 1) numLinesRequested (in) Specifies an upper limit on the
    ' number of lines to be returned.
    ' 2) carriageControls (out) An array that indicates carriage
    ' control for each line returned.
    ' 3) lineTypes (out) An array that indicates the line type
    ' for each line returned.
    ' 4) logLines (out) Contains the SAS log output lines
    ' retrieved by this call.

    flushLogLinesParams(3) = 1000
    obScripto.InvokeMethod "FlushLogLines",_
    flushLogLinesParams

    ' flushLogLinesParams(0) now has logLines
    ' flushLogLinesParams(1) now has lineTypes
    ' flushLogLinesParams(2) now has carriageControls

    ' Print the first line
    wscript.echo flushLogLinesParams(0)(0)


    Their example shows a commented out alternative, and obsas~languageservice~getKnownMethods returns this for the method when called directly:

    FlushLogLines
    Flush log lines that were spooled by program execution.
    SAS
    SAS: Integrated Object Model (IOM) (SAS System 9.1) Type Library
    ILanguageService
    A service for submitting SAS language and obtaining output from the SAS list and
    log.
    1
    VT_VOID
    6002000f
    4
    NumLinesRequested
    VT_I4
    [in]
    CarriageControls
    VT_PTR
    [out]
    LineTypes
    VT_PTR
    [out]
    LogLines
    VT_PTR
    [out]

    If I use .nil for the outs then ooRexx blows up with an exception. If I use the unknown method, ooRexx does not blow up, but it gives an error about being unable to convert vt_error, so the message doesn't tell me anything useful to me.

    Of course having ooRexx blow up with an exception is a problem too.
    AppName: rexx.exe AppVer: 3.2.0.1 ModName: oleaut32.dll
    ModVer: 5.1.2600.3266 Offset: 00004f2a

     
    • Mark Miesfeld
      Mark Miesfeld
      2008-05-15

      Hagrinas,

      Thanks for reporting this, I'll take a look at it. Unfortunately I'm going out of town for a while and will not have Internet access for about 2 weeks.

      I don't suppose SAS has a trial version, or something I can use to look at this on my system?

      I fixed a couple of OLEObject bugs right after 3.2.0 was released. I can get you a build of the fixed DLL that you can drop into your installation, to see if it fixes the crash, if you are interested.

      Also, can you post your ooRexx code, any different versions of the code you have tried.

      Thanks.

      --
      Mark Miesfeld

       
    • Mark Miesfeld
      Mark Miesfeld
      2008-05-16

      Hagrinas,

      I think this is the format you should try. I believe the method takes four arguments.

      obSAS~LanguageService~FlushLogLines(1000, carriageControls, linetypes, logLines)

      I would try something like this first:

      carriageControls = .array~new
      lineTypes = .array~new
      logLines = .array~new

      obSAS~LanguageService~FlushLogLines(1000, carriageControls, linetypes, logLines)

      If that doesn't work then I would try playing with OLEVariant. Maybe something like:

      carriageControls = .array~new
      lineTypes = .array~new
      logLines = .array~new

      vCC = .OLEVariant~new(carrigageControls, "VT_VARIANT,VT_ARRAY", "IN,OUT")
      vLT = .OLEVariant~new(lineTypes, "VT_VARIANT,VT_ARRAY", "IN,OUT")
      vLL = .OLEVariant~new(LogLines, "VT_VARIANT,VT_ARRAY", "IN,OUT")
      obSAS~LanguageService~FlushLogLines(1000, vCC, vLT, vLL)

      The last 3 arguments should definitely have a type of: VT_VARIANT | VT_ARRAY ooRexx may do the conversion correctly, if not use OLEVariant.

      I'll try to get you the DLL tomorrow before I leave, but I may not have time. ;-( In 3.2.0 there was a problem where an empty array was wrongly handled. If you don't get the DLL from me before I leave, and the above doesn't work, try putting one element in each array, a simple " " should be enough.

      Email me directly if you can, so I have some place to send the DLL.

      --
      Mark Miesfeld
      miesfeld@gmail.com

       
    • I'd like a copy of the new DLL.

      SAS does have trial versions for 30 days, but it's a matter of going through their sales department and getting a non technical person who is looking to get a sale out of it. Once I get the DLL, it will be easier to assess the need for addressing that.

      I'll do what I can when I have time. I tried a variety of things in ooRexx, many of which I wouldn't have tried under normal circumstances, and would be more than happy to run any sort of test matrix and report any errors in detail, if there still are any. The ooRexx code should amount to a few lines, except that my code is using a rudimentary class library, and creating a SASIOMobject that's a subclass of OleObject, so it would make more sense for me to post something simpler.

      Here's a random sampling of lines of code, all of which were tried in various ways, and none of which constitutes an ooRexx program. Most of the trials were run with trace ?r and with me dynamically issuing commands, many of which I did not capture.

      --flushLogLinesParams=.array~of(o1,cc,lt,loglines)
      --flushLogLinesParams=.array~of('1000',.nil,.nil,.nil)
      --obScripto~unknown("InvokeMethod",.array~of("FlushLogLines",flushLogLinesParams))
      --obSAS~LanguageService~unknown("FlushLogLines",flushLogLinesParams)
      obSAS~LanguageService~FlushLogLines(1000,.nil,.nil,.nil)
      --flushLogLinesParams = .OLEVariant~new(p,"VT_DISPATCH,VT_ARRAY","IN,OUT")
      -- logLines = .OLEVariant~new(.nil,"VT_BSTR,VT_BYREF")
      -- o1 = .OLEVariant~new('1000',"VT_BSTR,VT_BYREF")

      Don't take any of these to be contiguous or assume that a given variable in one statement is the same as the one referenced in another. Essentially, if I were to post a program, it would consist of what I thought should have worked in the first place, which is mostly taking the VBS and making appropriate syntax changes, with the exception of invoking FlushLogLines. But after continuous butchering and abandoning my original strategy, I don't have something that resembles the test case.

      I think getting the DLL would be a good next step.