Autor: elGuille

  • gsCompilarNET: una biblioteca de clases para compilar código de C# o VB

    Pues eso… intentando convertir la utilidad de Compilar y ejecutar a .NET 5.0 (Preview 8) me topé que (si no recuerdo mal) el .NET 5.0 no ofrece las clases para compilar (Microsoft.CodeDom.Providers.DotNetCompilerPlatform), así que… me puse a buscar en la web y me topé con un código de ejemplo (en C#) de Laurent Kempé que estaba escrito usando .NET Core 3.0 Preview 2.

    Me puse a copiar el código que tenía publicado en el artículo y lo modifiqué para crear un proyecto para .NET Core 3.1 que usara las clases de compilar y ejecutar (Compiler y Runner) desde otra clase estática que es la encargada de llamar compilar y ejecutar el código. Después descubrí que ese código lo tenía publicado en GitHub, pero en realidad ya lo tenía copiado/adaptado usando el código de su web.

    El problema inicial con el que me encontré es que solo compilaba código de C#, así que… lo modifiqué para que también compilara código de Visual Basic.

    En principio ese código solo compilaba/ejecutaba código de consola. Así que… tuve que modificarlo para que también compilara código de Windows Forms, eso sí, todo el código debía estar en un solo fichero.

    La respuesta a esto último que me dio la idea de cómo solucionarlo (o casi) la encontré en la red, pero no recuerdo en qué página, solo sé que era para ejecutar código de Visual Basic contenido en una base de datos, pero en realidad no era para código de Windows Forms, si no de consola, pero eso me sirvió para (además de agregar las referencias necesarias) poder crear el fichero json que necesita dotnet para crear el tipo adecuado de aplicación o usar las bibliotecas necesarias, la verdad es que tampoco me enteré demasiado… solo que haciéndolo, funcionaba 😉

    La cuestión es que conseguí hacer operativo el compilador para usar código de Visual Basic (y C#) tanto para consola como para formularios de Windows.

    Este es el código (o parte) que hace que esto sea posible:

            ' para ejecutar una DLL usando dotnet, necesitamos un fichero de configuración
            Dim jsonFile = Path.ChangeExtension(outputExe, "runtimeconfig.json")
            Dim jsonText = ""
            If compiler.EsWinForm Then
                Dim version = Compiler.WindowsDesktopApp().Version
                ' Aplicación de escritorio (Windows Forms)
                ' Microsoft.WindowsDesktop.App
                ' 5.0.0-preview.8.20411.6
                jsonText = "
    {
        ""runtimeOptions"": {
        ""tfm"": ""net5.0-windows"",
        ""framework"": {
            ""name"": ""Microsoft.WindowsDesktop.App"",
            ""version"": """ & version & """
        }
        }
    }"
            Else
                Dim version = Compiler.NETCoreApp().Version
                ' Tipo consola
                ' Microsoft.NETCore.App
                ' 5.0.0-preview.8.20407.11
                jsonText = "
    {
        ""runtimeOptions"": {
        ""tfm"": ""net5.0"",
        ""framework"": {
            ""name"": ""Microsoft.NETCore.App"",
            ""version"": """ & version & """
        }
        }
    }"
            End If
            Using sw = New StreamWriter(jsonFile, False, Encoding.UTF8)
                sw.WriteLine(jsonText)
            End Using
    

    Hoy me ha dado por convertir el código de C# (ya modificado y operativo) a Visual Basic y he creado un «repositorio» en GitHub con el código de la DLL que he creado para compilar código.

    También he publicado el código de la versión de C#, ya que actualmente tengo las dos versiones sincronizadas (es decir, los cambios y mejoras que he añadido en VB los he pasado al proyecto de C# y viceversa).

    Así que… si te interesa el código de esta DLL para compilar puedes descargarlo/verlo en el repositorio de GitHub para gsCompilarNET.

    Después publicaré también la utilidad de .NET 5.0 para Windows Forms que utiliza esa DLL (y la de gsColorearNET).

     

    Espero que te sea de utilidad. 🙂

    Nos vemos.
    Guillermo

    P.S.
    He publicado en NuGet la utilidad ya compilada por si quieres usarla en tus proyectos de Visual Studio (final o preview):
    gsCompilarNET en NuGet.

    P.S.2
    Esta es la pagina original de Compilar y ejecutar en elGuille.info (para .NET Framework 4.7.2 usando WPF).

  • Indicar a Visual Studio que al copiar texto lo haga con colores más enriquecidos (el RTF)

    Pues eso… Si usas el texto copiado de Visual Studio para después mostrarlo coloreado en una publicación en la WEB (un blog, etc.) este truco que te explico aquí te será de gran ayuda, ya que le indica que a demás de colorear el código «normal» (instrucciones, comentarios y cadenas entrecomilladas) también copie el color de los tipos.

    Esto lo utilizo con mi utilidad de colorear el código (gsColorearCodigo), concretamente usando la opción Colorear desde RTF del menú contextual de la caja de textos donde se pega el código a colorear.

    Y ( lo que decía ese párrafo anterior 🙂 ) antes, al copiar texto del editor de Visual Studio, éste me contenía los colores de los tipos de datos (verde azulado), pero últimamente no lo hacía, así que… esta mañana me puse a ver las opciones del editor de textos (realmente buscando otra cosa, todo hay que decirlo) y me topé con una opción que no era muy aclaratorio de que podía ser eso lo que lo solucionara: Usar clasificación precisa. Pero al estar justo debajo de Copiar texto enriquecido al copiar o cortar, pues… ¡tuve que probarlo! 😉

    Y eso es… aquí te dejo la nota «adicional» que puse en el post anterior en el que explico sobre la nueva versión de la utilidad de colorear código.

     

    Nota adicional sobre el coloreado de Visual Studio

    Comenté en el párrafo anterior que Visual Studio no pasa los colores de las clases (verde azulado) y antes lo hacía. ¿Lo habrán quitado?

    No, no lo han quitado.

    Y es que el que lo haga o no depende de una opción en la configuración del editor de textos de Visual Studio.

    Esa opción en español es: Usar clasificación precisa.
    En inglés es: Use accurate classification.

    Y con esos nombres… ¿Quién lo iba a saber?

    Para poder cambiar (activar) esa opción lo tienes que hacer en: (ver la captura)
    Herramientas>Opciones>Editor de textos>Avanzadas
    En inglés sería:
    Tools>Options>Text editor>Advanced

    Opción para que al copiar el código en Visual Studio coloree también las definiciones de los tipos

    Fíjate que también tiene que estar seleccionada la opción Copiar texto enriquecido al copiar o cortar (Copy rich text on copy/cut).

    Al pegar el texto coloreado, quedaría así:

    ''' <summary>
    ''' Devuelve la versión de la DLL.
    ''' Si completa es True, se devuelve también el nombre de la DLL:
    ''' gsColorear v 1.0.7.0 (para .NET Framework 4.7.2 revisión del dd/MMM/yyyy)
    ''' </summary>
    Public Shared Function Version(Optional completa As Boolean = False) As String
        Dim res = ""
        Dim ensamblado = System.Reflection.Assembly.GetExecutingAssembly
        'Dim m_fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(ensamblado.Location)
        'res = $"v {m_fvi.FileVersion}"
    
        Dim versionAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyVersionAttribute), False)
        'DirectCast(DirectCast(versionAttr, System.Reflection.AssemblyVersionAttribute())(0), System.Reflection.AssemblyVersionAt
        Dim vers = If(versionAttr.Length > 0, (TryCast(versionAttr(0), System.Reflection.AssemblyVersionAttribute)).Version,
                                          "1.0.7.0")
        Dim fileVerAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyFileVersionAttribute), False)
        Dim versF = If(fileVerAttr.Length > 0, (TryCast(fileVerAttr(0), System.Reflection.AssemblyFileVersionAttribute)).Version,
                                          "1.0.7.1")
    
        res = $"v {vers} ({versF})"
    
        If completa Then
            Dim prodAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyProductAttribute), False)
            Dim producto = If(prodAttr.Length > 0, (TryCast(prodAttr(0), System.Reflection.AssemblyProductAttribute)).Product,
                                            "gsColorear")
    
            res = $"{producto} {res} (para .NET Framework 4.7.2 revisión del 09/Sep/2020)"
        End If
        Return res
    End Function
    

     

    Nos vemos.
    Guillermo

  • Utilidad para colorear el código a mostrar en páginas WEB (gsColorearCodigo)

    Pues eso… si eres de los que no entran habitualmente en el sitio del Guille (www.elguille.info) y prefieres ver las cosas publicadas aquí en el blog, te diré que ayer publiqué la nueva versión de la utilidad gsColorearCodigo. Y digo NUEVA porque la actualización anterior que publiqué fue hace ya unos 13 añitos de nada 😉 y era para .NET 2.0, mientras que la nueva es para .NET Framework 4.8.

    Para facilitar la «coloración» del código a publicar en la WEB esta nueva versión permite copiar el código de Visual Studio, pegarlo en la ventana de la utilidad y generar el código HTML a partir del contenido RTF (ver la figura 1).

    Figura 1. La utilidad gsColorearCodigo usando Colorear desde RTF

    Esto tiene dos ventajas, la primera es que no es necesario que la utilidad analice el código fuente buscando palabras clave y comentarios, etc. Ya que lo único que tiene que hacer es convertir el código interno del formato RTF y convertirlo en etiquetas span.

    Además que al hacerlo así se gana tiempo… te lo digo por experiencia, ya que prácticamente todo el código coloreado que publico desde hace 12 o 13 años lo hago usando esa opción… así que… ya sabes… 😉

    Y para muestra, un código coloreado, precisamente el que usé para hacer la captura de la figura 1.

    Te lo vuelvo a mostrar en la captura de la figura 2, que es el editor de Visual Studio 2019.

    Figura 2. El código a copiar del editor de Visual Studio 2019

    Y este es el código HTML generado :

    ''' <summary>
    ''' Devuelve la versión de la DLL.
    ''' Si completa es True, se devuelve también el nombre de la DLL:
    ''' gsColorear v 1.0.7.0 (para .NET Framework 4.7.2 revisión del dd/MMM/yyyy)
    ''' </summary>
    Public Shared Function Version(Optional completa As Boolean = False) As String
        Dim res = ""
        Dim ensamblado = System.Reflection.Assembly.GetExecutingAssembly
        'Dim m_fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(ensamblado.Location)
        'res = $"v {m_fvi.FileVersion}"
    
        Dim versionAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyVersionAttribute), False)
        'DirectCast(DirectCast(versionAttr, System.Reflection.AssemblyVersionAttribute())(0), System.Reflection.AssemblyVersionAt
        Dim vers = If(versionAttr.Length > 0, (TryCast(versionAttr(0), System.Reflection.AssemblyVersionAttribute)).Version,
                                          "1.0.7.0")
        Dim fileVerAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyFileVersionAttribute), False)
        Dim versF = If(fileVerAttr.Length > 0, (TryCast(fileVerAttr(0), System.Reflection.AssemblyFileVersionAttribute)).Version,
                                          "1.0.7.1")
    
        res = $"v {vers} ({versF})"
    
        If completa Then
            Dim prodAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyProductAttribute), False)
            Dim producto = If(prodAttr.Length > 0, (TryCast(prodAttr(0), System.Reflection.AssemblyProductAttribute)).Product,
                                            "gsColorear")
    
            res = $"{producto} {res} (para .NET Framework 4.7.2 revisión del 09/Sep/2020)"
        End If
        Return res
    End Function
    

    En este caso, el VS no ha pasado los colores de los tipos (verde azulado), pero en otras ocasiones sí que lo hacía y quedaba guay, pero últimamente no le pasa los datos del color al código que utiliza de RTF… en fin…

     

    Nota adicional sobre el coloreado de Visual Studio

    Comenté en el párrafo anterior que Visual Studio no pasa los colores de las clases (verde azulado) y antes lo hacía. ¿Lo habrán quitado?

    No, no lo han quitado.

    Y es que el que lo haga o no depende de una opción en la configuración del editor de textos de Visual Studio.

    Esa opción en español es: Usar clasificación precisa.
    En inglés es: Use accurate classification.

    Y con esos nombres… ¿Quién lo iba a saber?

    Para poder cambiar (activar) esa opción lo tienes que hacer en: (ver la captura)
    Herramientas>Opciones>Editor de textos>Avanzadas
    En inglés sería:
    Tools>Options>Text editor>Advanced

    Opción para que al copiar el código en Visual Studio coloree también las definiciones de los tipos

    Fíjate que también tiene que estar seleccionada la opción Copiar texto enriquecido al copiar o cortar (Copy rich text on copy/cut).

    Al pegar el texto coloreado, quedaría así:

    ''' <summary>
    ''' Devuelve la versión de la DLL.
    ''' Si completa es True, se devuelve también el nombre de la DLL:
    ''' gsColorear v 1.0.7.0 (para .NET Framework 4.7.2 revisión del dd/MMM/yyyy)
    ''' </summary>
    Public Shared Function Version(Optional completa As Boolean = False) As String
        Dim res = ""
        Dim ensamblado = System.Reflection.Assembly.GetExecutingAssembly
        'Dim m_fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(ensamblado.Location)
        'res = $"v {m_fvi.FileVersion}"
    
        Dim versionAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyVersionAttribute), False)
        'DirectCast(DirectCast(versionAttr, System.Reflection.AssemblyVersionAttribute())(0), System.Reflection.AssemblyVersionAt
        Dim vers = If(versionAttr.Length > 0, (TryCast(versionAttr(0), System.Reflection.AssemblyVersionAttribute)).Version,
                                          "1.0.7.0")
        Dim fileVerAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyFileVersionAttribute), False)
        Dim versF = If(fileVerAttr.Length > 0, (TryCast(fileVerAttr(0), System.Reflection.AssemblyFileVersionAttribute)).Version,
                                          "1.0.7.1")
    
        res = $"v {vers} ({versF})"
    
        If completa Then
            Dim prodAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyProductAttribute), False)
            Dim producto = If(prodAttr.Length > 0, (TryCast(prodAttr(0), System.Reflection.AssemblyProductAttribute)).Product,
                                            "gsColorear")
    
            res = $"{producto} {res} (para .NET Framework 4.7.2 revisión del 09/Sep/2020)"
        End If
        Return res
    End Function
    

     

    Lo que si hace es usar la coloración de las cadenas con los argumentos de las cadenas interpoladas (las que se usan poniendo un signo dólar delante del inicio de las comillas dobles) que utiliza la coloración de Visual Studio, mientras que si lo haces con el comando Colorear en HTML, todo el contenido de la cadena estaría de color rojo, tal como puedes ver a continuación.

            res = $"{producto} {res} (para .NET Framework 4.7.2 revisión del 09/Sep/2020)"
        End If
        Return res
    End Function
    

    Aunque con la utilidad puedes configurar los colores y usar Colorear en HTML y mostrar el código con el look ese que tanto le gusta a «los otros» 😉

    ''' <summary>
    ''' Devuelve la versión de la DLL.
    ''' Si completa es True, se devuelve también el nombre de la DLL:
    ''' gsColorear v 1.0.7.0 (para .NET Framework 4.7.2 revisión del dd/MMM/yyyy)
    ''' </summary>
    Public Shared Function Version(Optional completa As Boolean = False) As String
        Dim res = ""
        Dim ensamblado = System.Reflection.Assembly.GetExecutingAssembly
        'Dim m_fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(ensamblado.Location)
        'res = $"v {m_fvi.FileVersion}"
    
        Dim versionAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyVersionAttribute), False)
        'DirectCast(DirectCast(versionAttr, System.Reflection.AssemblyVersionAttribute())(0), System.Reflection.AssemblyVersionAt
        Dim vers = If(versionAttr.Length > 0, (TryCast(versionAttr(0), System.Reflection.AssemblyVersionAttribute)).Version,
                                          "1.0.7.0")
        Dim fileVerAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyFileVersionAttribute), False)
        Dim versF = If(fileVerAttr.Length > 0, (TryCast(fileVerAttr(0), System.Reflection.AssemblyFileVersionAttribute)).Version,
                                          "1.0.7.1")
    
        res = $"v {vers} ({versF})"
    
        If completa Then
            Dim prodAttr = ensamblado.GetCustomAttributes(GetType(System.Reflection.AssemblyProductAttribute), False)
            Dim producto = If(prodAttr.Length > 0, (TryCast(prodAttr(0), System.Reflection.AssemblyProductAttribute)).Product,
                                            "gsColorear")
    
            res = $"{producto} {res} (para .NET Framework 4.7.2 revisión del 09/Sep/2020)"
        End If
        Return res
    End Function

    Por si te interesa, aquí tienes los colores a usar y el valor de «pre» para conseguir ese coloreado del código:

    Tag del formato <pre>:
    <pre style=»background-color:black; color:#dcdcdc»>
    Color texto: d69d85
    Color comentario: 57a64a
    Color documentación (XML): 57a64a
    Color instrucciones: 569cd6

    Bueno, no te canso más… espero que te sea de utilidad y la uses si necesitas colorear código para publicar en una sitio web.

    El código fuente y el instalador de ClickOnce lo encontrarás en la página que publiqué en elGuille.info.

    Este es el enlace para instalar la utilidad con ClickOnce y este otro es para que veas la página de la utilidad gsColorearCodigo en elguille.info.

     

    ¡Hasta pronto y que lo colorees bien! 🙂

     

    Nos vemos.
    Guillermo

    P.S.
    Ahora que veo el código publicado… no queda mal el fondo negro con el resto de colores… lo mismo modifico la utilidad de colorear para que al colorear desde RTF utilice esos colores en vez de los «predeterminados», que yo creo que son los que recoge del código RTF de Visual Studio, pero lo mismo es fácil de cambiarlos.
    Si lo logro, ya te enterarás con una nueva actualización 😉