Everything: Una herramienta productiva.

17 11 2009

Existe una multitud de herramientas, plugins para Visual Studio, editores, y demás que nos asisten a la hora de desarrollar. Yo particularmente soy amigo de las más sencillas, ya bastante con aprender todos los vericuetos del entorno.

Entre estas herramientas que me “conquistaron”, la que más me gusta es Everything, Un buscador de archivos. No hace nada que no se pueda hacer con Windows o con muchas otras herramientas que realizan la misma tarea y ofrecen mucha más funcionalidad, básicamente escribimos partes del nombre del cualquier archivo separadas por espacios y nos muestra una lista de todos los que coinciden con el patrón buscado.

¿Por que vale la pena entonces? El secreto de Everything es que lo que hace lo hace bien, es gratis (vale donar ¡eh!), consume escasos recursos y es muy, muy, MUY rápido.

Busqueda en Everything

El secreto: Respuesta inmediata.

Para ser claro, a la pulsación de cada tecla tendremos nuestra lista de archivos filtrada. Para escanear todo el disco rígido por primera vez solo tarda unos segundos, y los cambios que se hagan a los archivos, afectan los resultados de Everything en tiempo real.

Ahora, si trabajan en proyectos con cientos o miles de archivos créanme que con un poco de uso de Everything se van a olvidar de navegar por árboles infinitos de carpetas y listas interminables de archivos. Abrir un archivo en Visual Studio se convierte en activar el Everything con un shortcut, escribir unas letras y presionar enter.

Unos pocos tips para su uso:

  • Incluirlo entre los programas de inicio, pesa muy poco e inicia sin que lo notemos.

    Setear HotKey

    La única configuración necesaria: el HotKey.

  • Setear un shortcut, no viene por defecto y es uno de los secretos para su uso, yo uso Windows + S. (Se agrega en: Tools – General – New Windows HotKey Modifier / Key)
  • Excluir las carpetas sobre las que no queremos resultados: (Tools – Exclude / Volumes)
  • Si queremos buscar dentro de una carpeta específica, la escribimos antes del nombre del nombre del archivo seguida de barra invertida. (“MiProyecto\  app.config”)
  • Si trabajan con varios entornos abiertos, asegurensé de tener el foco sobre el que quieren abrir el archivo buscado antes de activar Everything.

¡Extra, Extra!

Everything tiene como extra unas pocas pero poderosas funcionalidades.

Permite exponer un disco o carpetas seleccionadas con Everything actuando como un mini web server, pudiendo hacer busquedas desde otra máquina mediante un browser ¡y bajarse los archivos encontrados!

Podemos exponer parte de nuestros archivos por HTTP. ¡Usar con responsabilidad!

Posee un protocolo propio (ETP: Everything Transfer Protocol) que nos permite setear una instancia Everything como servidor y utilizar otras como clientes de búsqueda, con la misma funcionalidad que usándolo en forma local. Fantástico.

Si quieren hilar fino se puede configurar para usar Regular expressions, permite exportar a un archivo de texto la lista de archivos encontrados, y tiene multiplicidad de opciones que vienen configuradas como para no tener que tocarlas.

Asique ya saben, basta del perro de XP y de la (mucho mejor pero igualmente) no muy efectiva barra de búsqueda de Vista, no tienen nada que hacer al lado de Everything. Después me cuentan.

links: Everything





Atachar procesos automáticamente con macros de Visual Studio

16 07 2008

La manera de atachar un proceso a Visual Studio es clasicamente mediante ‘Debug – Attach to process’ o el más productivo Ctrl + Alt + P, y luego seleccionar el o los procesos que querramos depurar.

En desarrollos medianamente importantes es muy probable que debamos realizar este procedimiento repetidas veces para depurar un proyecto fuera de la interface de usuario, expuesto mediante una capa de servicios, llámese WS, remoting, WCF, etc. Ni hablar del worker process de ASP.NET,  ‘aspnet_wp.exe’. También es común que corramos un proyecto desde fuera del Visual Studio para evitar la compilación, y luego lo atachemos al IDE.

Entonces, si los procesos que atachamos son siempre los mismos, ¿por que no automatizar la tarea?, bueno, la solución que propongo es una macro de Visual Studio que haga este trabajo, atachando con un atajo de teclado todos los procesos que sean necesarios.

Para incluirla en VS, vamos al editor de macros (Alt + F11), agregamos un nuevo módulo y reemplazamos el contenido por el siguiente:

Imports System.Collections.Generic
Imports EnvDTE
Imports EnvDTE80
Imports System.Text

Public Module DebugMacros

    Private Enum EnumAction
        ResultOK
        ReRunWithDisatach
        Abort
    End Enum

    Public Sub AttachProcs()
        Dim ProcessList As New List(Of String)
        ProcessList.Add("InterfaceUsuario.exe")
        ProcessList.Add("MiServiceLayer.exe")
        AttachProcs(False, ProcessList)
    End Sub

    Private Sub AttachProcs(ByVal detachAll As Boolean, ByVal ProcessList As List(Of String))

        If detachAll Then DTE.Debugger.DetachAll()

        Dim isOK As EnumAction = EnumAction.ResultOK
        Dim sbErrorResult As New StringBuilder

        For Each proc As String In ProcessList
            Dim match As Boolean = False
            For i As Integer = 1 To DTE.Debugger.LocalProcesses.Count
                If DTE.Debugger.LocalProcesses.Item(i).Name.EndsWith(proc) Then
                    match = True
                    Exit For
                End If
            Next
            If Not match Then
                sbErrorResult.Append("El proceso '" + proc + "' no se está ejecutando." + vbCrLf)
                isOK = EnumAction.Abort
            End If
        Next

        If isOK = EnumAction.ResultOK Then
            'Desatacho todos los procesos
            Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
            Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
            Dim dbgeng(1) As EnvDTE80.Engine
            dbgeng(0) = trans.Engines.Item("Managed")
            Dim proc2 As EnvDTE80.Process2
            For Each processName As String In ProcessList
                Try
                    proc2 = dbg2.GetProcesses(trans, ".").Item(processName)
                    proc2.Attach2(dbgeng)
                Catch ex As Exception
                    If ex.Message.EndsWith("8971001E") Then
                        sbErrorResult.Append("Error atachando " + processName + ". " + "El proceso ya se encuentra atachado" + vbCrLf)
                        isOK = EnumAction.ReRunWithDisatach
                    Else
                        sbErrorResult.Append("Error inesperado atachando " + processName + ". " + ex.Message + vbCrLf)
                        isOK = EnumAction.Abort
                    End If
                End Try
            Next
        Else
        End If

        Select Case isOK
            Case EnumAction.Abort
                DTE.Debugger.DetachAll()
                MsgBox(sbErrorResult.ToString + vbCrLf + "No se ha atachado ningún proceso", MsgBoxStyle.OkOnly, "Error al atachar proceso")
            Case EnumAction.ReRunWithDisatach
                If MsgBox("Hay procesos previamente atachados. ¿Desea reatacharlos?", _
                                    MsgBoxStyle.YesNo, "Atachar Proceso") = MsgBoxResult.Yes Then
                    AttachProcs(True, ProcessList)
                    Exit Sub
                End If
            Case EnumAction.ResultOK
                Dim Resultado As New StringBuilder
                For Each s As String In ProcessList
                    Resultado.Append(s + vbCrLf)
                Next
                MsgBox("Se han atachado los siguientes procesos: " + vbCrLf + Resultado.ToString, MsgBoxStyle.OkOnly, "Proceso atachados")
        End Select
    End Sub

End Module

Observar que en AttachProcs() hay una colección con los nombres de los procesos la cual hay que editar de acuerdo a nuestras necesidades.

Ahora solo falta asignarle una combinación de teclas, desde Tools – Options – Keyboard, filtramos por “Macro” o “AtachProcs” y una vez ubicada la macro le asignamos una combinación de teclas.

Ahora solo basta correr los procesos por fuera de Visual Studio y atacharlos con la combinación de teclas.

Si el código encuentra alguno de los procesos atachado, desatacha todos los procesos e intenta nuevamente.

Nota: Este simple código está hecho a partir de la grabadora de macros (Tools – Macros – Record Temporary Macro), recordemos que todo lo que hacemos en VS queda registrado en la grabadora y que casi todo en el entorno es un objeto que se puede manipular.





Depurar sin complicarnos la vida utilizando Debugging Attributes

29 05 2008

Cuando depuramos con Visual Studio es un verdadero fastidio el hecho de tener que entrar a todos los métodos o propiedades que se encuentran dentro de una llamada, por ejemplo:

void MiMétodo(DameUnString())
{
   //algo acá que si quiero depurar
}
String DameUnString()
{
   //¡No quiero depurar esto!
   return "Este es tu String!";
}

DebuggerStepThrough y DebuggerHidden

Cuando se trabaja en cualquier sistema medianamente complejo es muy molesto depurar código como el anterior ya que no hay manera en VS de indicar que queremos ir directamente al cuerpo del método que estamos por depurar, sin entrar a cada parámetro.

Lo mismo ocurre cuando presionamos por error F11 en vez de F10 y entramos a un interminable método que nos obliga a poner un break al final (y luego a quitarlo para no parar nuevamente)

Una solución parcial pero util son los atributos DebuggerStepThrough y DebuggerHidden.

Poniendo DebuggerHidden a un método logramos que Visual Studio no pase nunca por el método:

[System.Diagnostics.DebuggerHidden]
String DameUnString(){...}

hará que nunca depuremos el método DameUnString.

En cambio con el más util DebuggerStepThrough, el entorno se detiene en el método si colocamos un break, pero no de otra manera.

Realmente sería más util una tecla para “Avanzar StepThrough”, incluso por ahí he visto una solicitada para su inclusión en VS…pero esta es la solución parcial que tenemos disponible.

DebuggerBrowsable y DebuggerDisplay

Por defecto VS nos permite ver los miembros privados de las clases y estructuras que escribimos al momento de depurarlas. Si bien esto puede ser util, cuando la clase es un contenedor de datos, no es práctico disponer de esta información que está expuesta nuevamente en las propiedades públicas. Ni hablar si nuestra clase va a ser expuesta a terceros.

Por ejemplo si depuramos una clase “Persona” con tres propiedades vemos en la ventana de Watch una molesta duplicación de datos:

El atributo DebuggerBrowsable nos permite especificar que no se deben mostrar en el depurador los métodos, miembros o propiedades decorados con el mismo.

DebuggerDisplay, a su vez, nos permite especificar el texto a mostrar en la columna value de las ventanas de depuración. En la cadena que nos pide podemos especificar entre llaves “{}” código ejecutable, pero la mejor manera de entender esto es ver un ejemplo. Si la clase de la imagen anterior estuviera declarada de la siguiente manera:

[DebuggerDisplay("{this.GetType().ToString(),nq} ({_nombre,nq} {_apellido,nq}, {_edad} años)")]
public struct Persona {...}

(nq significa “No Quotes”, para quitar las comillas de las cadenas)

y los miembros privados estuvieran decorados así:

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Int32 _edad;

Entonces lo que veríamos en la ventana de Watch sería:

Mucho más claro si tenemos en cuenta que el tipo persona lo escribiremos una sola vez pero lo depurarán por miles de años.

Hay otros atributos de debugging que permiten desde wrappear en otra clase lo que se va a mostrar al depurar, hasta implementar un viewer customizado para un tipo, como el que Visual Studio trae para el DataSet.

Nota: No olvidar que estos atributos pertenecen al namespace System.Diagnostics, por lo que hay que agregar el correspondiente using/Imports.