Announcement

Collapse
No announcement yet.

Application Return value

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Application Return value

    Been a while since I've used the DOS compiler full time. I'm needing
    to make a Band-Aid application to call a program and check its return
    value. 0= Good, anything else= error. What happens is sometimes when 0
    is returned it is after a Stack Overflow, so really there was an error condition.

    So, what I need to do is if <> 0 then END my app with the same return value so the calling
    program knows there was an error. If it returns 0 then I need to check a log file to see if
    it did what it was supposed to do. If it did then return 0, if not then return <> 0 so the
    calling app knows there was really an error. PB DOS has a way of returning completion codes with
    END, but how do I call an app and get the return code of it??? Shell and checking Err values doesn't
    appear to support this. Is ther a command I'm forgetting, or is there not a way to do this?

    ------------------
    If you aim at nothing...you will hit it.
    sigpic
    Mobile Solutions
    Sys Analyst and Development

    #2
    NT-class OS's don't support retrieving the exit code for 16-bit
    apps. I know for sure that applies to 16-bit Windows apps. I don't
    know if it applies to 16-bit DOS apps. It's been years since I read
    that on MSDN, and I don't remember where/how I found that article.
    But I would suggest the documentation for the GetExitCodeProcess() API
    as a start.


    ------------------
    Clay 's Website
    mailto:[email protected][email protected]</A>

    Comment


      #3
      No, both will be DOS applications running in DOS 5/6.

      I did find some code here calling INT 21, but the way it allocates
      the memory is a little weird. I'll play around with it, or try to find
      my old C++ Compiler or something. I'm surprised this wasn't supported since END
      allows for an exit code.

      ------------------
      If you aim at nothing...you will hit it.
      sigpic
      Mobile Solutions
      Sys Analyst and Development

      Comment


        #4
        Ahhh, gotcha. My MASM614 (DOS assembler) has a routine that
        allows to shell to another DOS app and retrieve the shelled
        app's exit code. If you wish, I will reinstall the MASM and
        PB/DOS 3.5 backups and see if I can interpret it enough to port
        it to a PB/DOS routine.

        But you will have to tell me if you want me to do it before I will.
        I haven't messed with DOS programming for 3-4 years, and that
        stuff has pretty much left my mind, so it might be quite a feat
        to recall enough of what I did so I can port it to PB/DOS.

        Hmmmm, just realized - I *might* be able to do some twisting around
        of the MASM "shell" procedure so I can compile it as an OBJ file that can
        be LINK'd into a PB/DOS app. Would that be your preference?


        ------------------
        Clay 's Website
        mailto:[email protected][email protected]</A>

        Comment


          #5
          Search POFFs or this forum for "ERRORLEVEL", there are plenty of posts about it..

          ------------------
          kgpsoftware.com - Downloads
          kgpsoftware.com - Development and Consulting
          kgpsoftware.com | Slam DBMS | PrpT Control | Other Downloads | Contact Me

          Comment


            #6
            How to set it:
            http://support.microsoft.com/kb/77457

            (int 21, service 4C)

            How to get it from a child program:
            Code:
            ' EXECDOS.BAS
            ' Execute an exteernal program as a child proccess, interrogate
            ' it's return code.
            ' For PB/DOS 3.2
            ' Author: Michael Mattias Racine WI 
            ' from original version for Microsoft QuickBASIC by Ethan Winer.
            
            
            '============================================================
            '     SUB TO Execute a program as a child process           
            ' Function value = return code of process; if < 0, error is 
            ' -1 * (dos error)
            '============================================================
            
            ' REG equates as expected in REGS.INC
            DEFINT A-Z
            FUNCTION DosExecute% (Program$, Parameter$) LOCAL
              '---- Prepare the program name and parameter strings for processing.  DOS
              '     requires that the parameter string hold the length of the parameter
              '     text, followed by the parameter text, and then followed by a CHR$(13)
              '     Enter byte.  The parameter block holds two CHR$(0) bytes followed by
              '     the address and segment of the parameter string.
              '
              DIM Block   AS LOCAL STRING * 14    'this is the DOS parameter block
              DIM Parm    AS LOCAL STRING * 80    'and this is the actual parameter text
            
              DIM ZBuffer AS LOCAL STRING * 80    'this holds a copy of the program name
            
              SaveDefSeg = pbvDefSeg
              DEF SEG
              DefaultDS = pbvDefSeg
              Zero$ = CHR$(0)                  'invoke CHR$() only once for efficiency
              DOS = &H21                       'saves a few bytes
              ZBuffer$ = Program$ + Zero$      'make an ASCIIZ string for DOS
            
              LSET Parm$ = CHR$(LEN(Parameter$)) + Parameter$ + CHR$(13)
              LSET Block$ = Zero$ + Zero$ + MKI$(VARPTR(Parm$)) + MKI$(VARSEG(Parm$))
            
              Dummy& = SETMEM(-500000)         'free up memory for the program being run
              REG %RegAX, &h4B00
              REG %RegDX, VARPTR (ZBuffer$)
              REG %RegES, VARSEG(Block$)
              REG %RegBX, VARPTR(Block$) 
              REG %RegDS, DefaultDS
              CALL INTERRUPT DOS
              Flags = REG(0)
              ReturnAX = REG(%RegAX)
              IF (Flags AND 1) THEN          'DOS error trying to run the program?
                DosExecute% = -(ReturnAX)    'yes, set function value to -1 * error code
                GOTO Execute.Done            'and jump to reclaim memory
              END IF
            
              REG %RegAX, &H4D00               'retrieve subordinate process code
              CALL Interrupt DOS
              DosExecute% = REG (%RegAX)          'set function value to exit code
            
            Execute.Done:
              Dummy& = SETMEM(500000)          'reclaim the memory relinquished eariler
              DEF SEG = SaveDefSeg             ' restore DS to what it was at entry.
            
            END FUNCTION
            MCM



            [This message has been edited by Michael Mattias (edited December 07, 2006).]
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


              #7
              Code:
              on error goto errortrap
              
              open "onlyfortesting" for input as #1     'to force an error
              
              '...
              ' your code here
              '...
              
              errortrap:
                  'some error trap here
                  'or only continue to
                  PRINT ERR
                  END ERR
              ------------------
              Arthur Gomide
              Como diria nosso profeta da bola, Dadá Maravilha: "Para toda Problemática existe uma Solucionática!"
              "The trouble with quotes on the Internet is that you can never know if they are genuine." - Abraham Lincoln.

              Comment


                #8
                If you're not going to believe the return code all the time,
                why not just do your check of the log file from the other
                program?


                ------------------

                Comment


                  #9
                  No need to check it if there is an actual error. And if it gets corrupt or
                  in a state I'm not testing for then it could return an error when nothing
                  is wrong.

                  I made sort of a hybrid of Michael's code and the other's I found along
                  with looking up the interupts and seeing what they really need. The Code
                  below seems to work and doesn't blow up.

                  Code:
                  Function PBExec (Program As String, Parameter As String) As Integer
                  ' DOS requires that the parameter string hold the length of the parameter
                  ' text, followed by the parameter text, and then followed by a CHR$(13)
                  ' Enter byte. The parameter block holds two CHR$(0) bytes followed by
                  ' the address and segment of the parameter string.
                  
                  Dim Block As String * 14 'this is the DOS parameter block
                  Dim Parm As String * 80 'and this is the actual parameter text
                  Dim ZBuffer As String * 15 'this holds a copy of the program name
                  Dim Zero As String * 1
                  Dim SaveDefSeg As Word
                  Dim Dummy As Long
                  
                  SaveDefSeg = pbvDefSeg
                  Zero = Chr$(0) 'invoke CHR$() only once for efficiency
                  ZBuffer = Program + Zero 'make an ASCIIZ string for DOS
                  LSet Parm = Chr$(Len(Parameter)) + Parameter + Chr$(13)
                  LSet Block = Zero + Zero + Mki$(VarPtr(Parm)) + Mki$(VARSEG(Parm))
                  Dummy = SETMEM(-500000) 'free up memory for the program being run
                  
                  REG 1, &h4B00 ' AX
                  REG 4, VarPtr(ZBuffer) ' DX
                  REG 9, VARSEG(Block) ' ES
                  REG 2, VarPtr(Block) ' BX
                  REG 8, VARSEG(ZBuffer) ' DS
                  Call INTERRUPT &H21
                  
                  If (REG(0) And 1) Then 'DOS error trying to run the program?
                     PBExec = -(REG(1)) ' set function value to -1 * DOS error code
                  Else
                     REG 1, &H4D00 'retrieve subordinate process code (AX)
                     Call Interrupt &H21
                     PBExec = REG(1) 'set function value to exit code (AX)
                  End If
                  
                  Dummy = SETMEM(500000) 'reclaim the memory relinquished eariler
                  DEF SEG = SaveDefSeg ' restore DS to what it was at entry.
                  End Function
                  ------------------
                  If you aim at nothing...you will hit it.
                  sigpic
                  Mobile Solutions
                  Sys Analyst and Development

                  Comment


                    #10
                    Roger,

                    Couldn't you just check the log file and forget about any returns
                    from the band-aid program? Sounds like the easiest solution.

                    ------------------
                    C'ya
                    Don
                    don at DASoftVSS dot com
                    http://www.DASoftVSS.com
                    --
                    "There are 2 Ss in Christmas, Cratchet, and they're both dollar signs!"
                    C'ya
                    Don

                    http://www.ImagesBy.me

                    Comment


                      #11
                      Couldn't you just check the log file and forget about any returns
                      from the band-aid program? Sounds like the easiest solution.
                      That would be highly dependent on the application.

                      "Checking the log" is simply not effective in a high-volume situation, where what you want is exception-based reporting/action. Using return codes wisely is an excellent way to effect this kind of reporting.

                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                        #12
                        Exactly. There are like 5 different situations to check for:

                        < 0 meaning it can't spawn, and mine reports -1 back for any negative
                        value since the C++ spawn command calling it returns that.

                        0 which is the only time I check the log to verify. Normal logs have time/dates
                        and 3 other fields per row for what is going on, what is sending, and its process. I didn't
                        write the code making this and don't have access to it, so have no clue what it could
                        log for all cases. All I want is if the file contains the text "run-time error" and
                        reported 0 that it reports an error instead so the application calling it doesn't think
                        everything is fine. It still needs the other 1-28 codes to know what to do on those no
                        matter what the log says good or bad.

                        1 to 28 meaning error

                        29 to 255 which to me would mean error, but the company said they are fine.

                        Then a check I added for > 255 since it is possible in the function
                        calling that it gets a device error and the High Byte(AH) gets set. No
                        chance of Ctl+Break or TSR Ends setting them high, but this does use
                        Serial, so I wanted to cover all bases and return an error for it...and since
                        the original code sees > 28 as fine I return 1 so it is in the error range.

                        This is just a Band-Aid being named the original called filename and calling the
                        renamed original file since an application upgrade to do this and detect the issue
                        will take 6 months and they need it now, so I made this in a day...

                        For some reason out of the blue this application our software calls started getting
                        Stack Overflows. I'm guessing because of communication errors and retries at certain
                        locations and Fuji programmers suck and didn't know how to error check better or used
                        recursive function calls. Since their stuff comes and goes like Stanley Tools...no
                        one can fix it. So, we have to recover from it.

                        ------------------
                        If you aim at nothing...you will hit it.



                        [This message has been edited by Roger Garstang (edited December 08, 2006).]
                        sigpic
                        Mobile Solutions
                        Sys Analyst and Development

                        Comment

                        Working...
                        X
                        😀
                        🥰
                        🤢
                        😎
                        😡
                        👍
                        👎