elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado:


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Crear Menu Contextual Windows
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 2 [3] 4 Ir Abajo Respuesta Imprimir
Autor Tema: Crear Menu Contextual Windows  (Leído 16,540 veces)
Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #20 en: 27 Agosto 2018, 19:12 pm »

Saqué un poco de tiempo anoche para hacer un sencillo ejemplo, pero se me hizo tarde para postearlo aquí, y ponerlo sin comentarios no me parecía adecuado...

Me falta crear un fichero reg, que sirva de apoyo al ejemplo, para hacer el registro de las claves que se van a necesitar. Este lo pondré a la noche cuando regrese del curro...



Para el ejemplo vamos a considerar que se tratara de un programa que puede comprimir y descomprimir (que suelen tener muchos parámetros disponibles y por ello más complejos de lo habitual)... debe servir para entender ampliamente las formas de proceder (que no son fijas, ni inalterables, solo instructivas). Y supuestamente... dicho programa de ejemplo generaría ficheros con extensión *.comp

Al comienzo hay que considerar que acciones vamos a necesitar y qué parámetros precisa cada una.
Si tenemos ya el código que hace cada acción, los parámetros pueden ser los mismos que toman las funciones, y solo resta ver de escoger la letra/s más propicia para cada acción. Si son pocas acciones las que vamos a registrar, no hace falta comerse mucho la cabeza pero sin muchas, habrá que pararse en ello, más tiempo y meditarlo bien....

Algunas aclaraciones previas para no liarnos:
Los parámetros que aceptamos, no distinguimos mayúsculas de minúsculas pero eso al gusto, si el programa hubiera de proveer tropecientos parámetros, quizás haya que repensarlo, aunque es fácil que los usuarios no reparen en la distinción de tal circunstancia... es preferible evitar parecidos confusos.

Cuando solo lleva un parámetro o dos, no hace falta mucho 'guiso' con ellos, pero cuando van a ser varios, es preferible que tengan un formato que podamos entender y manipular fácilmente.

Como en las líneas de comando, está a la orden del día que se incluyan rutas, debes parar a considerar que ciertos caracteres no son válidos para las rutas, precisamente por que se utilizan para acciones sobre las rutas... por ejemplo nunca podrás poner un '*' al nombre de un fichero o carpeta, porque el asterisco es un 'comodín' para nombres de ficheros... esos caracteres prohibidos en las rutas, son precisamente los más aptos y los que nos han de servir para realizar nuestro formato. Los que programan en 'C', tienen el gran incordio de las dobles barras '\\' como separadores de rutas, precisamente por ser un escollo... harmeos uso del carácter ":" que como también foramn parte de las rutas, y por elegir hacer 'splits', igualmente nos vemos forzados s poner 2... podríamos haber elegido otro modelo para el formato, pero así se aprenden más cosas por el camino.

Y ahora al grano, cada parámetro irá antecedido de la barra ' /' y detrás irá la letra o letras que dan nombre al parámetro y que será lo que el programa reconozca. Cuando un parámetro deba llevar adjunto además de un valor, irá en la forma:
/parametro::valor
Ejemplos:
/ruta::C:/program files/compresor/ejemplo.txt
/T::3
/S::<<<--->>>


Luego en el programa se escruta la línea de comandos recibida...
 - Iniciamente se hace un split, generando así un array con todos los parámetros y ya libres de la barra, porque cortamos justamente por ella (fijarse que lleva un espacio delante, para impedir que se corte por la barra de las rutas). Por tanto se exige, que cada parámetro vaya antecedido de " /"...
 - Los parámetros son flexibles, no se exige que haya un orden concreto en la entrada de los parámetros, excepto para el parámetro que marca la orden-acción a ejecutar, que debe ser el primer parámetro.
De no ser asi, complica el asunto (innecesariamente pués antes que nada, habría que recorrer todos los parámetros para buscar la orden y retirarla, para luego investigar que parámetro acompañan a dicha orden).

- El primer parámetro se exige que sea la acción-orden que se reclama llevar a cabo. Cada tipo de orden llevará asociado sus propios parámetros, e ignorará los que no le competen (no marcará error si aparece un parámetro que no entiende, una vez quede clara la orden a ejecutar).
Al diseñar los parámetros (el string dedicado a cada uno), sin embargo los específicos de una orden no deberían interferir con los de otra,  es decir, los usados para una orden o significan lo mismo para otra orden o mejor usar otra 'letra-palabra', para no confundir al usuario del programa ni producirle amargas experiencias...
Es decir si /t significa Tipo, para una acción conviene que signifiqwue Tipo para todas las acciones, hacer que signifique 'Todo' para otra acción facilita que un posible usuario cometa errores y no se los aprenda.

Como decía, el programa de ejemplo consideramos que se tratara de un programa que puede comprimir y descomprimir, estas son las órdenes admitidas (evidentemente las que uno quiera tratar), yo he elegido estas de ejemplo y nótese que aunque en el registro se pondrá solo una letra, si se invoca por ejemplo desde un bat o desde una ventana de scripts (cmd, powershell, etc...) puede pasarse cualquiera de los valores señalados para la acción:

/h, /?, /Help, /Ayuda          
Propósito: mostrar info de ayuda
Si aparece, se ignora el resto de parámetros que hubiere...

La ayuda se invoca también si aparece un parámetro como orden, que no se reconoce...(pero solo si aparece como ORDEN)
...o si faltan parámetros obligatorios para una orden específica. En esete caso se invoca justo desde donde se escruta la orden.

/i, /Info                      
Propósito: Reclama información sobre un fichero comprimido.
Razonablemente exige que la ruta recibida sea un fichero de tipo ".comp"
Parámetros adicionales para esta orden:
           /r::ruta /Ruta::ruta
                      Obligatorio, Especifica la ruta de entrada, debe ser un  fichero de tipo '.comp'...
                      Ejemplo: /r::c:/Fotos/primavera 2020/primavera.comp
           /k, /Comment, /Comentario  
                      Opcional, Señala que se muestre el comentario del archivo si lo tiene.

      
/t, /Test, /v, /Verificar, /Verify  
Propósito: Reclama verificar si el archivo está bien o resulta dañado.
Puede solicitarse distintos niveles de verificación.
Parámetros adicionales para esta orden:
           /r::ruta /Ruta::ruta        
                      Obligatorio, Especifica la ruta de entrada, debe ser un  fichero de tipo '.comp'...
                      Ejemplo: /r::c:/Fotos/primavera 2020/primavera.comp
           /n::numero /Nivel::numero    
                      Opcional, señala el nivel de verificación que se lleva a cabo. Por defecto, solo evalúa la cabecera.

/l, /Listar                    
Propósito: Reclama listar el contenido de un fichero comp.
La ruta de entrada es obligatoria, el separador y la ruta de destino opcionales (si no se acompaña de ruta de destino, se vuelca en la pantalla, si la trae se vuelca al fichero).
           /r::ruta /Ruta::ruta          
                      Obligatorio, Especifica la ruta de entrada, debe ser un  fichero de tipo '.comp'...
                      Ejemplo: /r::c:/Fotos/invierno 2020/invierno.comp
           /d::ruta, /Destino::ruta      
                      Opcional, Especifica una ruta de destino donde volcar el listado. No debe existir.
                      Ejemplo: /r::c:/Fotos/invierno 2020/invierno.txt
           /s::string, /separador::string  
                      Opcional, Separador usado para generar el listado, si se omite se usa 'CR+LF'


/e, /Extraer, /Extract    
Propósito: Reclama la extracción de todo o parte del contenido.
           /r::ruta /Ruta::ruta          
                      Obligatorio, Especifica la ruta de entrada, debe ser un  fichero de tipo '.comp'...
                      Ejemplo: /r::c:/Fotos/invierno 2020/invierno.comp
           /d::carpeta, /Destino::carpeta
                      Obligatorio, Especifica una Carpeta de destino donde extraer el contenido. No debe existir (no sobrescribe).
                      Ejemplo: /r::c:/Fotos/invierno 2020/
           /p::patron, /Pattern::patron, /Patron::patron
                      Opcional, especifica un patrón que señala que se va a extraer.
                      Ejemplo: /p::*.jpg     (apunta a todas las imágenes jpg)
                      Ejemplo: /p::*vacaciones*.jpg   /apunta las imágenes jpg, que contengan 'vacaciones' en el nombre)
                      Ejemplo: /p::-20   (extrae las 20 últimos ficheros, si hay menos pués todos).

/a, /Add, /Añadir        
Proposito: Reclama comprimir y añadir ficheros a un archivo ya existente.
Podría llevar más parámetros para indicar otras opciones, pero es solo un ejemplo...
           /r::ruta /Ruta::ruta          
                      Obligatorio, Especifica la ruta de entrada, debe ser un  fichero de tipo '.comp'...
                      Ejemplo: /r::c:/Fotos/invierno 2020/invierno.comp
           /f::ruta /File::ruta, /Fichero::ruta
                      Obligatorio, Especifica la ruta del fichero a comprimir, debe existir...
                      Ejemplo: /r::c:/Fotos/invierno 2020/vacaciones en Marte 1254.jpg
           /t::numero, /Type::numero, /Tipo::numero    
                      Opcional, Determina que tipo de compresión quiere usarse... (un valor 0, no comprime solo archiva)

/c, /Compress, /Comprimir      
Propósito: Reclama crear un nuevo fichero comprimido, partiendo de la ruta recibida.
Puede ser un fichero o una carpeta. Si es una carpeta, comprime (supuestamente) todos los ficheros en la raíz de dicha carpeta (por defecto), y un parámetro adicional señala si comprime recursivamente.
Es común que un archivo comprimido pueda incorporar un comentario, pero no es normal que dicho comentario esté contenido sobre el registro (sería el mismo para todos los archivos). Pero si podría crearse otra acción para investigar si un archivo *.comp no tiene comentario y en tal caso abrir una ventanita para añadirle uno... pero.... es solo un ejemplo.
           /r::ruta, /Ruta::ruta          
                      Obligatorio. Especifica la ruta de entrada, donde está el fichero/s que se van a comprimir (puede ser un fichero o una carpeta).
                      Ejemplo: /r::c:/Fotos/invierno 2020/
                      Ejemplo: /r::c:/Fotos/invierno 2020/vacaciones en Marte 1254.jpg
           /t::x, /Type::x, /Tipo::x    
                      Opcional, Determina que tipo de compresión quiere usarse...
           /n,  /Nest, /Recursivo, /Anidado
                      Opcional, Si es una carpeta, indica si también se comprimirá todo el contenido de las subcarpetas que contenga.

Y listo... ese será todo lo que el programa habrá de reconocer... 7 órdenes-acciones distintas, cada una con sus propios parámetros, en el registro habran de introducirse todas esas accciones... muchas irán solamente sobre ficheros *.comp, y otras sobre cualquier fichero y carpeta...  


Ahora pasamos a la parte del código... yo había elegido windows forms, pero como al final no se hará con la interfaz, lo cambié a una aplicación de consola y como bien dice Elektro, no estoy muy puesto en WPF.
WPF lo veo más bien como la evolución dentro de las empresas de 'superespecialización', donde al final habrá programadores especializados solo en shell, solo en menús, solo en interfaces, solo en red, solo en seguridad, solo en... yo soy contrario a ese ideal empresarial, creo que un programador debe ser todoterreno, completo, no localizado en una porción minúscula dentro de un región, dentro de... y debe saber de casi todo, dominar al menos varios temas (todos es imposible), y tener amplios y profundos conocimientos en otros varios temas más, aunque también habrá otros temas que a uno no le parezcan nada atractivos y le queden lejanos... es razonable.

También te aclaro, que el espacio de nombre My (en Visual Basic), ofrece mayor funcionalidad de cara a operar con la línea de comandos que recibe el programa, sin embargo... cuanto a menor nivel de objetos se dé el ejemplo, más fácil será de trasladar a cualquier otro lenguaje, especialmente si no se tiene gran conocimiento de los objetos específicos de un lenguaje... así que predomina el uso del string... y los pocos métodos que uso son autoentendibles aunque varíen ligeramente en otro lenguaje.

He elegido una aplicación de consola, toda vez que no vamos a hacer nada con una interfaz, si se plasma el código en una aplicación windows forms, el código sobre Main, debe trasladarse al Sub New del form1, y con lo mismo las llamadas a 'console.writeline' pueden ser derivados hacia 'messagebox.show()'... y listo...
Por lo demás mientras se prueba mejor en modo debug, y meter la línea de comandos sobre "opciones de inicio, en la ficha "depurar" de la ventana de "Propiedades del proyecto" (el punto donde se localice puede variar según la versión de VS y lenguaje específico que uno tenga, pero vamos bucenado sobre el IDE, debe uno acabar por encontrarlo. Adjuntaré imágenes de todos modos...


Código
  1. Sub Main()
  2.        ' Si no hay línea de comandos, y fuera un programa con interfaz gráfica, debería abrir la aplicación por la ventana por defecto...
  3.        If (Command.Length > 0) Then
  4.            Call ProcesarLineaDeComandos()
  5.            ' si fuera una aplicación de windows forms,
  6.            'End  (y retirar el END de más abajo).
  7.        End If
  8.        End
  9. En sub
  10.  

En Main, lo dejamos claro y simple... si la línea d ecomandos ha recibido algo, se manda procesar y al término da por finalizada la sesión.

Ahora el código en dicha función que es la que evalúa todo el trabajo de proceso de la línea de comandos (pero no ejecuta ninguna orden ahí, cada orden se deriva a la función específica...
Básicamente esta es la función de la que te debes empapar bien... y tratar de comprenderla al 100%.
Date cuenta que se podría optimizar mucho, pero posiblemente a riesgo de quedar más oscuro para los que no dominen VB... así creo que incluso alguien que apenas sepa nada de Vb, sería capaz de entenderlo todo o casi todo...
Código
  1. Private Sub ProcesarLineaDeComandos()
  2.        Dim sepCommand(0) As String        
  3.        Dim cmd() As String
  4.        Dim SubParam() As String
  5.        Dim k As Integer, n As Integer = 0
  6.        Dim Param As String, Valor As String = ""
  7.        Dim faltaParam As String = "No se puede procesar el comando. Falta uno o más parámetros obligatorios "
  8.  
  9.        Dim rutaOrg As String = "", rutaDst As String = ""
  10.        Dim separador As String = vbCrLf, Comentario As String = "", patron As String = ""
  11.        Dim nivel As Integer = 0, tipo As Integer = 0
  12.        Dim tComentario As Boolean = False, recursivo As Boolean = False
  13.  
  14.        sepCommand(0) = " /"
  15.        If Command.StartsWith(" ") = False Then
  16.            Param = " " & Command()
  17.        Else
  18.            Param = Command()
  19.        End If
  20.        cmd = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  21.        sepCommand(0) = "::"
  22.  
  23.        ' Puede limitarse los parámetros a usar un único carácter en vez de todo un texto, remplazando
  24.        '  las líneas: If (Param.Contains(sepCommand)) Then
  25.        '  por la siguiente If (Param.Length > 1) Then
  26.  
  27.        Param = cmd(0).ToUpper
  28.        Select Case Param  ' la orden, se exige que sea el primer parámetro, y no lleva valor detrás.
  29.            Case "I", "INFO"
  30.                For k = 1 To cmd.GetUpperBound(0)
  31.                    Param = cmd(k).ToUpper
  32.  
  33.                    If (Param.Contains("::")) Then
  34.                        SubParam = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  35.                        If (SubParam.Length > 1) Then
  36.                            Param = SubParam(0) : Valor = SubParam(1)
  37.                        Else
  38.                            Param = "-"
  39.                        End If
  40.                    End If
  41.  
  42.                    Select Case Param
  43.                        Case "R", "RUTA"
  44.                            rutaOrg = Valor
  45.                        Case "K", "COMMENT", "COMENTARIO"
  46.                            tComentario = True
  47.                    End Select
  48.                Next
  49.  
  50.                ' Esta orden, contiene todo lo necesario?
  51.                If (rutaOrg.Length > 0) Then
  52.                    Call Informar(rutaOrg, tComentario)
  53.                Else
  54.                    Call ShowAyuda(faltaParam & " /Ruta, es obligatorio para /Info")
  55.                End If
  56.            Case "L", "LISTAR", "LIST"
  57.                For k = 1 To cmd.GetUpperBound(0)
  58.                    Param = cmd(k).ToUpper
  59.  
  60.                    If (Param.Contains("::")) Then
  61.                        SubParam = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  62.                        If (SubParam.Length > 1) Then
  63.                            Param = SubParam(0) : Valor = SubParam(1)
  64.                        Else
  65.                            Param = "-"
  66.                        End If
  67.                    End If
  68.  
  69.                    Select Case Param
  70.                        Case "R", "RUTA"
  71.                            rutaOrg = Valor
  72.                        Case "D", "DESTINO"
  73.                            rutaDst = Valor
  74.                        Case "S", "SEPARADOR"
  75.                            separador = Valor
  76.                    End Select
  77.                    Valor = ""
  78.                Next
  79.  
  80.                ' Esta orden, contiene todo lo necesario?
  81.                If (rutaOrg.Length > 0) Then
  82.                    Call ListarContenido(rutaOrg, separador, rutaDst)
  83.                Else
  84.                    Call ShowAyuda(faltaParam & " /Ruta, es obligatorio para /Listar")
  85.                End If
  86.  
  87.            Case "T", "V", "TEST", "VERIFY", "VERIFICAR"
  88.                For k = 1 To cmd.GetUpperBound(0)
  89.                    Param = cmd(k).ToUpper
  90.  
  91.                    If (Param.Contains("::")) Then
  92.                        SubParam = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  93.                        If (SubParam.Length > 1) Then
  94.                            Param = SubParam(0) : Valor = SubParam(1)
  95.                        Else
  96.                            Param = "-"
  97.                        End If
  98.                    End If
  99.  
  100.                    Select Case Param
  101.                        Case Is = "R", "RUTA"
  102.                            rutaOrg = Valor
  103.                        Case "N", "NIVEL"
  104.                            nivel = Integer.Parse(Valor)
  105.                    End Select
  106.                Next
  107.  
  108.                ' Esta orden, contiene todo lo necesario?
  109.                If (rutaOrg.Length > 0) Then
  110.                    Call Verificar(rutaOrg, nivel)
  111.                Else
  112.                    Call ShowAyuda(faltaParam & " /Ruta, es obligatorio para /Verificar")
  113.                End If
  114.  
  115.            Case "E", "EXTRAER", "EXTRACT"
  116.                For k = 1 To cmd.GetUpperBound(0)
  117.                    Param = cmd(k).ToUpper
  118.  
  119.                    If (Param.Contains("::")) Then
  120.                        SubParam = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  121.                        If (SubParam.Length > 1) Then
  122.                            Param = SubParam(0) : Valor = SubParam(1)
  123.                        Else
  124.                            Param = "-"
  125.                        End If
  126.                    End If
  127.  
  128.                    Select Case Param
  129.                        Case "R", "RUTA"
  130.                            rutaOrg = Valor
  131.                        Case "D", "DESTINO"
  132.                            rutaDst = Valor
  133.                        Case "P", "PATTERN", "PATRON"
  134.                            patron = Valor
  135.                    End Select
  136.                Next
  137.  
  138.                ' Esta orden, contiene todo lo necesario?
  139.                If ((rutaOrg.Length > 0) And (rutaDst.Length > 0)) Then
  140.                    Call Extraer(rutaOrg, rutaDst, patron)
  141.                Else
  142.                    Call ShowAyuda(faltaParam & " /Ruta o /Destino (ó ambas) son obligatorias para /Extraer uno o más ficheros")
  143.                End If
  144.  
  145.            Case "C", "COMPRIMIR", "COMPRESS"
  146.                For k = 1 To cmd.GetUpperBound(0)
  147.                    Param = cmd(k).ToUpper
  148.  
  149.                    If (Param.Contains("::")) Then
  150.                        SubParam = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  151.                        If (SubParam.Length > 1) Then
  152.                            Param = SubParam(0) : Valor = SubParam(1)
  153.                        Else
  154.                            Param = "-"
  155.                        End If
  156.                    End If
  157.  
  158.                    Select Case Param
  159.                        Case "R", "RUTA"
  160.                            rutaOrg = Valor
  161.                        Case "T", "Tipo", "TYPE"
  162.                            tipo = Valor
  163.                        Case "N", "RECURSIVO", "ANIDADO", "NEST"
  164.                            recursivo = True
  165.                    End Select
  166.                Next
  167.  
  168.                ' Esta orden, contiene todo lo necesario?
  169.                If (rutaOrg.Length > 0) Then
  170.                    Call Comprimir(rutaOrg, tipo, recursivo)
  171.                Else
  172.                    Call ShowAyuda(faltaParam & " /Ruta, es obligatorio para /Comprimir")
  173.                End If
  174.  
  175.            Case "A", "ADD", "AÑADIR"
  176.                For k = 1 To cmd.GetUpperBound(0)
  177.                    Param = cmd(k).ToUpper
  178.  
  179.                    If (Param.Contains("::")) Then
  180.                        SubParam = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  181.                        If (SubParam.Length > 1) Then
  182.                            Param = SubParam(0) : Valor = SubParam(1)
  183.                        Else
  184.                            Param = "-"
  185.                        End If
  186.                    End If
  187.  
  188.                    Select Case Param
  189.                        Case "R", "RUTA"
  190.                            rutaOrg = Valor
  191.                        Case "F", "FILE", "FICHERO"
  192.                            rutaDst = Valor
  193.                        Case "T", "Tipo", "TYPE"
  194.                            tipo = Valor
  195.                    End Select
  196.                Next
  197.  
  198.                ' Esta orden, contiene todo lo necesario?
  199.                If ((rutaOrg.Length > 0) And (rutaDst.Length > 0)) Then
  200.                    Call Añadir(rutaOrg, rutaDst, tipo)
  201.                Else
  202.                    Call ShowAyuda(faltaParam & " /Ruta o /Fichero (ó ambas) son obligatorias para /Añadir un nuevo fichero al archivo comprimido.")
  203.                End If
  204.  
  205.            Case "H", "?", "HELP", "AYUDA"
  206.                Call ShowAyuda("")
  207.  
  208.            Case Else ' una orden con la que el programa no tiene 'compromiso' (quizás si en una versión más actual).
  209.                Call ShowAyuda("No se reconoce el comando recibido (para la versión actual), se muestra la forma correcta de invocar el programa...")
  210.        End Select
  211.    End Sub
  212.  
  213.  
Como se puede ver cada acción realiza básicamente lo mismo... chequea cada parámetro aparecido en un bucle donde se pone como trampa cada parámetro que dicha acción admite, si aparece toma el valor que contenga si aparece un parámetro 'extraño' qued aignorado...
Luego se verifica que los parámetros obligatorios para la orden solicitada existan todos, si no se aborta y se lanza el 'manual' de la ayuda...
Si todo va bien, se invoca la función que ha de ejecutar la acción, junto con todos los parámetros.
OJO: Para parámetros opcionales, siempre debe inicializarse a un valor por defecto, de modo que si tal parámetro no comparece, sea el valor por defecto el que recibe la función.
A veces la aparición de un parámetro inutiliza el valor de otro, es decir hay parámetros con prioridad... en el ejemplo solo se dan 2 casos, uno con la ruta para la acción 'Comprimir', que permite añadir un único fichero o todos los que tenga una carpeta...
El otro caso se da  en listar, en teoría se volcará el listado por consola, pero si aparece un parámetro de ruta de destino para un fichero, se vuelva la salida a dicho fichero...
A veces se dan casos, donde un parámetro que recibe un valor siguen siendo válido el parámetro pero otro parámetro con más prioridad invalida su valor... es un caso más complejo, y esos casos se deben tratar mejor ya dentro de la función que ha de ejecutar la acción.

Solo queda añadir las funciones (de pega, la  única a medio completar es la de ayuda), para que haciendo un copy-paste, y modificando lo que proceda (si se adapta a otro lenguaje), pueda ejecutarse hasta el crítico momento de entrar a la función que acabaría realizando la ejecución de la acción solicitada.
Código
  1. #Region "Procesado de Ordenes..."
  2.    ''' <summary>
  3.    ''' Orden ayuda (o cuando hay error en los parámetros de entradas).
  4.    ''' </summary>
  5.    ''' <param name="TextoExtra"></param>
  6.    ''' <remarks></remarks>
  7.    Private Sub ShowAyuda(ByRef TextoExtra As String)
  8.        If (TextoExtra.Length > 0) Then
  9.            Console.WriteLine(TextoExtra & vbCrLf)
  10.            Console.WriteLine(Strings.StrDup(80, "="))
  11.            Console.WriteLine("")
  12.        End If
  13.        Console.WriteLine("Uso:" & vbTab & "compresor.exe /orden <resto de parametros para dicha orden>")
  14.        Console.WriteLine(Strings.StrDup(80, "="))
  15.        Console.WriteLine("")
  16.        Console.WriteLine("Ordenes disponibles: Añadir, Ayuda, Extraer, Comprimir, Info, Listar, Verificar, ")
  17.        Console.WriteLine("   Comprimir: Crea un nuevo fichero comprimido, partiendo de la ruta recibida. Fichero o carpeta.")
  18.        Console.WriteLine("     Parametros: /c /r:ruta [/t:x] [/n]")
  19.        Console.WriteLine("     /c" & vbTab & "Orden para comprimir (tambien puede indicarse /Compress o /Comprimir)")
  20.        Console.WriteLine("     /r:ruta" & vbTab & "Obligatorio. Especifica la ruta de entrada, donde esta el fichero/s que se van a comprimir (puede ser un fichero o una carpeta).")
  21.        Console.WriteLine("     /t:numero" & vbTab & "Opcional. Determina que tipo de compresion quiere usarse... (un valor 0, no comprime solo archiva)")
  22.        Console.WriteLine("     /n" & vbTab & "Opcional. Si es una carpeta, indica si tambien se comprimira todo el contenido de las subcarpetas que contenga.")
  23.        Console.WriteLine("")
  24.        Console.WriteLine("   Listar: Enumera el contenido de un fichero comp. Si no se indica una ruta de destino, se vuelca en la pantalla.")
  25.        Console.WriteLine("     Parametros: /l /r:ruta [/d:ruta] [/s:string]")
  26.        Console.WriteLine("     /l" & vbTab & "Orden para listar, también se acepta /List y /Listar")
  27.        Console.WriteLine("     /r:ruta" & vbTab & "Obligatorio. Especifica la ruta de entrada, debe ser un  fichero de tipo '.comp'...")
  28.        Console.WriteLine("     /d:ruta" & vbTab & "Opcional. Especifica una ruta de destino donde volcar el listado. No debe existir.")
  29.        Console.WriteLine("     /s:separador" & vbTab & "Opcional. Separador usado para generar el listado, si se omite se usa 'CR+LF'.")
  30.        Console.WriteLine("")
  31.        Console.WriteLine("   Ayuda: Muestra detalles del uso de la línea de comandos del programa.")
  32.        Console.WriteLine("     Parametros: /h")
  33.        Console.WriteLine("     /h" & vbTab & "Orden para mostrar este mensaje de ayuda (también se acepta /? /Help y /Ayuda)")
  34.        Console.WriteLine("")
  35.        Console.WriteLine("etc... para otras ordenes.")
  36.    End Sub
  37.  
  38.    ''' <summary>
  39.    ''' Orden para ofrecer información sencilla sobre un archivo comprimido.
  40.    ''' </summary>
  41.    ''' <param name="Ruta"></param>
  42.    ''' <param name="Comentario"></param>
  43.    ''' <remarks></remarks>
  44.    Private Sub Informar(ByVal Ruta As String, ByVal Comentario As Boolean)
  45.        Dim fsI As IO.FileStream
  46.  
  47.        If GetFileStreamSiEsFormatoValido(Ruta, fsI) = True Then
  48.            ' leer cabecera, tomar ciertos datos informativos
  49.            ' y mostrarlos en alguna ventanita...
  50.            ' versión del programa con que fue creada el archivo, cuantos ficheros contiene
  51.            '  tamaño del archivo y tamaño que tendría el contenido descomprimido...etc...
  52.            If Comentario = True Then
  53.                ' si el archivo contiene un comentario sobre el mismo, tomar para mostrarlo...
  54.            End If
  55.  
  56.            fsI.Close() : fsI = Nothing
  57.        End If
  58.    End Sub
  59.  
  60.    ''' <summary>
  61.    ''' Orden listar:
  62.    ''' </summary>
  63.    ''' <param name="Ruta"></param>
  64.    ''' <param name="Separador"></param>
  65.    ''' <param name="Destino"></param>
  66.    ''' <remarks></remarks>
  67.    Private Sub ListarContenido(ByRef Ruta As String, ByRef Separador As String, Optional ByRef Destino As String = "")
  68.        Dim fsI As IO.FileStream, fsO As IO.FileStream
  69.        Dim lista() As String ' o cualquier otro objeto que facilite el añadido... según diseño del programa.
  70.  
  71.        If GetFileStreamSiEsFormatoValido(Ruta, fsI) = True Then
  72.            ' leer la cabecera.
  73.            ' mover el puntero de lectura al punto donde consta la lista de ficheros contenidos
  74.            ' Ir tomando la lista de ficheros que contiene (si es una lista plana, si no ir saltando entre el contenido con el par direccion + size).
  75.            ' recordar añadir el separador tras cada nombre.
  76.            If (Destino.Length > 0) Then
  77.                If IO.File.Exists(Destino) = False Then
  78.                    ' crear fichero y volcar el contenido.
  79.                    ' en este caso es preferible ir escribiendo (append), directamente al fichero mejor que añadirlo a un array para después volcarlo a fichero...
  80.  
  81.                    '.Close() : fsO = Nothing
  82.                Else
  83.                    ' mensaje: error, el fichero de destino ya existe, la lista debe crearse en un fichero nuevo...
  84.                End If
  85.            Else ' volcarla por pantalla
  86.                ReDim lista(0 To 5)
  87.                Console.WriteLine("Éste es el contenido del archivo: " & vbCrLf & (lista.ToString)) ', "Contenido del archivo:")
  88.            End If
  89.  
  90.            fsI = Nothing
  91.        End If
  92.    End Sub
  93.  
  94.    ''' <summary>
  95.    ''' Orden para verificar
  96.    ''' </summary>
  97.    ''' <param name="Ruta"></param>
  98.    ''' <param name="Nivel"></param>
  99.    ''' <remarks></remarks>
  100.    Private Sub Verificar(ByVal Ruta As String, Optional ByVal Nivel As Integer = 0)
  101.        Dim fsI As IO.FileStream
  102.  
  103.        If GetFileStreamSiEsFormatoValido(Ruta, fsI) = True Then
  104.            ' (revisión mínima) leer cabecera y verificar que es correcta. esto siempre
  105.            If RevisionMinima(fsI) And Nivel > 0 Then
  106.                ' si nivel=1,(revisión simple) revisar por ejemplo que los índices de comienzo de extracción corresponden con la dirección guardada y tamaño del comprimido.
  107.                ' Si nivel=2 (revisión media) podría señalar revisión completa, en tal caso (por ejemplo), calcular hash, para todo el archivo (excepto la cabecera) y ver que coincide
  108.                '   con el hash guardado en la cabecera.
  109.                ' Si nivel>2 (revisión completa: a todo lo previo, toca ir extrayendo de uno en uno cada fichero comprimido y calcular su hash y comprobar que coincide con el alamcenado en la estructura ligada a dicho fichero)
  110.            End If
  111.  
  112.            ' informar de modo similar al chkdisk... por ejemplo...
  113.            ' ir informando sobre la marcha, para las revisiones 2 y mayor que 2...
  114.            ' informar al final con un resumen... todo ok, o falló tal cosa...
  115.        End If
  116.    End Sub
  117.  
  118.    ''' <summary>
  119.    ''' Orden para extraer contenido, todo o parcial.
  120.    ''' </summary>
  121.    ''' <param name="Ruta"></param>
  122.    ''' <param name="Destino"></param>
  123.    ''' <param name="Patron"></param>
  124.    ''' <remarks></remarks>
  125.    Private Sub Extraer(ByVal Ruta As String, ByVal Destino As String, ByVal Patron As String)
  126.        Dim fsI As IO.FileStream
  127.  
  128.        ' Si no existe la carpeta de destino, ni siquiera nos molestamos en abrir el archivo.
  129.        ' opcionalmente podría crearse la carpeta (solo si la ruta padre para ella existe)
  130.        '   pero como es un ejemplo, basta así...
  131.        If IO.Directory.Exists(Destino) Then
  132.            If GetFileStreamSiEsFormatoValido(Ruta, fsI) = True Then
  133.                ' Evaluar el patrón:
  134.                ' Si es "" implica que se extrae todo.
  135.                ' Si es en la forma *.extension" ó ".extension" , se extraen todos los ficheros que coincidan con dicha extensión...
  136.                ' Si es en la forma *algo* se extraen todos los ficheros que contengan ese 'algo'...
  137.                ' si es en la forma 'Xnumero-', se extraen los primeros x ficheros del comeinzo del archivo.
  138.                ' si es en la forma '-Xnumero', se extraen los últimos x ficheros del final del archivo.
  139.                ' si es en la forma 'Ynumero-Xnumero', se extren los x ficheros a partir de yº fichero comprimido.
  140.                ' si es en la forma 'nombre.extension' se extrae el fichero cuyo nombre coincide (si existe).
  141.                ' también podrían indicarse patrones por fecha..."mm/dd/AAAA' por ejemplo, para extrer los ficheros cuya fecha de compresión/creacion/modificacion/etc... coincidan con la indicada...
  142.                '  incluyendo fechas parciales como indicar solo el mes o año, o un rango entre fechas...
  143.                ' etc... cosa de imaginación.
  144.  
  145.                ' informar al final de la cantidad de ficheros extraídos... y abrir la carpeta donde se extrajo (resulta útil).
  146.            End If
  147.        End If
  148.    End Sub
  149.  
  150.    ''' <summary>
  151.    ''' Orden para comprimir un fichero y añadirlo al archivo comprimido.
  152.    ''' </summary>
  153.    ''' <param name="Ruta"></param>
  154.    ''' <param name="Fichero"></param>
  155.    ''' <remarks></remarks>
  156.    Private Sub Añadir(ByVal Ruta As String, ByVal Fichero As String, ByVal Tipo As Integer)
  157.        ' verifica que el fichero comprimido existe (se supone que sí) y el de origen
  158.        ' luego Más de lo mismo, comprime el fichero, añadiéndolo al final del archivo,
  159.        ' y actualiza la cabecera, cantidad de ficheros, y hash de la cabecera.
  160.        ' etc..
  161.        '...
  162.    End Sub
  163.  
  164.    ''' <summary>
  165.    ''' Orden para crear un nuevo archivo comprimido (no debe existir)
  166.    ''' </summary>
  167.    ''' <param name="Ruta"></param>
  168.    ''' <param name="Tipo"></param>
  169.    ''' <param name="Recursivo"></param>
  170.    ''' <remarks></remarks>
  171.    Private Sub Comprimir(ByVal Ruta As String, ByVal Tipo As Integer, Optional ByVal Recursivo As Boolean = False)
  172.        Dim nombre As String
  173.        Dim fsO As IO.FileStream
  174.        Dim fi As IO.FileInfo, di As IO.DirectoryInfo
  175.        Dim puntero As Int64
  176.        Dim numfiles As Integer
  177.  
  178.        ' no sabemos a priori si origen es la ruta a un fichero o a una carpeta
  179.        ' si es una carpeta, se comprimirá todo su contenido.
  180.        If IO.Directory.Exists(Ruta) Then
  181.            di = FileIO.FileSystem.GetDirectoryInfo(Ruta)
  182.            nombre = (Ruta & "\" & di.Name & ".comp")
  183.            fsO = IO.File.Create(nombre)
  184.  
  185.            puntero = ComprimirAnidado(fsO, Ruta, numfiles, Tipo, Recursivo)
  186.        ElseIf FileIO.FileSystem.FileExists(Ruta) Then
  187.            fi = FileIO.FileSystem.GetFileInfo(Ruta)
  188.            nombre = Ruta.Replace(fi.Extension.ToUpper, ".comp")
  189.            If IO.File.Exists(nombre) = False Then
  190.                fsO = IO.File.Create(nombre)
  191.  
  192.                puntero = ComprimirFichero(fsO, Tipo, Ruta)
  193.                numfiles = 1
  194.            Else
  195.                ' error ya existe el archivo de salida, debe crearse uno nuevo... no puede existir.
  196.                Exit Sub
  197.            End If
  198.        End If
  199.  
  200.        If puntero = -1 Then
  201.            ' mensaje: ha fallado la compresión para el fichero 'nombre'
  202.            ' se puede solicitar ignorar y continuar, o bien abortar,
  203.            ' como es un ejemplo se aborta, pero se informa...
  204.            'fsO.Close()
  205.            ' eliminar archivo.
  206.        Else
  207.            ' mensaje: archivo creado... total de 'numfiles' comprimidos...
  208.        End If
  209.  
  210.        fsO = Nothing
  211.    End Sub
  212. #End Region
  213.  

Y finalmente otras pequeñas funciones (tamvbién de 'papel-cartón') que aparecen invocadas en el código, para que no cante error...
Código
  1. #Region "Las funciones que realizan todo el trabajo (ejecutan las órdenes)"
  2.  
  3.    Private Function ComprimirAnidado(ByRef Fs As IO.FileStream, ByRef Carpeta As String, ByRef NumFiles As Integer, ByVal Tipo As Integer, ByRef Recursivo As Boolean) As Int64
  4.        Dim fi As IO.FileInfo, di As IO.DirectoryInfo, d As IO.DirectoryInfo
  5.        Dim files() As IO.FileInfo, folders() As IO.DirectoryInfo
  6.        Dim puntero As Int64
  7.  
  8.        di = FileIO.FileSystem.GetDirectoryInfo(Carpeta)
  9.  
  10.        files = di.GetFiles
  11.        For Each fi In files
  12.            puntero = ComprimirFichero(Fs, Tipo, fi.FullName)
  13.            If (puntero = -1) Then
  14.                Return -1
  15.            Else
  16.                ' puntero se usa como dirección, punto de inicio de la compresión del siguiente fichero
  17.                '  para la estructura del mismo
  18.                NumFiles += 1
  19.            End If
  20.        Next
  21.  
  22.        If (Recursivo = True) Then
  23.            folders = di.GetDirectories
  24.            For Each d In folders
  25.                puntero = ComprimirAnidado(Fs, d.FullName, NumFiles, Tipo, Recursivo)
  26.                If puntero = -1 Then
  27.                    Return -1
  28.                End If
  29.            Next
  30.        End If
  31.  
  32.        Return Fs.Position
  33.    End Function
  34.  
  35.    Private Function ComprimirFichero(ByRef Fs As IO.FileStream, ByVal Tipo As Integer, ByRef Fichero As String) As Int64
  36.        Dim fsI As IO.FileStream
  37.  
  38.        fsI = IO.File.OpenRead(Fichero)
  39.        ' según el tipo de compresión debería derivarse a la función específica...
  40.  
  41.        '...crear un búffer de lectura, y sobre un bucle ir leyendo y comprimiendo y volcando al destino.
  42.        ' al tiempo ir calculando un hash para sobre el buffer.
  43.        ' escribir los datos de cabecera de info del fichero (tamaño original, hash, fechas, etc...).
  44.        ' actualizar en destino
  45.  
  46.        ' si falla devolver -1.
  47.  
  48.        Return Fs.Position
  49.    End Function
  50.  
  51.    Private Function GetFileStreamSiEsFormatoValido(ByRef Ruta As String, ByRef fichero As IO.FileStream) As Boolean
  52.        If IO.File.Exists(Ruta) Then
  53.            Try
  54.                fichero = IO.File.OpenRead(Ruta) ' Verifica primero si existe el fichero.
  55.                '   lo(abre), lee la cabecera para verificar que es del tipo esperado
  56.                '   y quizás un breve chequeo de que no está corrupto...
  57.                '   Si todo conforme devuelve el filestream y
  58.                Return True
  59.                '   si no conforme
  60.                '      fichero.Close() : fichero = Nothing
  61.                '      mensaje: el fichero 'ruta' no es del formato que éste programa está capacitado para tratar.
  62.                '      o mensaje: el fichero 'ruta', es del tipo esperado, pero parece estar dañada la cabecera.
  63.                '      o mensaje: el fichero 'ruta' es del tipo esperado, pero la versión que señala no puede ser atendida por la versión actual del programa, por favor actualice a una versión más actual."
  64.                '      return false
  65.            Catch ex As Exception
  66.                Console.WriteLine("Ha ocurrido un error no controlado:" & vbCrLf & ex.Message)
  67.                Return False
  68.            End Try
  69.        Else 'si no existe:
  70.            '    mensaje: el fichero 'ruta' no parece existir (se ha movido, eliminado, renombrado?), o quizás no tenga permisos suficientes
  71.            Return False
  72.        End If
  73.    End Function
  74.  
  75.    ' Trata de ver que como mínimo la cabecera no está corrupta
  76.    '  (ya se sabe previamente que es del tipo adecuado y puede leerse)
  77.    Private Function RevisionMinima(ByRef FS As IO.FileStream) As Boolean
  78.        ' leer la cabecera y verificar que esta bien...
  79.        ' en general primero se computa un hash a la cabecera y luego se revisa con el hash contenido  en la misma cabecera. a estos efectos, el propio hash no debe formar parte de ese cómputo, por lo que suele ponerse al final de la cabecera.
  80.        Return True
  81.    End Function
  82. #End Region
  83.  

Y listo, debiera ser suficiente (si no soy muy optimista), para que te sirva de aprendizaje e inspiración...
Me queda eso si, poner alguna imagen y el contenido de un fichero reg, que guardara todas las acciones en el registro... aún así, para probarlo puede hacerse sin shell, haciendo uso de scripts... algún bat-cmd, por ejemplo. Aunuqe para eso entonce shay que compilarlo.
Si desde debug, se meten las opciones de línea de comando se puede probar "paso a paso" (en vbnet es la tecla F11, no recuerdo ahora mismo cual es la de C#).


En línea

rigorvzla

Desconectado Desconectado

Mensajes: 213


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #21 en: 28 Agosto 2018, 03:01 am »

Guao NEBIRE que explicacion tan extensa , solida y concisa, muchisimas gracias , esto es tema de sentarse a leer con detalle linea a linea y mas aun analizar cada linea de codigo, de momento pasare de implementarlo de una vez al proyecto mio ya que me llevara tiempo estudiar aprender y entender todo lo explicado, muchisimas gracias a medida de  que valla haciendlo las pruebas respectivas te ire preguntando para la mayor comprension  del tema,  MUCHISIMAS GRACIAS !! .

Dejare claro que uso C# WPF , basicamente por que es el primero y unico lenguaje de programacion que  me presentaron y hasta la fecha me ha gustado mucho, podria decir que es lo mejor que conozco y unico. Versatil y "Facil"... (para no ser programador de profesion).

Cinco estrellas a este super tutorial , le dedicare tiempo necesario y estare informandote de acuerdo a mis avances en el tema, ya previamente habia logrado con ejemplos previos de elektro crear una aplicacion simple con parametros donde mostraba mensajes, solo que se presentaron los problemas como que se abria nuevamente la aplicacion, cosa que no es correcto, entre otras cosas.

Pero ya con esa guia todo duda mia deberia quedar solventado.


En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.788



Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #22 en: 28 Agosto 2018, 05:00 am »

ya previamente habia logrado con ejemplos previos de elektro crear una aplicacion simple con parametros donde mostraba mensajes, solo que se presentaron los problemas como que se abria nuevamente la aplicacion, cosa que no es correcto, entre otras cosas.

Primero presentaste un problema, y se te ofrecieron dos soluciones (manipulación del registro de Windows, o desarrollo de una shell-extensión), luego presentaste un problema distinto y adicional que no habias comentado al principio: mantener una única instancia de tu app, y se te ofrecieron varias soluciones por mi parte con ejemplos completos y funcionales en el último post de la segunda página de este thread, que no los hayas querido o sabido aplicar es cosa tuya.

Lo comento, por que casi pareces insinuar que los problemas que te surgen sean culpa mía. Si desde un principio te expresaras con la suficiente claridad y comentando punto por punto todas y cada una de las cosas que quieres lograr hacer, todo sería más facil.



Ya que estamos, aquí te dejaré unos últimos ejemplos relacionados para mostrarte una alternativa de como lo puedes hacer. El primero demuestra una forma dinámica mediante clases de tipos genéricos, elegante y reutilizable para representar (definir) argumentos y también parsearlos en una aplicación:
 

...se podría decir que es una solución guiada para administrar la creación, el uso y el análisis de argumentos recibidos en la aplicación.

El segundo y último ejemplo demuestra una forma igualmente dinámica y elegante (mediante Xml) y además yo diría que incluso divertida al poder jugar con la colorización de forma dinámica, para representar la entrada de ayuda command-line mostrada por una aplicación:


Saludos.
« Última modificación: 28 Agosto 2018, 05:19 am por Eleкtro » En línea

rigorvzla

Desconectado Desconectado

Mensajes: 213


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #23 en: 28 Agosto 2018, 12:10 pm »

Elektro nada que ver con que tu generas problemas, todo lo contrario agradezco muchisimo la solucion que me diste tambien, ambas me seran de gran ayuda.

Citar
Lo comento, por que casi pareces insinuar que los problemas que te surgen sean culpa mía. Si desde un principio te expresaras con la suficiente claridad y comentando punto por punto todas y cada una de las cosas que quieres lograr hacer, todo sería más facil.

Se me es complicado explicarme con la suficiente claridad lo acepto no solo me pasa por aqui, pero aclaro que NO es culpa de ustedes lo que me surje a mi por falta de explicacion clara.

De igual manera agradezco el trabajo de ambos buen dia, me pondre a esto al tener la disponiblidad (factor tiempo es muy cruel y corto).
En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #24 en: 28 Agosto 2018, 23:49 pm »

Bueno, al final he echo el ficherito reg para añadir todas las acciones al registro...

Debajo del copiapega, algunos comentarios...

Código
  1. Windows Registry Editor Version 5.00
  2.  
  3. # Lo derivamos hacia una clave donde extendernos más...
  4. [HKEY_CLASSES_ROOT\.comp]
  5. @="compresorSuper"
  6.  
  7. [HKEY_CLASSES_ROOT\compresorSuper]
  8. "BrowserFlags"=dword:00000008
  9. @="Compresor descompresor de ficheros y carpetas"
  10. "EditFlags"=dword:00000000
  11. "AlwaysShowExt"=""
  12.  
  13. # El icono del programa se asocia a los *.comp...
  14. [HKEY_CLASSES_ROOT\compresorSuper\DefaultIcon]
  15. @="c:\\program files\\compresorSuper\\compresorSuper.exe,1"
  16.  
  17. [HKEY_CLASSES_ROOT\compresorSuper\shell]
  18.  
  19. [HKEY_CLASSES_ROOT\compresorSuper\shell\Open]
  20.  
  21. # Esta acción es la típica del doble click, a un fichero *.comp
  22. # El simple OPEN, al tratarse de una aplicación de consola lo derivamos hacia la acción: INFO
  23. #  Si fuera una interfaz, se abriría la aplicación mostrando una ventana con el contenido y un extenso menú...
  24. [HKEY_CLASSES_ROOT\compresorSuper\shell\Open\command]
  25. @="c:\\program files\\compresorSuper\\compresorSuper.exe /I /R::%1"
  26.  
  27.  
  28. # Acción para informar
  29. # --------------------------------
  30. [HKEY_CLASSES_ROOT\compresorSuper\shell\Informar]
  31. @="Comp:&Informar"
  32.  
  33. # Acción para informar con petición de mostrar el comentario...
  34. [HKEY_CLASSES_ROOT\compresorSuper\shell\Informar\command]
  35. @="c:\\program files\\compresorSuper\\compresorSuper.exe /I /R::%1 /K"
  36.  
  37.  
  38. # Acción para Verificar (TEST)
  39. # --------------------------------
  40. [HKEY_CLASSES_ROOT\compresorSuper\shell\Verificar]
  41. @="Comp:&Verificar"
  42.  
  43. # Acción para verificar con petición de hasta el nivel 2 (revisión media)
  44. [HKEY_CLASSES_ROOT\compresorSuper\shell\Verificar\command]
  45. @="c:\\program files\\compresorSuper\\compresorSuper.exe /T /R::%1 /N::2"
  46.  
  47.  
  48. # Acción para Listar
  49. # --------------------------------
  50. [HKEY_CLASSES_ROOT\compresorSuper\shell\ListarToScreen]
  51. @="Comp:&Listar en pantalla"
  52.  
  53. # Acción para Listar, el separador se deja por defecto (CR+LF), por lo que dicho parámetro se omite.
  54. [HKEY_CLASSES_ROOT\compresorSuper\shell\ListarToScreen\command]
  55. @="c:\\program files\\compresorSuper\\compresorSuper.exe /L /R::%1"
  56.  
  57.  
  58. # Acción para Listar (a FICHERO)
  59. # --------------------------------
  60. [HKEY_CLASSES_ROOT\compresorSuper\shell\ListarToFile]
  61. @="Comp:Li&star en fichero"
  62.  
  63. # Acción para Listar, a fichero... en la raíz de la unidad C.
  64. #  Algo más elaborado debería admitir el parámetro '/d' sin valor, para señalar que la carpeta fuere la misma de origen de %1
  65. [HKEY_CLASSES_ROOT\compresorSuper\shell\ListarToFile\command]
  66. @="c:\\program files\\compresorSuper\\compresorSuper.exe /L /R::%1 /D::C:\"
  67.  
  68.  
  69. # Acción para Extraer todo
  70. # --------------------------------
  71. [HKEY_CLASSES_ROOT\compresorSuper\shell\ExtraerTodo]
  72. @="Comp:&Extraer todo"
  73.  
  74. # Acción para Extraer todo, en la unidad C (que no es muy interesante).
  75. #  Algo más elaborado debería admitir el parámetro '/d' sin valor, para señalar que la carpeta fuere la misma de origen de %1
  76. #    o al menos preguntar por la ruta de extracción, trtas recibir el comando...
  77. [HKEY_CLASSES_ROOT\compresorSuper\shell\ExtraerTodo\command]
  78. @="c:\\program files\\compresorSuper\\compresorSuper.exe /E /R::%1 /D::C:\"
  79.  
  80.  
  81. # Acción para Extraer imágenes jpg
  82. # --------------------------------
  83. [HKEY_CLASSES_ROOT\compresorSuper\shell\ExtraerImgJpg]
  84. @="Comp:&Extraer imágenes jpg"
  85.  
  86. # Acción para Extraer solo las imágenes JPG (que hubiere dentro del archivo comprimido), en la unidad C (que no es muy interesante).
  87. #  Algo más elaborado debería admitir el parámetro '/d' sin valor, para señalar que la carpeta fuere la misma de origen de %1
  88. #    o al menos preguntar por la ruta de extracción, trtas recibir el comando...
  89. # Esto debiera dar idea que el mismo comando puede tener diferentes variaciones en función de los valores que se coloquen en los parámetros que admite.
  90. [HKEY_CLASSES_ROOT\compresorSuper\shell\ExtraerImgJpg\command]
  91. @="c:\\program files\\compresorSuper\\compresorSuper.exe /E /R::%1 /D::C:\ /P::*.jpg"
  92.  
  93. # Ayuda con la línea de comandos
  94. # --------------------------------
  95. [HKEY_CLASSES_ROOT\compresorSuper\shell\Ayuda]
  96. @="Comp:&Help (ayuda CommandLine)"
  97.  
  98. # No precisa más comentario...
  99. [HKEY_CLASSES_ROOT\compresorSuper\shell\ExtraerImgJpg\command]
  100. @="c:\\program files\\compresorSuper\\compresorSuper.exe /H"
  101.  
  102.  
  103.  
  104. # ====================================================================================
  105. # TODAS LAS ACCIONES PREVIAS EMERGEN SOLO PARA ARCHIVOS DE TIPO *.COMP
  106. # AHORA TOCA LA ÚNICA ACCIÓN QUE SE APLICA AL RESTO DE FICHEROS Y CARPETAS (COMPRIMIR)
  107. # ====================================================================================
  108.  
  109.  
  110. # Acción para Comprimir (fichero)
  111. # --------------------------------
  112. [HKEY_CLASSES_ROOT\*\shell\ComprimirComp]
  113. @="Comp:&Comprimir"
  114.  
  115. # Comprime el fichero... (con el algoritmo por defecto: tipo 1)
  116. [HKEY_CLASSES_ROOT\*\shell\ComprimirComp\command]
  117. @="c:\\program files\\compresorSuper\\compresorSuper.exe /C /R::%1 /T::1"
  118.  
  119.  
  120. # Acción para Comprimir (fichero)
  121. # --------------------------------
  122. [HKEY_CLASSES_ROOT\*\shell\ComprimirCompZip]
  123. @="Comp:Comprimir (&Zip)"
  124.  
  125. # Comprime el fichero... (con el algoritmo ZIP (tipo 2))
  126. [HKEY_CLASSES_ROOT\*\shell\ComprimirCompZip\command]
  127. @="c:\\program files\\compresorSuper\\compresorSuper.exe /C /R::%1 /T::2"
  128.  
  129.  
  130. # Acción para Comprimir (fichero)
  131. # --------------------------------
  132. [HKEY_CLASSES_ROOT\*\shell\ComprimirCompPaq]
  133. @="Comp:E&mpaquetar (no comprime)"
  134.  
  135. # Solo empaqueta el fichero... (tipo 0))
  136. [HKEY_CLASSES_ROOT\*\shell\ComprimirCompPaq\command]
  137. @="c:\\program files\\compresorSuper\\compresorSuper.exe /C /R::%1 /T::0"
  138.  
  139.  
  140.  
  141. # Acción para Comprimir (ficheros en carpeta)
  142. # --------------------------------
  143. [HKEY_CLASSES_ROOT\Directory\shell\ComprimirCompZip]
  144. @="Comp:&Comprimir (ficheros)"
  145.  
  146. # Acción para comprimir los ficheros en la raíz de la carpeta en ZIP (Tipo 2)
  147. [HKEY_CLASSES_ROOT\Directory\shell\ComprimirCompZip\command]
  148. @="c:\\program files\\compresorSuper\\compresorSuper.exe /C /R::%1 /T::2"
  149.  
  150.  
  151. # Acción para Comprimir (recursivamente en carpeta)
  152. # --------------------------------
  153. [HKEY_CLASSES_ROOT\Directory\shell\ComprimirCompZipNest]
  154. @="Comp:&Comprimir (recursivo)"
  155.  
  156. # Acción para comprimir el contenido completo de una carpeta en ZIP (Tipo 2)
  157. [HKEY_CLASSES_ROOT\Directory\shell\ComprimirCompZipNest\command]
  158. @="c:\\program files\\compresorSuper\\compresorSuper.exe /C /R::%1 /T::2 /N"
  159.  

0 - NOTA: No he probado el ficherito, espero que si contiene algún error seas capaz de subsanarlo, si no es así, informa, pero primero inténtalo por tí mismo...

1 - Lo primero, todo el texto de esta cita, lo copias y lo pegas en un fichero nuevo, y lo guardas con extensión .reg, luego haces los cambios que se indican a continuación y cuando estén todos los cambios acomodados, guardas de nuevo el contenido y haz doble click sobre él, el sistema reconoce este tipo de fichero y guardará todas las claves en el registro...

2 - Su contenido es una asociación con la exrtensión ".comp" (que se supone no existe en tu registro, si existiera, mira de cambiar sobre el texto del fichero por otra que no exista (quizás comp2, o lo que se te ocurra).

3 - Los archivos que crees (aunque estén vacios) con extensión .comp, llevarán el mismo icono de tu aplicación... Y cuando pinches sobre dicho ficheros, en el menú contextual aparecerá un chorro de acciones para ellos.
Para facilitar la búsqueda en el menú contextual, a todos los he precedido con un texto en la forma: 'comp: texto de acción', donde texto de acción es el texto que describe la acción... así aparecerán todos juntos y será fácil de ver....

4 - Cambios a realizar al fichero .reg:
Como se ve se da por sentado que el programa se llama CompresorSuper.exe, por tanto haz un remplazo para cambiar cada aparición de compresorSuper por el que hubiere de tener tu programa o bien deja este y crea una aplicación de prueba con la transcripción del código del mensaje previo, y así los cambios son mínimos al menos para probarlo... y fíjate que se deja una ruta en program files\nombre del programa\...
Es decir una vez que se meta esto al registro, debe existir un ejecutable en la ruta que se haya indicado... así que cambia la ruta a la que tu tengas...
5 - Para hacer uso (sin errores), de dichas acciones una vez registradas (es decir fuera ya de debug), debes haber compilado el programa y diponer el ejecutable en la ruta que se la indicado al registro...

6 - Guarda finalmente el fichero .reg y con doble click se introducirá al registro (seguramente te pida permiso para ello)...

7 - Ahora si examinas detenidamente el ficherito, verás que las acciones introducidas al registro, son las acciones que pusimos en el código más arriba, que son las que decdicmos que nuestro programa dispusiera de esta forma, y a nuestro antojo (observo que me he comido la acción "añadir", pero bueno el resto está y como son ejemplo de prueba pués vale). He añadido comentarios al ficherito y separado convenientemente cada acción de la siguiente, para mayor claridad...
Verás también que cada acción registrada tiene en concreto los parámetros designados para cada acción en el código, es decir se atiene al 'diseño' que elegimos... y por último verás que incluso hay acciones que tienen más de un 'registro', ya que se ha puesto una variación de la misma (a base de alterar los parámetros, por ejemplo 'comprimir y empaquetar y comprimir en Zip, etc...).

8 - Resument de registro: Hay 3 tipos de cosas registradas...
1º La asociación con una extensión. Fíjate como la extensión .comp se deriva hacia "compresorSuper", es una forma rápida de poder alterar-derivar una extensión hacia otra aplicación sin 'destruir' lo registrado por una aplicación previa. Así cuando abras el registro, no verás bajo la extensión .comp (bajo la clave HKEY\Classes\.comp más que una línea, por tanto busca luego esa clave en el registro (misma sección, es decir bajo: HKEY\Classes\compresorSuper ).

2º Se han resgistrado varias acciones para esa extensión, por tanto vinculadas al programa "compresorSuper.exe", es decir son accones que sólo emergerán en el menú contextual, cuando sea un fichero de tipo .comp ....por eso para probar que aparecen tras hacer el registro, deberás crear ficheros con esa extensión (crea un fichero de texto vacío (o escribe algo si quieres, no importa) y cambia su extensión... en ese punto, el registro no tiene ninguna respopnsabilidad sobre si un fichero es o no del tipo cuya extensión contiene, esa responsabilidad compete al programa asociado a la extensión (esto debe quedarte claro como el agua, para no exigir al registro cometidos que no le competen).

3º Se ha registrado para cualquier otro tipo de fichero, la acción comprimir y a las carpetas 2 acciones comprimir. es decir esas acciones solo cabe llevarlas a cabo a distintos ficheros, las previas solo a los de tipo .comp
Si te fijas bien, he dejado tachado (en el párrafo anterior) la palabra 'otro'... porque lamentablemente el registro es incapaz de entender que querríamos registrar acciones para todos los ficheros excepto para 1 (o más) determinados... por lo que el programa debería ser capaz de detectar cuando para esas acciones (en este caso cuando la acción es comprimir, únicamente), que el único fichero que no va a admitir esa acción, son precisamente los de tipo .comp (porque ya está comprimido), si se pretendiera comprimir una segunda vez, se debería cambiar la extensión. en resumen si a la acción comprimir le llega un fichero de tipo .comp, podría o debería rechazarlo... si se desea comprimir o empaquetar, el contenido de una carpeta,  si sería admisible que entre ese contenido hubiera ficheros .comp.
Imagina winrar para comprimir una carpeta y que deje fuera ficheros .rar que hubiere en esa carpeta, no es admisible, en cambio si verás que no deja 'recomprimir' un archivo .rar (si, si le 'engañas' cambiándole la extensión...).

...y bueno, no creo necesario más notas aclaratorias respecto del fichero reg... aunque no quita que algo se me pase...




9 - Cuando hagas copia del código del mensaje de más arriba, realmente puedes omitir, todas las llamadas a las funciones de más abajo, así no tienes porqué copiar, pegar y traducir a C (todas esa funciones), para probar el ejemplo (basta con), las líneas de llamada a dichas funciones pueden ser remplazadas por una salida a la consola, tal que así (añadimos 1 línea y por cada acción 2 líneas más y comentamos otra):

Código
  1.        console.writeline("Orden recibida: " & param  ' <<<<---------------------------
  2.        Select Case Param
  3.           ' ...
  4.           ' ...
  5.            Case "L", "LISTAR", "LIST"
  6.                For k = 1 To cmd.GetUpperBound(0)
  7.                    Param = cmd(k).ToUpper
  8.  
  9.                    If (Param.Contains("::")) Then
  10.                        SubParam = Param.Split(sepCommand, StringSplitOptions.RemoveEmptyEntries)
  11.                        If (SubParam.Length > 1) Then
  12.                            Param = SubParam(0) : Valor = SubParam(1)
  13.                        Else
  14.                            Param = "-"
  15.                        End If
  16.                    End If
  17.  
  18.                    console.writeline(vbtab & "Parametro recibido: " & param  & vbtab & "Valor: " & valor ' <<<<---------------------------
  19.                    Select Case Param
  20.                        Case "R", "RUTA"
  21.                            rutaOrg = Valor                            
  22.                        Case "D", "DESTINO"
  23.                            rutaDst = Valor
  24.                        Case "S", "SEPARADOR"
  25.                            separador = Valor
  26.                    End Select
  27.                    Valor = ""
  28.                Next    
  29.  
  30.                ' Esta orden, contiene todo lo necesario?
  31.                If (rutaOrg.Length > 0) Then
  32.                    ' Call ListarContenido(rutaOrg, separador, rutaDst)
  33.                      console.writeline("Aquí iría la ejecución d ela acción ' <<<<---------------------------
  34.                Else
  35.                    Call ShowAyuda(faltaParam & " /Ruta, es obligatorio para /Listar")
  36.                End If          
  37.  



Con respecto a lo que te señalaba Elektro, te aclaro que de cara a entender la línea de comandos, el código puesto más arriba conjuntamente con este fichero reg de ejemplo, es lo mejor que puede haber... porque así ves que se hace, cómo y porqué... sin embargo, aunque sea lo mejor para entender, no es lo mejor de cara al programador. Es decir, para cada programa tendrías que rescribir toda la operatoria, cada vez... si recurres a un objeto que empaquete todo esa operatoria y sea genérico (apto para cualquier programa), como la solución que mismamente Elektro te aporta en otro enlace, es mucho más óptimo cara a la 'progamación ágil'...

Aquí se emplean unas 200 líneas de código, mientras que usando un objeto, apenas serían unas 20... básicamente creas una instancia del objeto, al que se pasa el valor de 'commands' (o quizás el objeto sea capaz de interceptarlo por sí mismo, este punto es irrelevante), el objeto lo masca... y tu luego solo tienes un bloque select case donde evalúas el primer argumento (que al caso es la orden solicitada), y para cada caso, una llamada a la función donde se colocan el resto de argumentos, o bien se pasan todos como un paramArray, o como una colección, etc... según el diseño del objeto. Lo que efectivamente para esas 7 acciones distintas, se resumiría en poco más o menos que 20 líneas de código y además con bastante claridad y fáciles de mantener cuando surja la necesidad.

En resumen, diferencia el código puesto para entender y asimilar conceptos (que suele ser subóptimo, pués su cometido no es ese) y código óptimo para el rendimiento.


Olvidé adjuntar un par de imágenes, por lo demás obviables, pero por si alguien las necesita...

La siguiente imagen muestra, en 2 la línea de comando recibida, y en 1 los parámetros ya 'descompuestos' en el array...



La siguiente imagen muestra (en pasos demarcados), donde localizar el punto (en el IDe de VB), para ingresar la línea de comando cuando estamos en modo DEBUG...
« Última modificación: 29 Agosto 2018, 09:08 am por NEBIRE » En línea

rigorvzla

Desconectado Desconectado

Mensajes: 213


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #25 en: 29 Agosto 2018, 12:13 pm »

wooow , 21/10 puntos jejeje , gracias tengo material para leer analizar comprender para un buen rato muchas , MUCHISIMAS gracias  dudo que alla faltado algo, ya ahora me queda esperar los dias libres que vienen de esta semana y a leer con calma, gracias nuevamente por la ayuda prestada a ti y a Elektro feliz dia!! :D
En línea

rigorvzla

Desconectado Desconectado

Mensajes: 213


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #26 en: 2 Diciembre 2019, 00:53 am »

Antes de crear un nuevo tema probare por aqui, quiero saludar a todos nuevamente , ya que hace ya tiempo que publique este post y me fue de mucha ayuda.

Eh comprendido un tanto el manejo del registro desde C#, pero no eh logrado comprender lo siguiente, a pesar de estar en la ruta CLASS\ROOT donde estan todas las extensiones de los archivos, algunas extensiones carecen de la carpeta "shell", apesar de crearla y agregarle el comando que quiero , no se muestra en el menu contextual y no entiendo por que, por ejemplo quiero hacerlo con la extensión .mkv y solo me muestra las carpetas (OpenWithProgIds, ShellEx) y haga lo que haga creando manualmente la carpeta "shell" no funciona.

Si me pueden explicar el porque y que deberia hacer para lograrlo seria de mucha ayuda para mi.

NOTA: tengo instalado el reproductor VLC y este, crea en el registro una llave llamada VLC.mkv la cual SI tiene la carpeta "shell" , incluso le agregue mi menu y comando y se mostro, pero el asunto es que si el usuario NO tiene el VLC instalado, no funcionara, entocnes pense, como puedo registrar mi programa con las extensiones q quiero, de la misma manera que lo hace el VLC.

Espero sus respuestas y gracias de antemano.

MODIFICACION DE POST!
Probe la aplicacion en un sistema de windows limpio, y resulto interesante la prueba ya que al agregar la extensión ".7z" resulta que si me la toma, no me registra el icono de mi aplicacion en el archivo de dica extensión, pero si me aparece la accion en el menu contextual de dicho archivo, incluso lleva a cabo la accion cuando hago click.

La nueva pregunta es. Porque en el equipo donde estoy desarrollando la app y tengo instalado 7zip NO me registra la extensión y en cambio en la pc de prueba que esta limpia s(solo windows) SI me la registra, como puedo hacer para que me la visualize en un equipo que tenga instalado un programa que registre la misma extensión?
« Última modificación: 2 Diciembre 2019, 17:11 pm por rigorvzla » En línea

RayR

Desconectado Desconectado

Mensajes: 239


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #27 en: 4 Diciembre 2019, 00:20 am »

Creo que estás confundiendo algunas cosas, como registrar un tipo de archivo y registrar una aplicación que maneje ese tipo. No tengo tiempo para ver todo lo que te han escrito en este hilo, pero a forma de recordatorio o resumen, esto es lo mínimo necesario para agregar un programa a la lista "Abrir con" de un tipo de archivo.

Primero, no deberías modificar HKEY_CLASSES_ROOT. Leerla está bien, pero escribirla no se recomienda en los Windows modernos. Sólo deberías modificar HKEY_CURRENT_USER, para cambios que sólo apliquen al usuario actual; o HKEY_LOCAL_MACHINE, para los que apliquen de forma global. Windows automáticamente combina ambas para formar HKEY_CLASSES_ROOT, que se mantiene por motivos de compatibilidad. En este ejemplo supondré que quieres que los cambios apliquen a todos los usuarios.

Primero crea un ProgID por cada extensión que quieras manejar. Por ejemplo, suponiendo que tu programa se llama MyPlayer, para manejar los .mkv:

Código
  1. [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MyPlayer.mkv\shell\open\command]
  2. @="\"c:\\program files\\MyPlayer\\myplayer.exe\" \"%1\""

Luego, agregarlo a la extensión:

Código
  1. [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.mkv\OpenWithProgids]
  2. "MyPlayer.mkv"=hex(0):

Para agregar otra acción (verbo es el término oficial) como "Agregar a lista de reproducción", repites lo mismo del primer paso, pero en lugar de open, el verbo que quieras, por ejemplo: [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MyPlayer.mkv\shell\addtoplaylist\command]

Esto ya podría funcionar, pero si tienes más de una aplicación añadiendo verbos para ese mismo tipo de archivos desde el registro o se cambia la aplicación predeterminada para esa extensión, puede haber problemas, y quizás es lo que te pasa con 7-Zip. Para evitar eso puedes recurrir a la clave SystemFileAssociations, así:

Código
  1. [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\SystemFileAssociations\.mkv\shell\addtoplaylist]
  2. @="Agregar a lista de reproduccion"
  3.  
  4. [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\SystemFileAssociations\.mkv\shell\addtoplaylist\command]
  5. @="\"c:\\program files\\MyPlayer\\myplayer.exe\" -argumento \"%1\""
En línea

rigorvzla

Desconectado Desconectado

Mensajes: 213


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #28 en: 4 Diciembre 2019, 00:49 am »

muchs gracias!!! en efecto estoy modificando de manera directa la clas root, eso me sirve pero no me convece, por que si existen otros programas q asocian la misma extensión, hay problemas, entoces hare los pasos que me has dejado a lo ultimo a ver como me va, MCUHISIMAS GRACIAS!!! 
En línea

RayR

Desconectado Desconectado

Mensajes: 239


Ver Perfil
Re: Crear Menu Contextual Windows
« Respuesta #29 en: 4 Diciembre 2019, 05:36 am »

Debo aclarar que al decir que puede dar problemas no me refiero a que se vaya a producir un error ni nada por el estilo. Realmente no hay nada incorrecto en usar ProgIDs, y de hecho deberías hacerlo, pero si hay más de una aplicación registrada para manejar un tipo de archivo, es posible que los verbos de la tuya no se muestren si se dan ciertas condiciones, cosa que no sucede con SystemFileAssociations.
En línea

Páginas: 1 2 [3] 4 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
(Solucionado) Crear un archivo desde el menú contextual con contenido escrito?
Windows
Eleкtro 7 6,113 Último mensaje 24 Diciembre 2012, 16:53 pm
por Eleкtro
[BATCH] Menu contextual Windows Explorer
Scripting
r1v33 2 4,265 Último mensaje 7 Mayo 2012, 10:47 am
por r1v33
Crear nueva entrada en menú contextual de CREAR ARCHIVO TXT « 1 2 3 »
Windows
Esgrimidor 25 20,637 Último mensaje 30 Junio 2012, 08:26 am
por Eleкtro
Crear Imagen del sistema desde el Menú contextual
Windows
HenSil 3 3,974 Último mensaje 21 Febrero 2013, 15:27 pm
por HenSil
Crear carpetas y subcarpetas dentro del menú contextual « 1 2 »
Windows
zelarra 16 6,112 Último mensaje 9 Marzo 2024, 05:38 am
por Eleкtro
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines