Exceptions with OLE

  • 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:

    method InvokeMethod
    Scripto 1.1 Type Library
    IScripto Interface

    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(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:

    Flush log lines that were spooled by program execution.
    SAS: Integrated Object Model (IOM) (SAS System 9.1) Type Library
    A service for submitting SAS language and obtaining output from the SAS list and

    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: ModName: oleaut32.dll
    ModVer: 5.1.2600.3266 Offset: 00004f2a

    • Mark Miesfeld

      Mark Miesfeld - 2008-05-15


      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.


      Mark Miesfeld

    • Mark Miesfeld

      Mark Miesfeld - 2008-05-16


      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

    • Nobody/Anonymous

      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 = .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.


Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks