Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

parse command$ arguments 3

Status
Not open for further replies.

csomervi

Programmer
Jun 3, 2003
12
US
In C you can get each command-line argument as an element of the argv array. They system splits each argument (even if it is quote-surrounded with embedded spaces) into separate strings.

VB seems to give you the Command$ string and no tools I can find to easily split it into the separate arguments.

I know about split() but I need to get those quote-surrounded, space-containing arguments as whole strings as well as "regular" arguments.

I can do the parsing character-by-character brute force but does anyone know of a built-in function or service or "trick" which might make it easier to pull off?

Thanks

- Chuck Somerville
 
I have my vb programs use the "/" for each parameter thus the app start command might look like this

Track.exe /S \\TargetServer /O C:\Ouput logs\trace55.log /R 55

then I can SPLIT on /then I'm left with
S \\TargetServer
O C:\Ouput logs\trace55.log
R 55

I know the first character is my parameter type then the rest is the parameter.

Problem solved 8)
 
Yes, I agree - one could do that if it were command-line parameters formatted to my instructions, but (I should have elaborated more, I guess) in this case the operating system is providing the "sometimes quote-surrounded and space-containing" strings.

It is a program intended to process a bunch of files, where the files are (multiply) selected in an Explorer window and dragged onto the program shortcut icon.

In NT4 this is no problem - you get a string of several filenames, where any long or space-containing ones are "mangled" into the 8.3 equivalent with tildes and all.

The problem arises in Win2000 and XP where you get a string containing the space-separated list of filenames, and any space-containing names are quote-surrounded (but non-space-containing names are not quote-surrounded).

::sigh::

Such a Command$ string might look like this...
Code:
C:\foo\f1.dat "C:\foo\read me.dat" C:\foo\xx.x "C:\foo\y y.y"
I figured that since there are places in the OS where such strings are automatically handled (quotes and spaces or not) that there might be some service in the run-time accessible by some function or other. I can't find such a beast in VB.

If they were items in a DATA statement in the older BASICs, a READ would get you the strings correctly (quote-surrounded or not).

I think you could even loop through such a string in C with sscanf and the appropriate format string and grab the filenames.

Just hoping to avoid re-inventing the wheel, but I can always just grind through the string byte-by-byte and parse it myself.

- Chuck Somerville
 
oh sorry, got you....umm off the top of my head.....make sure when you reinvent it, make sure it is still round ok! 8)
 
sorry had a crash while coming up with a solution for you 8(

Basically do this

Take command$ and strip out all "s in it with the REPLACE command

Then use the : to tell you where the file name starts.
ie 1 char to the left of the :
Then get the end of the file name by finding the next : and stepping back 2 characters or in if you don't find the next : then just goto the end of the line.

Only problem with this is that it doesn't suppor UNC so you might have to have 2 routines but the 2nd routine will be easier. This is because you can split the file names up with SPLIT on the \\ of the UNC and just replace the \\ back before useing it.

I'll try to get my code up tonight.

 
Thanks, SemperFi...

No need to provide code - I can (and was afraid I would have to) write my own parser. I was just hoping someone had seen a mechanism usable from within VB to pull out the strings, since most of the rest of the programming environments provide such a tool in their libraries.

Oh well.

Thanks again for your thoughts!

Have a great day :)

- Chuck Somerville
 
Hi guys

Like you, I have struggled with the splitting of command lines. Lots of ugly loops and mid / instr commands with variables keeping track of what I found (spaces and quotes) and where in the string. Yucky spaghetti code (most of the stuff I write is <sigh>) but it did the trick!!

SemperFiDownUnda's thoughts on splitting ...

&quot;Take command$ and strip out all &quot;s in it with the REPLACE command

Then use the : to tell you where the file name starts.&quot;


got me thinking. This approach seemed so much better than any way I had approached this in the past, but it wouldn't work for relative path names &quot;..\another dir\file name.txt&quot; or &quot;filename.txt&quot;, so there would be another step required to handle these ...

So I thought what if you split on the quotes first, then replace the spaces in the bits that weren't quoted in the first place with quotes, requote the quoted bits, concatenate it all back together again, and then resplit on quotes again?

Bit of a mouthful, but it got me the following code which seems to work OK based on my limited testing, and which is a lot more elegant that some of my earlier brute force approaches. Might need some work to handle weirdly formed command lines (never know what might happen to a command line out there in the wild:))

[/code]Private Function SplitString(StringToSplit As String) As Variant
Dim sTmpCmdline() As String, sTemp As String
Dim iCounter As Integer
sTmpCmdline = Split(&quot; &quot; & StringToSplit, Chr(34))
For iCounter = 0 To UBound(sTmpCmdline)
If Left(sTmpCmdline(iCounter), 1) = &quot; &quot; Then
sTemp = sTemp & Replace(sTmpCmdline(iCounter), &quot; &quot;, Chr(34)) & Chr(34)
Else
sTemp = sTemp & sTmpCmdline(iCounter) & Chr(34)
End If
Next iCounter
sTemp = Replace(sTemp, Chr(34) & Chr(34), Chr(34))
SplitString = Split(sTemp, Chr(34))
End Function[/code]

Call it with

Code:
dim sCmdLine() as string
sCmdLine() = SplitString(Command)

Hope this helps.

David
 
Nice job PS42, star for you
just a little refinement and it would be perfect

Code:
[COLOR=#008000]
&quot;C:\this\that.txt &quot; & Chr(34) & &quot;C:\Program Files\other.txt&quot; & Chr(34) & &quot; ..\Myprogram.exe &quot;&quot;d:\Temp Folder\file.log&quot; & Chr(34) & &quot; &quot; & Chr(34) & &quot;Some File.txt&quot; & Chr(34) & &quot; \\MyComputer\d$\somefolder\blah.txt&quot;
[/color]
that line get a few blank strings in the final split but that easy to filter out and your code is small and elegant and works for all cases.
 
Thanks SemperFiDownUnda

You're right - gives blank entries - this version should fix that (at least it did on your posted string).

Code:
Private Function SplitString(StringToSplit As String) As Variant
    Dim sTmpCmdline() As String, sTemp As String
    Dim iCounter As Integer
    sTmpCmdline = Split(&quot; &quot; & StringToSplit, Chr(34))
    For iCounter = 0 To UBound(sTmpCmdline)
        If Trim(sTmpCmdline(iCounter)) = &quot;&quot; Then sTmpCmdline(iCounter) = &quot;&quot;
        If Left(sTmpCmdline(iCounter), 1) = &quot; &quot; Then
            sTemp = sTemp & Replace(sTmpCmdline(iCounter), &quot; &quot;, Chr(34)) & Chr(34)
        Else
            sTemp = sTemp & sTmpCmdline(iCounter) & Chr(34)
        End If
    Next iCounter
    sTemp = Replace(sTemp, Chr(34) & Chr(34), Chr(34))
    SplitString = Split(sTemp, Chr(34))
End Function

David
 
Inevitably there's a Regular Expression solution to this...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top