cCmdLineArgsClase para desglosar (de forma práctica e inteligente) los argumentos pasados a nuestra aplicación de VB
Publicado el 07/Feb/2005
|
Introducción (te lo puedes saltar si no quieres leer batallitas)
En Septiembre del 97 (como pasa el tiempo), publiqué una utilidad para desglosar los argumentos indicados en nuestra aplicación. Y la cosa es que el código estaba bien y hacía su trabajo, es decir tomar la línea de comandos pasada a nuestra aplicación y crear un array con cada uno de los argumentos, algo parecido a lo que la función main de C hace, es más, en ese código llamé a las variables de la misma forma que en C: argv para el array y argc para el número de argumentos, (en esta nueva versión también he dejado esos nombres).
Realmente el código hacía lo mismo que en C (o ahora en C# y VB .NET), es decir, cada una de las "palabras" indicadas en la línea de comandos la incluía en un elemento del array. He dicho "palabras" porque realmente cada argumento se "supone" que debe estar separado del anterior con un espacio, aunque lo habitual también es que esos argumentos se indiquen usando los caracteres de la barra invertida (/) o el signo menos (-), y ese código comprobaba estos dos casos y si se los encontraba los guardaba en un elemento del array creado. También se tenían en cuenta lo que estuviera entre comillas dobles, que es lo que se suele hacer cuando queremos que en uno de los argumentos se puedan indicar espacios.
¿Qué hay de nuevo viejo?
Pero este nuevo código que te voy a mostrar no hace exactamente lo mismo que el código que publiqué hace casi 8 años, ya que no tendría demasiado sentido... y el cambio no es por el hecho de que ahora está incluido en una clase... sino porque ahora, (como dice el subtítulo), lo hace de forma más inteligente y, por lo tanto, más práctica.
Me explico.
Si antes teníamos esta línea de comandos (donde prueba.exe es el nombre del programa):prueba.exe /f prueba.txt /c
El array contendría 3 elementos: /f, prueba.txt y /c
Si lo miramos bien, realmente /f prueba.txt debería ser un solo argumento y /c otro, por tanto nos podría ser de más utilidad tener la posibilidad de que en esos casos, se pudieran "agrupar" argumentos (teóricamente) relacionados.
Y esa es una de las cosas que el nuevo código que te muestro "sabe" hacer. Aunque también se puede seguir usando de la forma "clásica", es decir: cada argumento es un elemento del array.
Pero esta (que realmente es útil) no es la única novedad, ya que la clase cCmdLineArgs también hace otras cosas, como por ejemplo poder comprobar si un determinado "argumento" se ha indicado o saber el índice en el que está el argumento que nos interesa para posteriormente poder acceder a él usando un valor numérico, el cual podemos usar para eliminarlo o tomar el valor "asociado" a ese argumento.
También podemos indicarle que no permita argumentos repetidos o que distinga los nombres de los argumentos si se escriben en minúsculas o mayúsculas, e incluso poder decirle cuales son los argumentos permitidos, de forma que sólo guarde los indicados y el resto no los tenga en cuenta.Como ves tiene "cosillas" que realmente le da un valor añadido y sin tener que pagar impuestos... chiste malo, lo se... je, je, je.
Esta clase puede procesar la línea de comandos pasada a la aplicación (Command$) o bien una cadena creada por nosotros, aunque lo normal es que procese los argumentos indicados a la aplicación.
Los miembros de la clase
A continuación te hago una lista con los métodos y propiedades que tiene esta clase junto con una pequeña descripción. Más adelante veremos el código para poder usarlos.
Nombre Descripción Argc El número de argumentos.
Si se "asocian" argumentos, indica el total una vez asociados.Argv Permite acceder a cada argumento mediante un índice numérico.
Aunque se utiliza como un array, solo es de lectura.GetArgv Devuelve el array interno.
Realmente devuelve una copia, por tanto cualquier cambio al array devuelto no afecta al de la clase.HayAlgunSeparador Indica si hay argumentos que incluya un separador (/ o -) Clear Elimina todo lo que hubiera y reinicia los valores predeterminados.
Para cuando queremos volver a procesar otra línea de comandos.CmdLine2Arg Esta es la función principal que se encarga de "desglosar" la línea de comandos.
Permite indicar una cadena creada por nosotros o, lo habitual, procesar el contenido de Command$, que es la que contiene los argumentos indicados al llamar a la aplicación.
En los argumentos de la línea de comandos se puede indicar como separador el signo / o el de la resta (-), pero cuando se procesa la línea de comandos, se guarda con el signo -, por tanto en posteriores "búsquedas" debemos indicar siempre el signo - (aunque originalmente hayamos usado /), esto es así, para evitar tener que hacer dobles comprobaciones por si el usuario ha usado uno u otro.Desglosar Como la anterior, pero aquí se debe indicar la cadena a desglosar. DiferenciarCase Para diferenciar mayúsculas de minúsculas.
El valor que puede tener es el usado por el propio VB para hacer comparaciones binarias (distingue mayúsculas de minúsculas) o comparaciones de texto (no distingue el "case").
Los valores que puede tener son los de la enumeración eTipoCompare.
El valor predeterminado es TextCompare (no diferenciar).EntreSeparadores Para indicar si debemos asociar los argumentos dependiendo de que se usen los separadores / o -.
Los valores que puede tener son los de la enumeración: eOpSeparador.
El valor predeterminado es Ninguno.GetArgument Devuelve el argumento asociado con el argumento con separador indicado.
Por ejemplo, si tenemos -f prueba.txt e indicamos -f, devolverá prueba.txt
También se puede indicar sin separador, pero realmente no tiene ninguna utilidad, ya que cuando un argumento no tiene separador, no hay "otro" argumento asociado.GetArgumentByIndex Devuelve el valor asociado al argumento del índice numérico indicado.
No confundir este método con la posibilidad de acceder al argumento que estén en la posición indicada por el índice, para eso está el método Argv.GetArgumentNumber Nos indica el índice dentro del array del argumento indicado. Permitidos Una cadena con los argumentos permitidos.
Cada argumento se indicará sin el signo separador y se separarán usando punto y coma y sin ningún espacio extra.
Por ejemplo: "c;f;x;help;h;?"PermitirDuplicados Si se permiten argumentos con el mismo nombre.
Si no diferenciamos el "case" y PermitirDuplicados es False, no se aceptarán dos argumentos que se diferencien solo por mayúsculas y minúsculas.
El valor es True (permitir duplicados)RemoveArgument Quita el argumento indicado.
Opcionalmente se le puede decir que también quite el argumento asociado, si es que el que hemos indicado tiene separador.
Por ejemplo, si tenemos -f prueba.txt
Usándolo con RemoveArgument "-f", quitaría solo el -f, dejando prueba.txt
Usándolo con RemoveArgument "-f", True, quitará los dos.RemoveArgumentByIndex Como el anterior, pero en lugar de indicar el "nombre" del argumento, usamos un índice numérico.
Este índice deberíamos obtenerlo con GetArgumentByIndex.eTipoCompare Enumeración para el tipo de comparación.
BinaryCompare, hace distinción entre mayúsculas y minúsculas.
TextCompare, no diferencia mayúsculas de minúsculas.
Estos son los mismos valores usados por VB, particularmente con la función StrComp.eOpSeparador Enumeración para usar con la propiedad EntreSeparadores.
Ninguno, se toma cada argumento de forma independiente.
SeparadorArgumento, Cualquier separador o argumento al principio.
SoloSeparadores, Solo agrupar por separadores explícitos.Tabla 1. Los miembros de la clase
Antes del código, ejemplos de cómo usarla
Para que lo veas todo más claro y comprendas mejor cómo funciona todo esto que te digo, he creado una pequeña aplicación en la que puedes probar algunas de las características de la clase.
En las siguientes capturas de la aplicación de prueba en plena ejecución, puedes ver cómo hace el trabajo, según las opciones indicadas:En la figura 1 vemos un desglose "normal", es decir, cada argumento como un elemento del array.
Figura 1. Esta sería la forma "normal" de usarlo
En la figura 2 le decimos que NO permita duplicidad en los argumentos y como no hemos indicado que diferencie entre mayúsculas y minúsculas (la opción está oculta por el tip), ha quitado el argumento -F ya que existe otro anterior.
Figura 2.
En la figura 3 le decimos que "asocie" los argumentos, de forma que si encuentra uno que tenga cualquiera de los separadores (/ o -) y lo que sigue no tiene separador, pues lo une como un solo argumento.
Figura 3.
En la figura 4 es como la anterior, pero no permite duplicados.
Figura 4.
En la figura 5 le hemos indicado que solamente acepte los argumentos que contengan separadores.
Figura 5.
En la figura 6, le hemos indicado que solamente procese los argumentos permitidos, además de que los "asocie" y distinga mayúsculas de minúsculas.
Figura 6.
En todas estas figuras tienes las distintas combinaciones que podemos hacer mediante las propiedades de la clase. Pero también tenemos unos métodos que nos pueden ser de bastante utilidad para procesar de forma más "fácil" los argumentos indicados.
En la mayoría de aplicaciones que permiten argumentos en la línea de comandos, por ejemplo un compilador, suele permitirse que se indiquen de varias formas, lo habitual es que el mismo "comando" tenga una versión larga y otra corta, (con lo que se consigue hacer cierto eso que a muchos nos gustaría que fuese una "VERDAD INDISCUTIBLE" de que el tamaño NO importa, je, je), por ejemplo -help y -h.
Esas aplicaciones incluso permiten usar indistintamente los separadores - o /, por ejemplo /help o -help.
Por eso, esta clase, una vez procesados los argumentos, siempre usa - para indicar un argumento con separador, porque debemos tener en cuenta que también pueden existir argumentos que no tengan separadores, (aunque no es lo habitual), por ejemplo podríamos aceptar help sin necesidad de usar un separador.
A lo que iba, si queremos comprobar si el usuario ha indicado, por ejemplo, -buscar o -b, suponiendo que esas dos opciones realicen la misma operación y que se usen con el texto a buscar, por ejemplo:
-b "una frase con espacios" o -buscar elGuille, podríamos comprobarlo de esta forma:n = cmd.GeArgumentNumber("-b") If n = 0 Then n = cmd.GeArgumentNumber("-buscar") End If If n > 0 Then ' se ha indicado, ahora obtenemos lo que se ha indicado en ese argumento s = cmd.GetArgumentByIndex(n) End IfSi después de tener lo que ha indicado el usuario queremos eliminar ese argumento (con el correspondiente valor asociado), podemos hacerlo de esta forma:
cmd.RemoveArgumentByIndex n
¿Que utilidad tiene quitar un argumento?
Imagínate que en tu programa se esperan ciertos valores de forma secuencial, por ejemplo, un path seguido de una especificación, pero también quieres que se puedan usar otras opciones, como incluir subdirectorios y que se pueda indicar un fichero en el que guardar los resultados, etc. Por ejemplo:
miprograma.exe C:\Pruebas *.txt -subdir -resultado fichero.logPero lo que no quieres es "obligar" al usuario a que lo indique "exactamente" así, (entre otras cosas, porque suele pasar de hacer las cosas bien o como se deben hacer... si lo sabré yo); en esos casos podrías ser permisivo y dejar que, salvo los dos parámetros obligatorios, los argumentos opcionales los ponga como le de la gana, por ejemplo:
miprograma.exe -subdir C:\Pruebas *.txt -resultado fichero.log
E incluso rizando el rizo:
miprograma.exe C:\Pruebas -resultado fichero.log *.txt -subdirEn estos casos, comprobaríamos si existen los argumentos opcionales, guardamos los valores correspondientes, los quitamos y después tranquilamente podemos tomar los valores en el orden que deben ser indicados. De esta forma podríamos "aliviar" al usuario para que no tenga que indicar un argumento separador para cada uno de los parámetros (aunque es lo mejor y lo que queda más claro), por ejemplo:
miprograma.exe -dir C:\Pruebas -resultado fichero.log -ext *.txt -subdir
Para tu información, lo he hecho porque en un programilla que he "remodelado" hace poco he añadido cantidad de opciones y una de las formas de usarlo es como acabo de explicarte, además de la forma "larga" como en el último ejemplo.
Ahora, ya ¡por fin!
El código de la clase
Aquí tienes el código de la clase, el de la aplicación que utiliza este código, te lo puedes bajar del link que hay más abajo.
Realmente tienes que irte al final de la página para ver el código o bien pulsar el link.
Y esto ha sido todo, como siempre espero que te sea de utilidad y que si te sobra algo de calderilla (en tu tarjeta de crédito), te acuerdes de aportar algo mediante Paypal... je, je, por pedir que no quede.
Gracias.
Nos vemos
Guillermo
Nerja, 7 de Febrero de 2005El link con el código fuente, tanto de la clase como del ejemplo: LineaComandos2.zip 26.9 KB
El código está más o menos bien comentado, así que espero que tengas claro lo que hace cada uno de los "miembros" de la clase.
'------------------------------------------------------------------------------ ' cCmdLineArgs (01/Feb/05) ' Clase para manejar las opciones de la línea de comandos (argumentos) ' ' Basado en: (Cmd2argv.bas) ' Módulo para desglosar los parámetros de la línea de comandos ' Primera versión: 30/Sep/97 ' ' Esta clase tendrá estas características: ' -De forma predeterminada cada parámetro será lo que esté separado por: ' el guión (-) ' la barra (/) ' espacio ' tabulador ' entre comillas dobles ' -Podemos indicar los nombres de los parámetros a tener en cuenta ' En ese caso el resto de parámetros se ignorará ' -Podemos indicar que los datos asociados a un parámetro ' se comprueben hasta encontrar -, / o el final de línea ' ' -Permitir (o no) parámetros duplicados ' ' ©Guillermo 'guille' Som, 1997, 2005 '------------------------------------------------------------------------------ Option Explicit ' Los valores deben corrsponderse con vbBinaryCompare y vbTextCompare Public Enum eTipoCompare BinaryCompare ' Se diferencia entre mayúsculas y minúsculas TextCompare ' NO se diferencia entre mayúsculas y minúsculas End Enum ' Para agrupar por separadores Public Enum eOpSeparador Ninguno ' No se tiene en cuenta SeparadorArgumento ' Cualquier separador o argumento al principio SoloSeparadores ' Solo agrupar por separadores explíctos End Enum Public HayAlgunSeparador As Boolean ' si alguno tiene separador Private m_EntreSeparadores As eOpSeparador ' para emparejar los parámetros Private m_PermitirDuplicados As Boolean ' si se permiten duplicidades Private m_DiferenciarCase As eTipoCompare ' comparación binaria o de texto Private nPerm As Long ' número de parámetros permitidos Private mPermitidos As Boolean ' si se comprueban los permitidos Private aPermitidos() As String ' para los parámetros permitidos Private m_Argv() As String ' Contenido de cada argumento Const SEP_PERM As String = ";" ' el separador de parámetros Const sepArg As String = "-/" Public Argc As Long ' número de argumentos (de 1 a Argc) '---------------------------------------------------------------------- ' GetArgs ' ' Recupera una copia de los argumentos '---------------------------------------------------------------------- Public Function GetArgs() As String() GetArgs = m_Argv End Function '---------------------------------------------------------------------- ' Argv ' ' Para acceder a cada elemento del array de argumentos '---------------------------------------------------------------------- Public Function Argv(ByVal index As Long) As String If index < 1 Or index > Argc Then Argv = "" Else Argv = m_Argv(index) End If End Function '---------------------------------------------------------------------- ' Permitidos ' ' Indicar los parámetros permitidos ' Estarán en una cadena separados por ; ' (no indicar el separador, se supone - o /) ' Por ejemplo: ' "x;imprimir;f" '---------------------------------------------------------------------- Public Property Get Permitidos() As String ' devolver los parámetros permitidos If nPerm > 0 Then Permitidos = Join(aPermitidos, SEP_PERM) Else Permitidos = "" End If End Property Public Property Let Permitidos(ByVal value As String) If Len(Trim$(value)) > 0 Then ' desglosar en un array ' los parámetros estarán separados por ; If Right$(Trim$(value), 1) = SEP_PERM Then value = Left$(value, Len(value) - 1) End If value = Trim$(value) aPermitidos = Split(value, SEP_PERM) nPerm = UBound(aPermitidos) mPermitidos = True Else nPerm = 0 ReDim aPermitidos(0) mPermitidos = False End If End Property '---------------------------------------------------------------------- ' EntreSeparadores ' ' Si los parámetros se asignarán entre separadores, ' de esta forma podemos indicar espacios entre parámetros ' por ejemplo: ' -file C:\Prueba con espacios\t.txt -convertir si -imprimir no ' de esta forma se crearán estos elementos en argv: ' -file C:\Prueba con espacios\t.txt ' -convertir si ' -imprimir no ' ' Si EntreSeparadores es eOpSeparador.Ninguno (False) ' y se indican argumentos a tener en cuenta ' sólo se procesarán los que coincidan, ' por ejemplo: ' Si tenemos en cuenta: "convertir;imprimir" ' se devolverá (sin - ni /): ' convertir ' imprimir ' El resto se ignora. ' ' Si EntreSeparadores es True y se indican argumentos a tener en cuenta ' teniendo estos separadores: "convertir;imprimir" ' Se devolverán estos parámetros: ' convertir si ' imprimir no '---------------------------------------------------------------------- Public Property Get EntreSeparadores() As eOpSeparador EntreSeparadores = m_EntreSeparadores End Property Public Property Let EntreSeparadores(ByVal value As eOpSeparador) If value = SeparadorArgumento Or value = SoloSeparadores Then m_EntreSeparadores = value Else m_EntreSeparadores = eOpSeparador.Ninguno End If End Property '---------------------------------------------------------------------- ' DiferenciarCase ' ' Diferenciar los parámetros entre mayúsculas y minúsculas ' Esto solo tiene utilidad si se indican parámetros permitidos ' o en el caso que se quiera evitr duplicidades de parámetros '---------------------------------------------------------------------- Public Property Get DiferenciarCase() As eTipoCompare DiferenciarCase = m_DiferenciarCase End Property Public Property Let DiferenciarCase(ByVal value As eTipoCompare) If value = BinaryCompare Or value = TextCompare Then m_DiferenciarCase = value Else m_DiferenciarCase = TextCompare End If End Property '---------------------------------------------------------------------- ' PermitirDuplicados ' ' Si se permiten parámetros duplicados ' (el mismo parámetro más de una vez) '---------------------------------------------------------------------- Public Property Get PermitirDuplicados() As Boolean PermitirDuplicados = m_PermitirDuplicados End Property Public Property Let PermitirDuplicados(ByVal value As Boolean) m_PermitirDuplicados = value End Property '---------------------------------------------------------------------- ' Clear ' ' Asigna los valores predeterminados '---------------------------------------------------------------------- Public Sub Clear() ' valores predeterminados m_DiferenciarCase = TextCompare nPerm = 0 ReDim aPermitidos(nPerm) mPermitidos = False Argc = 0 ReDim m_Argv(Argc) m_EntreSeparadores = eOpSeparador.Ninguno '= SeparadorArgumento m_PermitirDuplicados = True End Sub '---------------------------------------------------------------------- ' Desglosar ' ' Este método llama a Command2Arg pero no devuelve nada ' ni permite parámetros opcionales '---------------------------------------------------------------------- Public Sub Desglosar(ByVal sCommand As String) 'Call Command2Arg(sCommand) Call CmdLine2Arg(sCommand) End Sub Public Function CmdLine2Arg(Optional ByVal sCommand As String = "") As Long ' Devuelve lo que hay en command$ o en la variable de entrada ' en un array global Argv() y devuelve el número de parámetros ' o cero si no hay ninguno '------------------------------------------------------------- Dim c As String Dim s As String Dim i As Long Dim j As Long Dim k As Long Dim b As Boolean Dim separadores As String separadores = "/- " & Chr$(34) & Chr$(9) ReDim m_Argv(0) Argc = 0 ' Si no se especifica el parámetro se toma la línea de comandos If Len(sCommand) = 0 Then sCommand = Command$ End If ' Si no tiene nada la variable devolver cero If Len(sCommand) = 0 Then CmdLine2Arg = 0 Argc = 0 Exit Function End If i = 0 Do While i < Len(sCommand) i = i + 1 c = Mid$(sCommand, i, 1) ' Si está entre comillas dobles ' asignar el contenido al argumento If c = Chr$(34) Then j = InStr(i + 1, sCommand, Chr$(34)) If j = 0 Then j = Len(sCommand) s = Mid$(sCommand, i + 1, j - i - 1) i = j + 1 Argc = Argc + 1 ReDim Preserve m_Argv(Argc) m_Argv(Argc) = Trim$(s) ElseIf c = "/" Or c = "-" Or c <> " " Then s = c Do While i < Len(sCommand) i = i + 1 c = Mid$(sCommand, i, 1) If InStr(separadores, c) Then i = i - 1 Exit Do End If s = s & c Loop Argc = Argc + 1 ReDim Preserve m_Argv(Argc) m_Argv(Argc) = Trim$(s) End If Loop If m_EntreSeparadores <> eOpSeparador.Ninguno Then testSep End If If m_PermitirDuplicados = False Then testDup End If If mPermitidos Then testPerm End If ' Devolver las opciones que tengan separador usando sólo - (03/Feb/05) ' y que como mínimo tenga un espacio después del parámetro ' para que se pueda buscar usando If Left$(Argv(i),3) = "-x " Then ' ' También se comprueba si hay algún separador ' Se cambiarán los caracteres especiales ' c34 comillas dobles HayAlgunSeparador = False For i = 1 To Argc If InStr(sepArg, Left$(m_Argv(i), 1)) > 0 Then HayAlgunSeparador = True m_Argv(i) = "-" & Mid$(m_Argv(i), 2) & " " Else m_Argv(i) = m_Argv(i) & " " End If m_Argv(i) = Replace(m_Argv(i), "c34", Chr$(34)) Next CmdLine2Arg = Argc End Function Private Sub testSep() ' Este método comprueba si se desglosa entre separadores, ' (solo se tendrán en cuenta los que empiecen por - o /) ' si tenemos: -x -f prueba ' devolvería: ' -x ' -f prueba Dim t_argv() As String Dim i As Long Dim n As Long Dim b As Boolean If m_EntreSeparadores = eOpSeparador.Ninguno Then Exit Sub End If t_argv = m_Argv n = 0 For i = 1 To Argc If InStr(sepArg, Left$(t_argv(i), 1)) > 0 Then n = n + 1 m_Argv(n) = LTrim$(t_argv(i)) b = True Else If m_EntreSeparadores = SoloSeparadores Then ' Si n = 0 no hay que tenerlo en cuenta, ' ya que es un parámetro no precedido por un separador, ' en otro caso es un valor del separador anterior. If n > 0 Then m_Argv(n) = m_Argv(n) & " " & LTrim$(t_argv(i)) End If Else ' Se puede indicar también entre separadores y ' los primeros que no estén entre separadores, ' en ese caso hacerlo así: If n = 0 Or b = False Then n = n + 1 m_Argv(n) = LTrim$(t_argv(i)) Else m_Argv(n) = m_Argv(n) & " " & LTrim$(t_argv(i)) End If End If b = False End If Next ReDim Preserve m_Argv(n) Argc = n End Sub Private Sub testDup() ' Comprobar si hay parámetros duplicados ' (sólo se tendrá en cuenta la primera palabra de cada argumento) ' Aquí cada parámetro puede estar precedido por un separador, ' pero no tiene porqué ser así. ' Si tenemos -x fichero -p -x Documento.txt fichero ' suponiendo que EntreSeparadores = False, tendríamos estos argumentos: ' -x ' fichero ' -p ' -x ' Documento.txt ' fichero ' por tanto -x y fichero estarían duplicados Dim t_argv() As String Dim i As Long Dim j As Long Dim k As Long Dim n As Long Dim s As String Dim s1 As String Dim b As Boolean ' If m_PermitirDuplicados = True Then Exit Sub End If t_argv = m_Argv n = 0 For i = 1 To Argc ' solo se comprueba la primera palabra ' (o la línea completa si solo hay una palabra) k = InStr(t_argv(i), " ") If k = 0 Then k = Len(t_argv(i)) + 1 End If If n = 0 Then n = n + 1 m_Argv(n) = t_argv(i) Else s = Left$(t_argv(i), k - 1) b = False For j = 1 To n k = InStr(m_Argv(j), " ") If k > 0 Then s1 = Left$(m_Argv(j), k - 1) Else s1 = m_Argv(j) End If If StrComp(s, s1, m_DiferenciarCase) = 0 Then b = True Exit For End If Next If b = False Then n = n + 1 m_Argv(n) = t_argv(i) End If End If Next ReDim Preserve m_Argv(n) Argc = n End Sub Private Sub testPerm() ' Comprobar los permitidos ' Se comprueban los parámetros permitidos ' de forma que sólo se acepten los indicados en Permitidos Dim t_argv() As String Dim i As Long Dim j As Long Dim k As Long Dim n As Long Dim s As String Dim b As Boolean ' If mPermitidos = False Then Exit Sub End If t_argv = m_Argv n = 0 For i = 1 To Argc k = InStr(t_argv(i), " ") If k > 0 Then s = Left$(t_argv(i), k - 1) Else s = t_argv(i) End If If InStr(sepArg, Left$(s, 1)) > 0 Then s = Mid$(s, 2) End If b = False For j = 0 To nPerm If StrComp(s, aPermitidos(j), m_DiferenciarCase) = 0 Then b = True Exit For End If Next If b Then n = n + 1 m_Argv(n) = t_argv(i) End If Next ReDim Preserve m_Argv(n) Argc = n End Sub Private Sub Class_Initialize() Clear End Sub '---------------------------------------------------------------------- ' Funciones de apoyo después de desglosar la línea de comandos '---------------------------------------------------------------------- Public Function GetArgument(ByVal sArg As String) As String ' Busca el argumento indicado y devuelve la cadena asociada (03/Feb/05) ' se debe indicar el signo - si es un argumento que se usa de separador ' ya que pueden existir argumentos con nombre, pero sin separador Dim i As Long Dim k As Long Dim s As String s = "" For i = 1 To Me.Argc k = InStr(m_Argv(i), " ") If k > 0 Then s = Left$(m_Argv(i), k - 1) If StrComp(s, sArg, vbTextCompare) = 0 Then s = Mid$(m_Argv(i), k + 1) Exit For End If End If Next GetArgument = s End Function Public Function GetArgumentNumber(ByVal sArg As String) As Long ' Busca el argumento indicado y devuelve la posición (03/Feb/05) ' Devuelve cero si no se ha encontrado ' Esta función se puede usar con GetArgumentByIndex(index) Dim i As Long Dim k As Long Dim s As String Dim n As Long n = 0 For i = 1 To Argc k = InStr(m_Argv(i), " ") If k > 0 Then s = Left$(m_Argv(i), k - 1) If StrComp(s, sArg, vbTextCompare) = 0 Then n = i Exit For End If End If Next GetArgumentNumber = n End Function Public Function GetArgumentByIndex(ByVal index As Long) As String ' Devuelve lo que contiene el índice indicado (03/Feb/05) ' hay que buscarlo con GetArgumentNumber Dim k As Long Dim s As String s = "" If Not (index < 1 Or index > Argc) Then k = InStr(m_Argv(index), " ") If k > 0 Then s = Trim$(Mid$(m_Argv(index), k + 1)) End If End If GetArgumentByIndex = s End Function Public Sub RemoveArgumentByIndex(ByVal index As Long, Optional ByVal quitarExtra As Boolean = False) ' Quita el argumento del índice indicado (05/Feb/05) Dim k As Long Dim s As String s = "" If Not (index < 1 Or index > Argc) Then k = InStr(m_Argv(index), " ") If k > 0 Then s = Trim$(Left$(m_Argv(index), k - 1)) End If End If RemoveArgument s, quitarExtra End Sub Public Sub RemoveArgument(ByVal sArg As String, Optional ByVal quitarExtra As Boolean = False) ' Quitar el argumento indicado del array (04/Feb/05) ' Hay que indicarlo con el signo - delante (05/Feb/05) ' Si quitarExtra = True, se quitará lo que haya a continuación ' esto es válido para argumentos que tienen datos Dim i As Long Dim k As Long Dim s As String Dim n As Long Dim t_argv() As String t_argv = m_Argv HayAlgunSeparador = False n = 0 For i = 1 To Argc k = InStr(t_argv(i), " ") If k > 0 Then s = Left$(t_argv(i), k - 1) If StrComp(s, sArg, vbTextCompare) <> 0 Then If Left$(s, 1) = "-" Then HayAlgunSeparador = True End If n = n + 1 m_Argv(n) = t_argv(i) ElseIf quitarExtra = False Then ' comprobar si le sigue algo ' (por si se ha indicado otro parámetro sin separador) s = Trim$(Mid$(t_argv(i), k + 1)) If Len(s) Then n = n + 1 m_Argv(n) = s End If End If Else n = n + 1 m_Argv(n) = t_argv(i) End If Next Argc = n ReDim Preserve m_Argv(n) End Sub