Wenn mehrere Argumente über die Kommandozeile an Ihre Anwendung übergeben werden sollen (Sie finden die Argumente in Command$ vor), ist es mitunter gar nicht so einfach, die einzelnen Argumente zu extrahieren. Es gibt zwar ein paar Grundregeln und Konventionen dafür, wie eine Kommandozeile aufgebaut sein sollte, doch lassen auch diese Regeln noch genügend Varianten zu, die das Zerlegen erschweren.
So können einerseits die einzelnen Argumente durch Leerzeichen voneinander getrennt sein - die Zerlegung wäre dann mittels der Split-Funktion kein Problem. Soll ein Argument selbst wiederum Leerzeichen enthalten können, etwa in Pfadangaben, wird das Argument in der Regel in doppelte Anführungszeichen eingeschlossen. Die direkte Verwendung der Split-Funktion taugt jedoch nicht mehr zur Zerlegung. Und so genannte "Kommandozeilen-Schalter" (-... oder /...) können sogar ohne Separierung durch Leerzeichen verwendet werden.
Das Modul modArguments.bas zerlegt eine Kommandozeile und bietet einen komfortablen Zugriff auf die einzelnen Argumente und auf die einzelnen möglicherweise in der Kommandozeile enthaltenen Schalter und deren Wertzuweisungen. Es initialisiert sich automatisch selbst mit der in der VB-Funktion Command$ übergebenen Kommandozeile, sobald Sie erstmals ein Argument oder einen Schalter auslesen, und zerlegt sie.
Sie können auch einen Kommandozeilen-String anderer Herkunft der Eigenschaft CommandLine zuweisen - dieser ist dann anstelle des VB-Command$-Inhalts Quelle der Argumente und Schalter. Weisen Sie CommandLine einen leeren String zu, wird wieder Command$ zur Quelle.
Die Eigenschaft CommandArgumentsCount liefert Ihnen die Anzahl der extrahierten Argumente.
Ein einzelnes Argument gibt Ihnen die Eigenschaft CommandArgument unter Angabe des Index zurück. Setzen Sie den optionalen Parameter ReducedQuotes auf True werden Anführungszeichen, die das Argument am String-Anfang und -Ende einschließen, entfernt. Soll ein in Anführungszeichen eingeschlossenes Argument selbst Anführungszeichen enthalten, sind diese jeweils zu verdoppeln - diese Verdoppelung wird bei ReducedQuotes aufgehoben. Die intern verwendete Funktion ReduceQuotes kann auch eigenständig aufgerufen werden.
Beispiele:
Debug.Print CommandArgument(2)
ergäbe
"Das ist ein ""Test"" für alle Fälle"
Und
Debug.Print CommandArgument(2, True)
ergäbe
Das ist ein "Test" für alle Fälle
Die Eigenschaft CommandSwitch liefert zu einem als Parameter übergebenen Schalter-Bezeichner den Wert des Schalters als String, falls der Schalter in der Kommandozeile enthalten ist. ist er nicht enthalten, wird ein leerer Variant-Wert (Empty, kann mit IsEmpty(...) getestet werden) zurückgegeben. Die Wirkung des optionalen Parameters ReducedQuotes ist die gleiche wie bei CommandArgument.
Beispiele:
Kommandozeile: /L/Dc:\ -T"Test"
Schalter:
Debug.Print TypeName(CommandSwitch("L"))
ergibt:
String
und
Debug.Print TypeName(CommandSwitch("X"))
ergibt:
Emtpy
und
Debug.Print CommandSwitch("d")
ergibt:
c:\
und
Debug.Print CommandSwitch("T", True)
ergibt:
Test
Der komplette Code des Moduls:
Private mArguments As Collection
Private pCommandLine As String
Public Property Get CommandLine() As String
CommandLine = pCommandLine
End Property
Public Property Let CommandLine(New_CommandLine As String)
Dim nCommandLine As String
nCommandLine = Trim$(New_CommandLine)
If pCommandLine <> nCommandLine Then
pCommandLine = nCommandLine
zGetArguments
End If
End Property
Public Property Get CommandArgumentsCount() As Long
zInitArguments
CommandArgumentsCount = mArguments.Count
End Property
Public Property Get CommandArgument(ByVal Index As Long, _
Optional ByVal ReducedQuotes As Boolean) As String
zInitArguments
On Error Resume Next
If ReducedQuotes Then
CommandArgument = ReduceQuotes(mArguments(Index))
Else
CommandArgument = mArguments(Index)
End If
End Property
Public Property Get CommandSwitch(Switch As String, _
Optional ByVal ReducedQuotes As Boolean) As Variant
Dim i As Integer
Dim nArgument As String
Dim nCommandSwitch As String
zInitArguments
For i = 1 To mArguments.Count
nArgument = mArguments(i)
Select Case Left$(nArgument, 1)
Case "-", "/"
If Mid$(UCase$(nArgument), 2, Len(Switch)) = _
UCase$(Switch) Then
If ReducedQuotes Then
nCommandSwitch = ReduceQuotes(Mid$(nArgument, _
Len(Switch) + 2))
Else
nCommandSwitch = Mid$(nArgument, Len(Switch) + 2)
End If
If Left$(nCommandSwitch, 1) = "=" Then
CommandSwitch = Trim$(Mid$(nCommandSwitch, 2))
Else
CommandSwitch = Trim$(nCommandSwitch)
End If
Exit Property
End If
End Select
Next 'i
End Property
Public Function ReduceQuotes(Arg As String) As String
Dim nArg As String
nArg = Arg
If Left$(nArg, 1) = Chr$(34) Then
If Right$(nArg, 1) = Chr$(34) Then
nArg = Replace(Arg, Chr$(34) & Chr$(34), Chr$(34))
ReduceQuotes = Mid$(nArg, 2, Len(nArg) - 2)
End If
End If
End Function
Private Sub zGetArguments()
Dim nCommandLine As String
Dim nParts() As String
Dim i As Integer
If Len(pCommandLine) = 0 Then
pCommandLine = Trim$(VBA.Command$)
End If
If Len(pCommandLine) = 0 Then
Set mArguments = New Collection
Exit Sub
End If
nCommandLine = " " & Replace(pCommandLine, _
Chr$(34) & Chr$(34), Chr$(1)) & " "
nParts = Split(nCommandLine, Chr$(34))
For i = 0 To UBound(nParts)
If i And 1 Then
nParts(i) = Replace(nParts(i), " ", Chr$(2))
nParts(i) = Replace(nParts(i), "/", Chr$(3))
nParts(i) = Replace(nParts(i), "-", Chr$(4))
nParts(i) = Chr$(34) & nParts(i) & Chr$(34)
End If
Next 'i
nCommandLine = Trim$(Join(nParts, ""))
nCommandLine = Replace(nCommandLine, "/", " /")
nCommandLine = Replace(nCommandLine, "-", " -")
nParts = Split(nCommandLine, " ")
Set mArguments = New Collection
For i = 0 To UBound(nParts)
If Len(nParts(i)) Then
nParts(i) = Replace(nParts(i), Chr$(1), _
Chr$(34) & Chr$(34))
nParts(i) = Replace(nParts(i), Chr$(2), " ")
nParts(i) = Replace(nParts(i), Chr$(3), "/")
nParts(i) = Replace(nParts(i), Chr$(4), "-")
mArguments.Add nParts(i), nParts(i)
End If
Next 'i
End Sub
Private Sub zInitArguments()
If mArguments Is Nothing Then
zGetArguments
End If
End Sub

|