Announcement

Collapse
No announcement yet.

File access / COMMAND$() problems when using EXE app.

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

  • File access / COMMAND$() problems when using EXE app.

    I'm making use of the PBCC6.0 compiler and working on an app that:

    takes command line parameters, E.g. App.exe file1.txt file2.txt 4

    opens two files in Binary mode, one in Read (file2.txt), one in Write/Append (file1.txt)


    The app gives the appearance of working correctly, creating the right contents in
    file1.txt, when run through the PB/CC IDE using the Command Line window.

    However it fails when run through a CMD window, having typed":
    App.exe file1.txt file2.txt 4


    The problem has been observed on Win95 & Win10


    I have inserted the following in the app code:
    #DEBUG DISPLAY ON
    #DEBUG ERROR ON

    ? COMMAND$(x) ' Where X has the appropriate values
    FLUSH (with appropriate filenum)

    When the app is run as a EXE, the above commands show no runtime problems.

    But what I do observe when the app is run as a EXE, is:

    File1.txt gets created with a file prefix matching the digit of the last
    command line parameter, i.e 4.txt 0 Bytes

    File1.txt has a length of zero bytes.

    If File1.txt already exists no characters are appended and an additional file
    is created, i.e 4.txt 0 Bytes


    Any suggestions as what to try would be appreciated.

    Thank you.


  • #2
    Hi Simon,

    Welcome to the forum!

    I haven't had any problems when using the command line.

    Maybe you can post your code, or part of it, so we can do a real analysis of the events.

    Regards

    "The trouble with quotes on the Internet is that you can never know if they are genuine." - Abraham Lincoln.

    Comment


    • #3
      One way could be to use CommandLineToArgvW to do the job...

      Pierre
      Code:
      '______________________________________________________________________________
      
       LOCAL pArg     AS WSTRINGZ POINTER
       LOCAL ArgCount AS LONG
      
       pArg = CommandLineToArgvW(BYVAL GetCommandLineW, ArgCount)
       IF pArg THEN 'We have something
         DIM sArg(0 TO ArgCount - 1) AS STRING
         FOR Looper = 0 TO ArgCount - 1 'sArg(0) is exe full filename
          sArg(Looper) = @@pArg         'Space between quotes are considered part of a filename  
          pArg = pArg + 4
         NEXT
         LocalFree(pArg) 'Free memory allocated by CommandLineToArgvW
         FOR Looper = 0 TO ArgCount - 1
           PRINT STR$(Looper) & ") " sArg(Looper)
         NEXT
       END IF
       'With <"My File.txt" "This File.txt" 4>
       'Return:
       '        0) D:\Basic\Bas\~~ScratchPad01.EXE
       '        1) My File.txt
       '        2) This File.txt
       '        3) 4
      '______________________________________________________________________________
      '

      Comment


      • #4
        I've written a lot of applications which accept one or more input files and create one or more output files and other options. I always separate my file names with semicolon so there is never any confustion (for ME) about parsing out the names.

        So your program would have a command line of
        Code:
        C:\whatever>  Start  App.exe file1.txt;file2.txt; 4
        It looks to me like using COMMAND$(n) the parsing is being done differently than I would do it by hand.

        The difference between using IDE and EXE (although your note says EXE twice) may be a leading space or something like that in the command line. I suggest you create a log (or at least print to console) the startup info...
        Code:
        APP.EXE begins at <date and time>
        Command Line is: '< entire command line>'
        Argument 1 (input file ) is '<arg1>'
        Argument 2 (output file) is '<arg 2> '
        Argument 3 (???) is  '4'
        That will at least tell you what your program is trying to do. (I always use the delimiters as it helps detect unwanted leading/trailing spaces)

        I think maybe you should add one more line to output:
        Code:
        Current Directory Is '< use CURDIR$ function here>'
        Since your code for writing the files is not shown, I have to guess but it's possible those files are being created just fine, just not in the folder where you are looking.

        OR, the writes are failing and you are not checking for this.

        MCM
        Michael Mattias
        Tal Systems Inc.
        Racine WI USA
        mmattias@talsystems.com
        http://www.talsystems.com

        Comment


        • #5
          Like as above using PowerBASIC encapsulation,
          since it's based on CommandLineToArgvW you may have a look for more infos on MSDN

          Pierre

          Code:
           LOCAL ArgIndex AS LONG
           LOCAL sArg     AS STRING
           DO
             sArg = COMMAND$(ArgIndex)
             IF LEN(sArg) = 0 THEN EXIT DO
             PRINT STR$(ArgIndex) & ") " & sArg
             INCR ArgIndex
           LOOP

          Comment


          • #6
            Hi Simon,

            I could not duplicate your problem with this test code on Win7 or Win10, compiled with either PBCC6.04 or PBWin10.04
            Code:
            #Compile Exe        ' PBCC604 , PBWin1004
            #Dim All
            #If %Def(%PB_CC32)
             #Break On
            #EndIf
            #Include "win32api.inc"
            
            #If %Def(%PB_Win32)
              Macro StdOut = MsgBox
            #EndIf
            '------------------/
            
            Function PBMain () As Long
             Local x As Long, sTemp As String
            
              Do
                sTemp += COMMAND$(x) + $CRLF
                Incr x
              Loop While Len(Command$(x))
              StdOut sTemp
            
              Open Command$(1) For Binary As #1                 ' Open file1.txt for Read Write
              Open Command$(2) For Binary Access Read As #2     ' Open file2.txt for read only
              Get$ #2, Lof(#2), sTemp                           ' Read contents file2.txt
              Seek #1, Lof(#1)+1                                ' seek end of data (if pre-existing file)
              Put$ #1, sTemp + " " + Command$(3) + $CRLF        ' 'Append sTemp + Commands(3)
              sTemp = ""
              Seek #1, 1                                        ' Read Back
              Get$ #1, Lof(#1), sTemp
              Close
              StdOut " #1 " + $CRLF + sTemp
            
            #If %Def(%PB_CC32)
              ? "Any key to exit"
              WaitKey$
            #EndIf
            End Function
            '------------------/PBMain
            
            #IF 0
            'Enter in cmd window
            App.exe file1.txt file2.txt 4
            #ENDIF
            Click image for larger version  Name:	AppClipCCW.png Views:	1 Size:	18.4 KB ID:	756465
            Last edited by Dave Biggs; 3 Jan 2017, 01:04 AM. Reason: Added file operations to test code - still no problems found so far..
            Rgds, Dave

            Comment


            • #7
              Thank you Arthur, Pierre, Michael and Dave for your very helpful replies.


              I perhapes came to the forum in haste. I misread and misunderstood the Help for COMMAND$.

              Before coming back to the forum, I found where all (?) the mistakes were and the matter seems (?) to be resolved.

              Further testing showed up the issue of embedded spaces in path and file names.

              This has been my first attempt at using PowerBASIC in any form.

              I will be trying out your code examples, some of which is new to me.


              Some years back I saw this article at

              http://www.drdobbs.com/security/the-...ithm/210603676

              As an introductory learning exercise, I've attempted to take the C code and implement it (Beale cipher) in PowerBASIC.

              Attached should be my code implementation of one of the 3 modules.

              Regards
              Simon
              Attached Files

              Comment


              • #8
                Michael is right

                What I would do is in my opening lines
                PRINT "a"+first parameter +"b"

                This checks for extraneous first and last spaces

                I know that you have sorted it now, but using 'print' is my first line of debugging defence
                [I]I made a coding error once - but fortunately I fixed it before anyone noticed[/I]
                Kerry Farmer

                Comment


                • #9
                  but using 'print' is my first line of debugging defence
                  Or for PB/WIN users..==> Simple STDOUT for PB/DLL and PB/Win 2-13-04

                  (MSGBOX interrupts you too often).

                  Michael Mattias
                  Tal Systems Inc.
                  Racine WI USA
                  mmattias@talsystems.com
                  http://www.talsystems.com

                  Comment


                  • #10
                    Normally when I use a number of arguments on a command line I use one of my own algos to clean up any potential errors with dodgy spacing or inserted tabs instead of spaces but I think it was Michael (MCM) who had a normal PB string function to do the same. Then there is the format of command line options, if there are no spaces in a particular argument, parse it as is but if an argument contains spaces, you must enclose the argument in double quotes.

                    If you clean up the whole command line to single spacing it then becomes reliable to parse it into parts, usually an array of strings using the standard PB PARSE or PARSE$ and you still may need to use TRIM$ on individual array members.

                    You are welcome to this one if its useful to you, its easy to use and easily fast enough.

                    Code:
                    ' いいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
                    
                    FUNCTION monospace$(src$)
                    
                      ' ---------------------------------------------------------------------------
                      ' left and right trim string, replace tabs with spaces and set single spacing
                      ' ---------------------------------------------------------------------------
                        #REGISTER NONE
                    
                        LOCAL pst as DWORD
                        LOCAL dst$
                    
                        dst$ = src$                         ' work on copy
                    
                        pst = StrPtr(dst$)
                    
                        ! mov esi, pst
                        ! sub esi, 1
                        ! mov edi, pst
                    
                      trm:                                  ' trim leading tabs and spaces
                        ! add esi, 1
                        ! movzx eax, BYTE PTR [esi]
                        ! cmp eax, 32
                        ! je trm
                        ! cmp eax, 9
                        ! je trm
                    
                        ! sub esi, 1
                        ! or ebx, -1                        ' set EBX non zero so it falls through the 1st TEST
                    
                      ' =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                    
                      #align 4
                      pre:
                        ! test ebx, ebx                     ' test for zero AFTER its written.
                        ! jz pastit
                    
                      stlp:
                        ! add esi, 1
                        ! movzx ebx, BYTE PTR [esi]
                        ! cmp ebx, 9
                        ! jne nxt1
                        ! mov ebx, 32                       ' replace tabs with spaces
                    
                      nxt1:
                        ! cmp ebx, 32
                        ! jne nxt2
                        ! movzx eax, BYTE PTR [esi+1]       ' test for following tab or space
                        ! cmp eax, 32
                        ! je pre
                        ! cmp eax, 9
                        ! je pre
                    
                      nxt2:
                        ! mov [edi], bl                     ' write acceptable character
                        ! add edi, 1
                        ! test ebx, ebx                     ' test for zero AFTER its written.
                        ! jnz stlp
                    
                      ' =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                    
                      pastit:
                        ! sub edi, 1
                        ! cmp BYTE PTR [edi-1], 32          ' if last character is a space
                        ! jne nxt3
                        ! sub edi, 1
                    
                      nxt3:
                        ! sub edi, pst                      ' length in EDI
                        ! mov pst, edi
                    
                        FUNCTION = left$(dst$,pst)
                    
                    END FUNCTION
                    
                    ' いいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいいい
                    Beware of relying on console output when testing messy strings as you don't always see spaces and other junk, write the actual string to a disk file then look at it in a HEX editor to see exactly when you have got.
                    Last edited by Steve Hutchesson; 4 Jan 2017, 05:56 AM. Reason: Added a comment.
                    hutch at movsd dot com
                    The MASM Forum

                    www.masm32.com

                    Comment


                    • #11
                      Or use STDOUT with this function to dump-to-hex on the fly... https://forum.powerbasic.com/forum/u...266-hex-dumper
                      Last edited by George Bleck; 4 Jan 2017, 07:05 AM.
                      <b>George W. Bleck</b>
                      <img src='http://www.blecktech.com/myemail.gif'>

                      Comment


                      • #12
                        Parsing command line parameters that include spaces (file names) needs some extra consideration. Instead of working around the issues at hand each time, I've written my own parser class:
                        Code:
                        '------------------------------------------------------------------------------
                        '*** Constants ***
                        '------------------------------------------------------------------------------
                        $DELIM_PARAM = "/"
                        $DELIM_VALUE = "="
                        
                        Class cBACmdLine
                        
                        
                           Instance msParamDelimiter As String ' Parameterbegrenzer, blicherweise ein "/"
                           Instance msValueDelimiter As String ' Begrenzer zwischen Parametername und
                                                               ' Parameterwert, blicherweise ein "="
                           Instance mdwParamCount As Dword     ' Anzahl der Parameter
                           Instance masParams() As String      ' Alle Parameternamen
                           Instance mavntValues() As Variant   ' Alle Parameterwerte. Variant weil ein Wert
                                                               ' alles sein kann
                        
                           Instance mdwParamID As Dword        ' Collection key of parameter
                           Instance mdwValueID As Dword        ' Collection key of value
                        
                           Instance mcolValues As IPowerCollection   ' Alle Parameterwerte. Variant weil ein Wert
                                                                     ' alles sein kann
                        '------------------------------------------------------------------------------
                        
                           Class Method Create()
                           ' Do initialization
                        
                              ' Set defaults
                              msParamDelimiter = $DELIM_PARAM
                              msValueDelimiter = $DELIM_VALUE
                        
                              ' Initialize collections
                              Let mcolValues = Class "PowerCollection"
                        
                           End Method
                        '------------------------------------------------------------------------------
                        
                           Class Method Destroy()
                           ' Do cleanup
                        
                              ' Release resources
                              Let mcolValues = Nothing
                        
                           End Method
                        '------------------------------------------------------------------------------
                        
                           Interface IBACmdLine
                        
                              Inherit Dual
                        
                              ' ParamDelimiter
                              Property Get ParamDelimiter() As String
                                 Property = msParamDelimiter
                              End Property
                              Property Set ParamDelimiter(ByVal sValue As String)
                                 msParamDelimiter = sValue
                              End Property
                        '------------------------------------------------------------------------------
                              ' ValueDelimiter
                              Property Get ValueDelimiter() As String
                                 Property = msValueDelimiter
                              End Property
                              Property Set ValueDelimiter(ByVal sValue As String)
                                 msValueDelimiter = sValue
                              End Property
                        '------------------------------------------------------------------------------
                        
                              Method ErrString(ByVal lErr As Long, Optional ByVal vntPrefix As Variant) As String
                              '------------------------------------------------------------------------------
                              'Purpose  : Returns an formatted error string from an (PB) error number
                              '
                              'Prereq.  : -
                              'Parameter: -
                              'Returns  : -
                              'Note     : -
                              '
                              '   Author: Knuth Konrad 12.02.2016
                              '   Source: -
                              '  Changed: -
                              '------------------------------------------------------------------------------
                                 Local sPrefix As String
                        
                                 If Not IsMissing(vntPrefix) Then
                                    sPrefix = Variant$(vntPrefix)
                                 End If
                        
                                 Method = sPrefix & Format$(lErr) & " - " & Error$(lErr)
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method GetParamByIndex(ByVal lIndex As Long) As String
                        
                                 Local vntValue As Variant
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 ' *** Safe guard
                                 If lIndex < 1 Or lIndex > Me.ValuesCount Then
                                    Method = ""
                                    Exit Method
                                 End If
                        
                                 Local wsKey As WString
                        
                                 Try
                                    mcolValues.Entry lIndex, wsKey, vntValue
                        
                                    If ObjResult = %S_False Then
                                       Method = ""
                                       Trace Print " -- GetParamByIndex: ObjResult = %S_FALSE"
                                    Else
                                       Method = wsKey
                                    End If
                                 Catch
                                    Trace Print " -- GetParamByIndex (Error): " & Format$(Err) & ", " & Me.ErrString(Err)
                                    ErrClear
                                 End Try
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method HasParam(ByVal wsKey As WString, Optional ByVal vntKeyAlias As Variant) As Long
                              '------------------------------------------------------------------------------
                              'Purpose  : Check wether a specific command line parameter is present
                              '
                              'Prereq.  : -
                              'Parameter: wsKey       - parameter to search for
                              '           vntKeyAlias - parameter alias
                              'Returns  : -
                              'Note     : -
                              '
                              '   Author: Knuth Konrad
                              '   Source: -
                              '  Changed: 10.11.2016
                              '           - Check for an additional (alias) parameter having the same
                              '           meaning at the same time.
                              '           I.e. /f and /file
                              '------------------------------------------------------------------------------
                                 Local vntValue As Variant
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 ' *** Safe guard
                                 If (Len(wsKey) < 1) And (IsMissing(vntKeyAlias)) Then
                                    Method = %TRUE
                                    Exit Method
                                 End If
                        
                                 Try
                                    vntValue = mcolValues.Item(wsKey)
                        
                                    If ObjResult = %S_False Then
                                       Method = %FALSE
                                       Trace Print " -- HasParam wsKey: ObjResult = %S_FALSE"
                                       Exit Method
                                    Else
                                       Method = %TRUE
                                       Exit Method
                                    End If
                                 Catch
                                    Trace Print " -- HasParam (Error): " & Format$(Err) & ", " & Me.ErrString(Err)
                                    ErrClear
                                 End Try
                        
                                 If Not IsMissing(vntKeyAlias) Then
                                    Local wsKeyAlias As WString
                                    wsKeyAlias = Variant$$(vntKeyAlias)
                        
                                    Try
                                       vntValue = mcolValues.Item(wsKeyAlias)
                        
                                       If ObjResult = %S_False Then
                                          Method = %FALSE
                                          Trace Print " -- HasParam vntKeyAlias: ObjResult = %S_FALSE"
                                          Exit Method
                                       Else
                                          Method = %TRUE
                                          Exit Method
                                       End If
                                    Catch
                                       Trace Print " -- HasParam (Error): " & Format$(Err) & ", " & Me.ErrString(Err)
                                       ErrClear
                                    End Try
                        
                                 End If
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method ValuesAdd(ByVal wsKey As WString, ByVal vntValue As Variant) As String
                        
                                 Local hResult As Long
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 Trace Print "  - wsKey: " & wsKey
                                 Trace Print "  - vntValue: " & Variant$(vntValue)
                        
                                 Try
                                    mcolValues.Add(wsKey, vntValue)
                                    hResult = ObjResult
                                    Method = wsKey
                                 Catch
                                    Trace Print " -- ValuesAdd (Error): " & Format$(Err) & ", " & Me.ErrString(Err)
                                    ErrClear
                                 End Try
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method ValuesClear()
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 Try
                                    mcolValues.Clear()
                                 Catch
                                    Trace Print " -- ValuesClear (Error): " & Format$(Err) & ", " & Me.ErrString(Err)
                                    ErrClear
                                 End Try
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method ValuesCount() As Dword
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 Try
                                    Method = mcolValues.Count
                                 Catch
                                    Trace Print " -- ValuesCount Error: " & Format$(Err) & ", " & Me.ErrString(Err)
                                    ErrClear
                                    Method = 0
                                 End Try
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method ValuesGet(ByVal lIndex As Long) As Variant
                        
                                 Local vntValue As Variant, wsKey As WString
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 Try
                                    If lIndex >= 1 And lIndex <= mcolValues.Count Then
                                       mcolValues.Entry lIndex, wsKey, vntValue
                                       If ObjResult = %S_False Then
                                          Trace Print " -- ValuesGet: ObjResult = %S_FALSE"
                                       Else
                                          Method = vntValue
                                       End If
                                    End If
                                 Catch
                                    Trace Print " -- ValuesGet(lIndex) Error: (" & Format$(lIndex) & ") " & _
                                       Format$(Err) & ", " & Me.ErrString(Err)
                                    ErrClear
                                 End Try
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method GetValueByIndex(ByVal lIndex As Long) As Variant
                              '------------------------------------------------------------------------------
                              'Purpose  : Liefert den Wert eines Parameters
                              '
                              'Prereq.  : -
                              'Parameter: vntIndex -  Nummer des Parameters (1 bis Anzahl Parameter(=ParamCount))
                              'Returns  : Wert des Parameters
                              'Note     : -
                              '
                              '   Author: Knuth Konrad 27.09.2000
                              '   Source: -
                              '  Changed: -
                              '------------------------------------------------------------------------------
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 ' Index im gltigen Bereich?
                                 If lIndex >= 1 And lIndex <= mcolValues.Count Then
                                    Method = me.ValuesGet(lIndex)
                                 End If
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method GetValueByName(ByVal sParam As String, Optional ByVal vntParamAlias As Variant,  _
                                 Optional vntCaseSensitive As Variant) As Variant
                              '------------------------------------------------------------------------------
                              'Purpose  : Liefert den Wert eines Parameters
                              '
                              'Prereq.  : -
                              'Parameter: sParam            -  Name des Parameters dessen Wert gesucht wird
                              '           bolCaseSensitive  -  Gro-/Kleinschreibung beachten
                              'Returns  : -
                              'Note     : -
                              '
                              '   Author: Knuth Konrad 27.09.2000
                              '   Source: -
                              '  Changed: 10.11.2016
                              '           - Check for an additional (alias) parameter having the same
                              '           meaning at the same time.
                              '           I.e. /f and /file
                              '------------------------------------------------------------------------------
                                 Local bolCaseSensitive As Long
                                 Local vntValue As Variant
                                 Local wsParam, wsParamAlias As WString
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 wsParam = sParam
                        
                                 If IsMissing(vntCaseSensitive) Then
                                    bolCaseSensitive = %FALSE
                                 Else
                                    If IsTrue(Variant#(vntCaseSensitive)) Then
                                       bolCaseSensitive = %TRUE
                                    Else
                                       bolCaseSensitive = %FALSE
                                    End If
                                 End If
                        
                                 If IsTrue(bolCaseSensitive) Then
                        
                                    Local i As Dword
                                    Local wsKey As WString
                        
                                    For i = 1 To mcolValues.Count
                                       mcolValues.Entry i, wsKey, vntValue
                                       If LCase$(wsParam) = LCase$(wsKey) Then
                                          Method = vntValue
                                          Exit Method
                                       End If
                                    Next i
                        
                                    If Not IsMissing(vntParamAlias) Then
                                       wsParamAlias = Variant$$(vntParamAlias)
                        
                                       For i = 1 To mcolValues.Count
                                          mcolValues.Entry i, wsKey, vntValue
                                          If LCase$(wsParamAlias) = LCase$(wsKey) Then
                                             Method = vntValue
                                             Exit Method
                                          End If
                                       Next i
                                    End If
                        
                                 Else
                        
                                    Try
                                       Method = mcolValues.Item(wsParam)
                                       Exit Method
                                    Catch
                                       Trace Print " -- GetValueByName() Error: " & Format$(Err) & ", " & Me.ErrString(Err)
                                       ErrClear
                                    End Try
                        
                                    If Not IsMissing(vntParamAlias) Then
                                       wsParamAlias = Variant$$(vntParamAlias)
                        
                                       Try
                                          Method = mcolValues.Item(wsParamAlias)
                                          Exit Method
                                       Catch
                                          Trace Print " -- GetValueByName() Error: " & Format$(Err) & ", " & Me.ErrString(Err)
                                          ErrClear
                                       End Try
                        
                                    End If
                        
                                 End If
                        
                              End Method
                              '------------------------------------------------------------------------------
                        
                              Method Init(ByVal sCmd As String) As Long
                              '------------------------------------------------------------------------------
                              'Purpose  : Diese Prozedur mu els erste Prozedur aufgerufen werden. Sie bernimmt
                              '           die Kommandozeile und wertet sie aus.
                              '
                              'Prereq.  : -
                              'Parameter: sCmd  -  Per COMMAND$ empfangene Kommandozeile
                              'Returns  : True  -  Kommandozeile konnte ausgewertet werden
                              '           False -  Ein Fehler ist aufgetreten
                              'Note     : -
                              '
                              '   Author: Knuth Konrad 27.09.2000
                              '   Source: -
                              '  Changed: -
                              '------------------------------------------------------------------------------
                                 Local i, lParamCount As Long
                                 Local vntValue As Variant
                                 Dim awsParams() As WString
                        
                                 Trace On
                                 Trace Print FuncName$
                        
                                 Trace Print "  - sCmd: " & sCmd
                        
                                 On Error GoTo InitError
                        
                                 ' ** Safe guards
                                 ' Enthielt CLI Werte?
                                 sCmd = LTrim$(sCmd)
                                 lParamCount = ParseCount(sCmd, msParamDelimiter)
                                 If lParamCount < 2 Then
                                    Method = %TRUE
                                    Exit Method
                                 End If
                        
                                 Trace Print "  - ParseCount(sCmd): " & Format$(lParamCount)
                        
                                 ' ParseCount returns 3 for strings like "/123 /abc" where delimiter is '/', as there's an
                                 ' 'empty' entry in front of the first '/'
                                 Dim awsParams(lParamCount - 1) As WString
                                 Parse sCmd, awsParams(), msParamDelimiter
                                 Me.ValuesClear
                        
                                 Trace Print "  - LBound(awsParams): " & Format$(LBound(awsParams))
                                 Trace Print "  - UBound(awsParams): " & Format$(UBound(awsParams))
                        
                                 For i = LBound(awsParams) To UBound(awsParams)
                                    Local wsKey As WString
                        
                                    Trace Print "  - awsParams(i): (" & Format$(i) & "), " & awsParams(i)
                        
                                    ' Nur wenn auch ein Parameter da ist...
                                    If Len(Trim$(awsParams(i))) > 0 Then
                        
                                       wsKey = Trim$(Remove$(Extract$(awsParams(i), msValueDelimiter), msParamDelimiter))
                        
                                       Trace Print "  - wsKey: " & wsKey
                        
                                       ' Parameter in der Art /User=Knuth.
                                       ' "User" ist der Parameter, "Knuth" ist der Wert
                                       If InStr(awsParams(i), msValueDelimiter) > 0 Then
                                          vntValue = Trim$(Remain$(awsParams(i), msValueDelimiter))
                        
                                          Trace Print "  - vntValue: " & Variant$(vntValue)
                        
                                          Me.ValuesAdd(wsKey, vntValue)
                        
                                       Else
                                       'Parameter in der Art /Quit.
                                       '"Quit" ist der Parameter, als Wert wird "True" angenommen
                                          Me.ValuesAdd(wsKey, %TRUE)
                        
                                          Trace Print "  - vntValue: %TRUE"
                        
                                       End If
                        
                                    End If
                        
                                 Next i
                        
                                 Method = %TRUE
                        
                              InitExit:
                                 On Error GoTo 0
                                 Exit Method
                        
                              InitError:
                                 Method = %FALSE
                                 Trace Print " -- Init(sCmd) Error: " & sCmd & Format$(Err) & ", " & Me.ErrString(Err)
                                 ' Collection "aufrumen"
                                 Me.ValuesClear
                                 ErrClear
                                 Resume InitExit
                        
                              End Method
                              '==============================================================================
                        
                           End Interface
                        '------------------------------------------------------------------------------
                        
                        End Class
                        (Sorry for the German/English comments mixture]

                        This class handles

                        - Parameter/value pairs like /file=C:\MyFile.txt
                        - Parameters without values, i.e. /verbose (which could also be written as /verbose=true)
                        - Parameter aliases, i.e. where /f=<value> and /file=<value> both have thesame meaning

                        An example on how to use it can be found at https://github.com/knuth-konrad/pb_deletefilesolderthan

                        Comment


                        • #13
                          If you clean up the whole command line to single spacing it then becomes reliable to parse it into parts
                          If it's command-line arguments, it's specified at runtime, making it something the user enters, automatically making it UNreliable and requiring editing.
                          Michael Mattias
                          Tal Systems Inc.
                          Racine WI USA
                          mmattias@talsystems.com
                          http://www.talsystems.com

                          Comment

                          Working...
                          X