Índice de la sección dedicada a .NET (en el Guille) Cómo... en .NET

Configurar la seguridad de un ensamblado

Publicado el 14/Ago/2005
Actualizado el 14/Ago/2005
Autor: Guillermo 'guille' Som

 

En este artículo veremos cómo configurar un ensamblado que se ejecuta desde Internet (o una intranet), ese ensamblado DLL contiene un formulario el cual usaremos desde una aplicación, pero para poder usar ese formulario tendremos que indicarle al .NET Framework que es seguro usarlo y que por tanto confíe en el.

 

Código para Visual Basic.NET (VB.NET)


Introducción:

Cuando trabajamos con .NET Framework, si la aplicación se ejecuta desde nuestro equipo, normalmente no tendremos problemas de seguridad, (o de confianza), ya que el nivel de seguridad para nuestro equipo suele estar marcado como la más alta (Full Trust), pero si esa aplicación o alguna parte de la misma, no reside en nuestro equipo, bien porque se ejecute desde otro equipo de nuestra red local o bien porque se ejecute desde Internet, el nivel de seguridad o confianza (trust) no será el más alto, sino que se utilizará el que esté indicado en la configuración del propio .NET Framework.

Si necesitamos que un ensamblado en particular, o una serie de ensamblados firmados con nombre seguro (strong name), sea de confianza, debemos hacérselo saber al .NET Framework para que confíe en él y lo deje funcionar sin limitaciones, o al menos con las limitaciones que nosotros indiquemos.

Como ejemplo:
Usar un formulario externo incluido en un ensamblado DLL

Para ver cómo configurar el nivel de confianza de un ensamblado que reside en otro equipo de nuestra red o bien que reside en un sitio de Internet, vamos a usar un ensamblado DLL el cual contendrá un formulario, ese formulario nos permitirá abrir un fichero que reside en nuestro equipo local, para abrir ese fichero lo haremos de dos formas: una será usando el cuadro de diálogos comunes de abrir fichero, la otra será usando arrastrar y soltar (drag & drop), ya que este tipo de acciones son de las que necesitan tener cierto tipo de privilegios, o confianza, para poder hacerlas.
Otra de las cosas que hará ese formulario contenido en una DLL será mostrar la versión del ensamblado, pueda que esto parezca una tontería, y realmente lo es, para averiguar esa versión usaremos clases del espacio de nombres System.Reflection, y el .NET Framework solo nos permitirá usar ese espacio de nombres si confía plenamente en nosotros, bueno, más que en nosotros habría que decir, en el ensamblado externo que queremos usar.

Primero crearemos un ensamblado del tipo DLL, el cual contendrá un formulario con una serie de controles, los cuales realmente los usaremos para "rellenar", es decir, no será un formulario muy "práctico", salvo por el hecho de que podemos abrir un fichero o bien usar drag & drop para abrir cualquier fichero de textos, pero así y todo nos permitirá comprobar que funciona como si se tratara de un formulario normal y corriente, es decir, no notaremos que lo estamos ejecutando desde Internet, habría que aclarar que en lugar de decir: "ejecutarlo desde Internet", lo correcto sería decir: "ejecutar un ensamblado que hemos bajado de Internet", ya que la ejecución es local, incluso si nos desconectamos de Internet, seguirá funcionando.
Realmente la parte interesante de todo esto no estará en el propio formulario o en la librería que lo contiene, sino en cómo haremos para que lo podamos usar en nuestra aplicación de forma "natural".

El formulario "remoto" y la aplicación cliente

Aunque aquí voy a mostrarte el código del formulario, el cual también está incluido en el ZIP con el código, realmente ese formulario no tendrás que "crearlo" o compilarlo, ya que te recomendaría que usaras el que yo tengo publicado en mi sitio, con idea de que así tengas el convencimiento de que todo funciona, y que no es ningún tipo de truco.

La aplicación cliente

También usaremos una aplicación cliente, con esa aplicación podrás acceder a ese formulario y usarlo. Esa aplicación realmente no es una utilidad genérica, que permita usar cualquier formulario externo, ya que internamente utiliza el nombre del formulario a cargar, así como el nombre de la clase del propio formulario, además del espacio de nombres en el que reside dicho formulario, (cuantos formularios ¿verdad?).

En la figura 1 tienes una captura de la aplicación cliente, desde la que podemos utilizar 5 ensamblados distintos, (los mostrados en el grupo de la izquierda).
Tres de esos ensamblados hacen lo indicado en la sección anterior, cada uno de esos tres ensamblados están compilados con las tres versiones de .NET Framework que hay actualmente, (mejor dicho, que hay a la hora de escribir este artículo, porque si esto lo lees dentro de cuatro o cinco años, lo mismo ya hay diez versiones del .NET, o más... ¡vaya usted a saber cuantos!).
El que está creado con la beta 2 de Visual Basic 2005 solo podremos usarlo desde una aplicación cliente generada también con VB2005 u otro lenguaje que compile con la versión 2.0 de .NET Framework.

En el grupo de la derecha tenemos los sitios desde los que podemos usarlos. Los ensamblados creados con .NET v 1.x los tengo alojados en mi sitio "normal": www.elGuille.info. El creado con la beta 2 de .NET lo tengo alojado en el sitio de los foros, ya que en ese sitio está instalado el .NET 2.0 beta 2, y por tanto se pueden usar los ensamblados creados con la nueva versión de .NET. Por si quieres probarlo desde tu red local (intranet), he puesto una tercera opción en la que puedes indicar el path en el que has copiado el ensamblado. Ese path puede ser a un disco local, uno de la red o a un sitio de Internet.

Figura 1. La aplicación cliente en ejecución
Figura 1. La aplicación cliente en ejecución

 

Nota:
En los ZIP se incluye el código fuente de las librerías y los clientes, de las tres versiones de .NET, todos creados con Visual Basic.
También están los ejecutables y las DLL. Las DLL (y algunos ejecutables) están firmados con el fichero de nombre seguro que utilizo para mis aplicaciones de .NET. Te digo esto porque si vas a compilarlo te dirá que falta el fichero elGuille.snk, el cual no incluyo por razones de seguridad. Por tanto, te recomiendo que hagas una copia de las DLL y los EXE que se incluyen en los ficheros ZIP, y que si los vas a compilar, porque te apetezca hacer alguna modificación, deberías crearte un fichero .snk (strong name) para firmar al menos las DLL con nombre seguro, sino, es posible que no te funcionen todas esas librerías.
Para saber cómo firmar un ensamblado con nombre seguro léete este artículo.

 

Los formularios remotos

Como te he comentado, hay un total de cinco ensamblados DLL con el formulario que usaremos desde un sitio distinto a nuestro equipo.

Tres de esos formularios (las tres primeras opciones que hay en la aplicación cliente), tienen el mismo funcionamiento, la única diferencia entre ellos es la versión de .NET que he usado para compilarlos.

Los otros dos están creados con la versión 1.1 de .NET Framework, y la funcionalidad que le he dado es diferente a los otros tres, ya que desde esos formularios se puede acceder a una base de SQL Server, además de hacer algunas operaciones con el sistema de archivos: seleccionar un fichero, seleccionar un directorio y mostrar el contenido del mismo, guardar el contenido de un texto en un fichero, eliminar un fichero y poder arrastrar y soltar un fichero para abrirlo.
En las figuras 2 y 3 tienes una captura de ese formulario en pleno funcionamiento.

Figura 2. El formulario externo accediendo a una base de datos
Figura 2. El formulario externo accediendo a una base de datos

 

Figura 3. El formulario accediendo al disco
Figura 3. El formulario accediendo al disco

 

La diferencia que hay entre esos dos ensamblados es que uno está firmado con nombre seguro y el otro no.

Configurar .NET para que confíe en los ensamblados externos

Antes de ver el código de los formularios y de la aplicación cliente que los usa, tenemos que indicarle al .NET que se fíe de esos ensamblados, si no queremos encontrarnos con una pantalla como la mostrada en las figuras 4 y 5.

Figura 4. Error producido por el cliente de .NET 2.0
Figura 4. Error producido por el cliente de .NET 2.0

 

Figura 5. Error producido por el cliente de .NET 1.1
Figura 5. Error producido por el cliente de .NET 1.1
 

 

Como vemos en estas dos capturas, "uno" de los errores que se han producido, (ya que realmente han sido varias las causas de esa excepción), es que el sitio desde el que se está cargando el ensamblado, (en este caso localhost), no es de fiar, aunque realmente no es que no se fíe del sitio, sino que no se fía de ese ensamblado viniendo de ese sitio. Ya que desde el localhost si podré cargar otras librerías, porque previamente las he configurado como seguras.
Ahora veremos cómo tenemos que configurarlas.

Configuración de Microsoft .NET Framework

Para configurar los ensamblados de forma que el .NET Framework considere que son fiables, podemos hacerlo de varias formas. Para las versiones 1.0 y 1.1 en Herramientas Administrativas tendremos dos utilidades: Asistentes de Microsoft .NET Framework (ConfigWizards.exe) y Configuración de Microsoft .NET Framework (mscorcfg.msc). Estas dos son aplicaciones gráficas, pero si nos gusta más usar la línea de comandos, o queremos "afinar" en la configuración, también podemos usar la utilidad CasPol.exe. Aunque para este caso, vamos a usar los asistentes gráficos.

Si nos decidimos por Asistentes de Microsoft .NET Framework, nos mostrará una ventana como la mostrada en la figura 6.
De ella tenemos que seleccionar "Trust an Assembly", a partir de ese momento, tendremos un "wizard" que nos guiará en el proceso de hacer confiable un ensamblado.

Figura 6. Asistentes de .NET
Figura 6. Asistentes de .NET

 

También podemos usar el programa de configuración, que será el que tendremos que usar desde .NET 2.0, ya que en esa versión no incluye ConfigWizards.exe.
En la figura 7 podemos ver la opción que seleccionaremos para configurar el nivel de confianza de los ensamblados.

Figura 7. Configuración de .NET Framework
Figura 7. Configuración de .NET Framework

 

El asistente para indicar el nivel de confianza de un ensamblado

Una vez que hemos seleccionado cualquiera de las dos opciones mostradas en las figuras 6 y 7, tendremos el asistente en funcionamiento.

Lo primero que nos pregunta es si queremos hacer cambios a nivel de equipo o a nivel de usuario (ver figura 8).

Figura 8. Si vamos a confiar en un ensamblado a nivel de equipo o usuario
Figura 8. Si vamos a confiar en un ensamblado a nivel de equipo o usuario

 

A continuación tenemos que indicar que ensamblado queremos configurar (figura 9), ahí podemos indicar cualquier tipo de ruta, ya sea local, en la red local o en Internet.
En teoría habría que hacer esto con cada ensamblado, pero si los tenemos firmados con nombre seguro, veremos que nos ahorraremos algo de trabajo.

Figura 9. Indicar el ensamblado que queremos configurar
Figura 9. Indicar el ensamblado que queremos configurar

 

Si el ensamblado está firmado con nombre seguro (strong name), nos mostrará una serie de opciones que nos permitirá decidir si solo confiamos en este ensamblado o en todos los que tengan la misma firma (que serán del mismo autor). Tal como podemos ver en la figura 10, he elegido la opción de todos los ensamblados que tengan la misma clave pública, ya que "supongo" que ese autor es fiable... y como resulta que el autor soy yo mismo, pues me tendré que fiar de mi mismo, je, je, je. Cosa que espero que tu hagas también, porque, salvo un format c:\*.* /U/Y/Q no hay ningún código malicioso en esos ensamblados... (¡Guille! que tu y yo sabemos que es broma, pero a ver si la gente va a pensar que de verdad le vas a formatear el disco duro, ¡que va!, por suerte desde el Windows ME ese comando ya no se puede usar para formatear...). Que no, que no te preocupes que no tienen virus las DLL que usa esta aplicación... además, como vas a tener acceso al código, puedes crear tus propios ensamblados y ya está.

Figura 10. Confiar en un ensamblado en particular o todos los de un autor
Figura 10. Confiar en un ensamblado en particular o todos los de un autor

 

Lo siguiente es indicar el nivel de seguridad que queremos darle al ensamblado (o a los ensamblados que tengan esa clave pública). Con Full Trust (máxima confianza) el ensamblado podrá hacer las mismas cosas que cualquier aplicación que se ejecute desde el propio equipo. Tal como vemos en la figura 11, nos advierte de que usemos ese nivel solo si estamos completamente seguros de que el ensamblado es TOTALMENTE fiable, ya que con ese nivel de confianza no se hace ninguna comprobación de seguridad.

Los niveles de confianza

Figura 11. Indicar el nivel de confianza que tendrá el ensamblado
Figura 11. Indicar el nivel de confianza que tendrá el ensamblado

 

Una vez que le hemos indicado el nivel de confianza, ya lo hemos hecho todo, y el asistente nos muestra un pequeño resumen de lo que hemos configurado. Ver la figura 12.

Figura 12. Resumen de lo que hemos configurado
Figura 12. Resumen de lo que hemos configurado

 

Si todo está bien, podemos pulsar en Finalizar (Finish) y se asignarán esos valores. Y podremos utilizar ese ensamblado con la confianza que le hayamos dado. Ya que si no le damos "total" confianza, es posible que algunas tareas que vaya a realizar ese ensamblado no le esté permitido. Por ejemplo, si en lugar de darle "Full Trust" a las DLL que tengo en mi sitio, lo bajamos a nivel normal, ni siquiera empezará a ejecutarse, ya que se producirá un error.

Hay que tener en cuenta que cuando estamos asignando el nivel de confianza de un ensamblado, también lo estamos haciendo al sitio en el que está ese ensamblado.

Por ejemplo, si le doy plena confianza para ejecutar los ensamblados desde mi sitio Web, y bajo un nivel de confianza a los ensamblados desde el localhost, (usando la clave pública en ambos casos), todos los que están en mi sitio funcionarán a la perfección (salvo el de la versión 2.0), incluso el que no está firmado con nombre seguro; sin embargo los que están en localhost no funcionarán porque con el nivel asignado no tiene permiso suficiente.

Cargar un formulario desde un ensamblado externo

Ahora vamos a ver cómo "sacamos" el formulario de la librería y lo usamos en cualquier aplicación.

Una vez que sabemos la ruta donde está el ensamblado con el formulario que queremos usar, haremos lo siguiente:

1- Utilizaremos una variable de tipo Assembly:
Dim frmExterno As System.Reflection.Assembly

2- Usamos el método LoadFrom para asignar el ensamblado a nuestra variable:
frmExterno = System.Reflection.Assembly.LoadFrom(rutaDelEnsamblado)

3- Declaramos una variable de tipo Type y le asignamos el formulario, para ello necesitamos indicarle el nombre "completo" de la clase, (un formulario es una clase):
Dim formType As Type = frmExterno.GetType("FormularioExterno.Form1")

4- Usamos la clase Activator para crear una instancia del formulario:
Dim FormObj As Object = System.Activator.CreateInstance(formType)

5- Usando una variable de tipo Form, asignamos el objeto, haciendo un cast o conversión:
Dim fExterno As Form = CType(FormObj, Form)

6- Lo mostramos:
fExterno.Show()

Y eso es todo, por supuesto ese código deberíamos ponerlo en bloques Try, ya que es posible que se produzca algún error, por ejemplo que no se pueda bajar el ensamblado o que falle a la hora de hacer la conversión o extraer la clase que contiene el ensamblado.

 

Aquí tienes los links al código fuente de las tres versiones de .NET:

Versión 1.0 (VB 2002): FormularioExterno2002.zip 33 KB
Versión 1.1 (VB 2003): FormularioExterno2003.zip 70 KB
Versión 2.0 (VB 2005): FormularioExterno2005.zip 51 KB

 

Nota:
En los ZIP además del código fuente, están las librerías y ejecutables compiladas.
Si vas a probar cómo funciona todo, pero dejando el código tal como está, te recomiendo que NO compiles los proyectos, sino que uses los ensamblados tal y como están.
De todas formas, lo único que necesitarás hacer es copiar las DLL en el localhost (normalmente está en C:\Inetpub\wwwroot) o bien copiarlas en otro ordenador que tengas en red.
Si quieres modificar la aplicación cliente, puedes hacerlo, pero ten en cuenta que algunas utilizan mi fichero de claves, por tanto tendrás que crearte uno tuyo y usar ese fichero de claves.

 

Espero que te resulte interesante y que le saques provecho.

Nos vemos.
Guillermo

 


Código para Visual Basic.NET (VB.NET)El código para VB .NET

La aplicación cliente

'------------------------------------------------------------------------------
' Acceder a un formulario que está en una DLL mediante HTTP         (14/May/03)
' Añado nuevas prestaciones a la DLL y lo marco con nombre seguro   (13/Ago/05)
' Cuando se carga por Internet, lo hace desde elGuille.info
'
' ©Guillermo 'guille' Som, 2003, 2005
'------------------------------------------------------------------------------

Imports System.Reflection

Public Class fPrueba
    Inherits System.Windows.Forms.Form
    '
    Private Const dir2005 As String = "http://test.foros.elGuille.info/public/NET/"
    '
    Public Sub New()
        MyBase.New()

        Application.EnableVisualStyles()
        Application.DoEvents()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub
    '
#Region " Windows Form Designer generated code "


#End Region
    '
    Private fExterno As Form 'FormularioExterno.Form1
    '
    Private Sub btnCerrar_Click(ByVal sender As System.Object, _
			 	ByVal e As System.EventArgs) _
				Handles btnCerrar.Click
        Me.Close()
    End Sub

    Private Sub btnMostrarFormExterno_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnMostrarFormExterno.Click
        ' Mostrar el formulario externo
        '
        ' Este código está "tomado" de:                             (16/May/03)
        '   Enabling the Smart Client with the .NET Runtime
        '   de Mark Boulter. Fecha 13/May/2001
        '
        ' Indicar dónde está localizado el formulario
        Dim fExternoAsm As System.Reflection.Assembly ' [Assembly]
        Dim desde As String = ""        ' La ubicación del ensamblado
        Dim nombreForm As String = ""   ' El nombre del ensamblado
        '
        ' El ensamblado puede estar en tres sitios:
        '   En el localhost
        '   El sitio del Guille
        '   En un directorio de nuestro equipo o de la red
        ' si hay que usarlo desde internet
        If optEnLocalhost.Checked Then
            desde = "http://localhost/""
        ElseIf optEnWeb.Checked Then
            'desde = "HTTP://guille.costasol.net/NET/"
            desde = "http://www.elguille.info/NET/"
            ' Si se usa la versión 2005, se cargará desde 
            ' http://test.foros.elGuille.info/
            If optUsar2005.Checked Then
                desde = dir2005
            End If
        ElseIf optEnPath.Checked Then
            If txtFichero.Text = "" Then
                MessageBox.Show("Debes indicar un path o dirección URL", _
				"Cargar ensamblado desde una ubicación", _
				MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
                txtFichero.Focus()
                Return
            Else
                If txtFichero.Text.ToLower.IndexOf("http") = -1 Then
                    desde = System.IO.Path.GetDirectoryName(txtFichero.Text)
                    Dim s As String = System.IO.Path.GetFileName(txtFichero.Text)
                    If s <> "" Then
                        nombreForm = s
                    End If
                Else
                    desde = txtFichero.Text
                End If
                ' Por si se indica una URL
                If desde.IndexOf("/") > -1 Then
                    If desde.EndsWith("/") = False Then
                        desde &= "/"
                    End If
                Else
                    If desde.EndsWith("\") = False Then
                        desde &= "\"
                    End If
                End If
            End If
        End If
        '
        ' La versión del .NET usada para crear el ensamblado (2002, 2003 ó 2005)
        If optUsar2002.Checked Then
            nombreForm = "FormularioExterno2002.dll"
        ElseIf optUsar2003.Checked Then
            nombreForm = "FormularioExterno.dll"
        ElseIf Me.optUsar2005.Checked Then
            nombreForm = "FormularioExterno2005.dll"
        ElseIf optUsar2003DatosSN.Checked Then
            nombreForm = "FormExternoDatos2003.dll"
        ElseIf optUsar2003DatosNoSN.Checked Then
            nombreForm = "FormExternoDatos2003SinSN.dll"
        End If
        '
        Try
            fExternoAsm = System.Reflection.Assembly.LoadFrom(desde & nombreForm)
        Catch ex As Exception
            MessageBox.Show("ERROR." & vbCrLf & ex.Message, _
				"Error al cargar " & nombreForm & " desde " & desde)
            Exit Sub
        End Try
        '
        ' Get the Form from the assembly
        Dim formType As Type
        ' El formulario con acceso a datos se llama de forma distinta
        If nombreForm.StartsWith("FormExternoDatos2003") Then
            formType = fExternoAsm.GetType("FormExternoDatos2003.FormExternoDatos")
        Else
            formType = fExternoAsm.GetType("FormularioExterno.Form1")
        End If
        '
        ' Create an instance of the Form
        Dim FormObj As Object
        FormObj = Activator.CreateInstance(formType)
        '
        ' Cast it to a Form object to enable early binding and show the form
        'fExterno = CType(FormObj, Form)
        'fExterno.Show()
        '-----------------------------------------------------------(09/sep/03)
        ' Desde el cliente 2003 se pueden usar librerías creadas con el 2002, pero no al revés
        ' También funciona                                          (13/Ago/05)
        Try
            fExterno = CType(FormObj, Form)
            fExterno.Show()
        Catch ex As Exception
            MessageBox.Show("ERROR." & vbCrLf & ex.Message, _
				"Error al realizar un 'cast' al tipo Form")
        End Try
    End Sub

    Private Sub btnExaminar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnExaminar.Click
        Dim openFD As New OpenFileDialog
        With openFD
            .Title = "Seleccionar el ensamblado externo a usar"
            .Filter = "Ensamblados DLL (*.dll)|*.dll|Todos los ficheros (*.*)|*.*"
            If txtFichero.Text <> "" Then
                .FileName = txtFichero.Text
            Else
                .InitialDirectory = System.IO.Directory.GetCurrentDirectory()
            End If
            If .ShowDialog = DialogResult.OK Then
                txtFichero.Text = .FileName
            End If
        End With
    End Sub

    Private Sub optEnPath_CheckedChanged(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles optEnPath.CheckedChanged
        txtFichero.Enabled = optEnPath.Checked
        btnExaminar.Enabled = optEnPath.Checked
    End Sub

    Private Sub fPrueba_Load(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles MyBase.Load
        txtFichero.Enabled = optEnPath.Checked
        btnExaminar.Enabled = optEnPath.Checked
        txtFichero.Text = dir2005
    End Sub
End Class

 

El formulario usado en las tres versiones de .NET (FormularioExterno)

'------------------------------------------------------------------------------
' Formulario para ser accedido externamente                         (14/May/03)
' o usándolo por referencia
' Añado Drag & Drop y lo firmo con nombre seguro		    (13/Ago/05)
'
' ©Guillermo 'guille' Som, 2003, 2005
'------------------------------------------------------------------------------

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

#End Region

    Private Sub btnCerrar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnCerrar.Click
        Me.Close()
    End Sub

    Private Sub btnAdd_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
Handles btnAdd.Click
        ' Añadir el contenido del TextBox a la lista
        Me.ListBox1.Items.Add(TextBox1.Text)
    End Sub

    Private Sub ListBox1_KeyUp(ByVal sender As Object, _
				ByVal e As System.Windows.Forms.KeyEventArgs) _
				Handles ListBox1.KeyUp
        ' eliminar el elemento seleccionado
        Dim i As Integer = ListBox1.SelectedIndex
        ListBox1.Items.RemoveAt(i)
    End Sub

    Private Sub ListBox1_Click(ByVal sender As Object, _
				ByVal e As System.EventArgs) _
				Handles ListBox1.Click
        Dim o As Object = ListBox1.SelectedItem
        TextBox1.Text = ListBox1.GetItemText(o)
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
Handles MyBase.Load
        ' Mostrar la versión de este ensamblado                     (13/Ago/05)
        ' esto dará error si no se tiene suficientes permisos
        Dim s As String = System.Reflection.Assembly.GetExecutingAssembly.Location
        Dim fvi As System.Diagnostics.FileVersionInfo
        fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(s)
        lblInfo.Text = "Versión: " & fvi.FileVersion
        '
        'lblInfo.Text = "v1.0.2.1 del 13/Ago/2005"
    End Sub
    Private Sub Form1_DragOver(ByVal sender As Object, _
				ByVal e As System.Windows.Forms.DragEventArgs) _
				Handles MyBase.DragOver
        If e.Data.GetDataPresent("FileDrop") Then
            e.Effect = DragDropEffects.Copy
        End If
    End Sub
    Private Sub Form1_DragDrop(ByVal sender As Object, _
				ByVal e As System.Windows.Forms.DragEventArgs) _
Handles MyBase.DragDrop
        If e.Data.GetDataPresent("FileDrop") Then
            Dim fic As String = DirectCast(e.Data.GetData("FileDrop", True), String())(0)
            abrirFichero(fic)
        End If
    End Sub
    Private Sub btnExaminar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnExaminar.Click
        ' Abrir un fichero del disco duro local                     (13/Ago/05)
        Dim openFD As New OpenFileDialog
        With openFD
            .Title = "Abrir un fichero para el ListBox"
            .Filter = "Ficheros de texto (*.txt;*.ini;*.cfg)|*.txt;*.ini;*.cfg|" & _
				"Todos los ficheros (*.*)|*.*"
            .InitialDirectory = System.IO.Directory.GetCurrentDirectory()
            If .ShowDialog = DialogResult.OK Then
                abrirFichero(.FileName)
            End If
        End With
    End Sub
    Private Sub abrirFichero(ByVal fic As String)
        Dim sr As System.IO.StreamReader = Nothing
        Try
            sr = New System.IO.StreamReader(fic, System.Text.Encoding.Default)
            While sr.Peek <> -1
                ListBox1.Items.Add(sr.ReadLine)
            End While
            sr.Close()
        Catch ex As Exception
            If Not sr Is Nothing Then
                sr.Close()
            End If
            MessageBox.Show("ERROR al abrir el fichero:" & vbCrLf & ex.Message, _
				"Abrir fichero desde formulario externo", _
				MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
End Class

 

El formulario de la versión 1.1 (2003) con acceso a datos

'------------------------------------------------------------------------------
' Formulario externo con acceso a datos y al sistema de archivos    (13/Ago/05)
'
' ©Guillermo 'guille' Som, 2005
'------------------------------------------------------------------------------
Imports Microsoft.VisualBasic
Imports System
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Data
Imports System.Data.SqlClient

Public Class FormExternoDatos
    Inherits System.Windows.Forms.Form

#Region " Código generado por el Diseñador de Windows Forms "

#End Region

    Private Sub Form1_Load(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles MyBase.Load
        ' Mostrar la versión de este ensamblado                     (13/Ago/05)
        ' esto dará error si no se tiene suficientes permisos
        Dim s As String = System.Reflection.Assembly.GetExecutingAssembly.Location
        Dim fvi As System.Diagnostics.FileVersionInfo
        fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(s)
        LabelInfo.Text = "Versión: " & fvi.FileVersion
        '
        txtConexion.Text = "data source=(local); initial catalog=Northwind;" & _
				" integrated security=yes; persist security info=False;"
        ' "user id=" & user & ";password=" & password & ";"
        With lvDatos
            .View = View.Details
            .GridLines = True
            .FullRowSelect = True
            .Columns.Clear()
            .Items.Clear()
        End With
    End Sub

    Private Sub btnMostrar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnMostrar.Click
        ' Conectar a la base de datos indicada y usando la cadena de selección
        Try
            Dim dt As New DataTable
            Dim da As New SqlDataAdapter(txtSelect.Text, txtConexion.Text)
            da.Fill(dt)
            ' rellenar el listview con los datos
            mostrarDatos(dt)
        Catch ex As Exception
            MessageBox.Show("ERROR al conectar a la base de datos:" & vbCrLf & ex.Message, _
				"Mostrar datos", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    Private Sub mostrarDatos(ByVal dt As DataTable)
        lvDatos.Items.Clear()
        lvDatos.Columns.Clear()
        ' Añadir las cabeceras
        For i As Integer = 0 To dt.Columns.Count - 1
            Dim dc As DataColumn = dt.Columns(i)
            If dc.DataType.Name = "DateTime" Then
                lvDatos.Columns.Add(dc.ColumnName, 120, HorizontalAlignment.Right)
            ElseIf dc.DataType.Name = "String" Then
                lvDatos.Columns.Add(dc.ColumnName, 120, HorizontalAlignment.Left)
            Else
                lvDatos.Columns.Add(dc.ColumnName, 100, HorizontalAlignment.Left)
            End If
        Next
        ' Añadir los datos de cada fila devuelta
        For Each dr As DataRow In dt.Rows
            Dim lvi As New ListViewItem
            For i As Integer = 0 To dt.Columns.Count - 1
                Dim dc As DataColumn = dt.Columns(i)
                If i = 0 Then
                    lvi.Text = dr(dc).ToString
                Else
                    lvi.SubItems.Add(dr(dc).ToString)
                End If
            Next
            lvDatos.Items.Add(lvi)
        Next
    End Sub

    Private Sub btnCerrar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) _
				Handles btnCerrar.Click
        Close()
    End Sub

    Private Sub TabPage2_DragOver(ByVal sender As Object, _
				ByVal e As System.Windows.Forms.DragEventArgs) _
				Handles TabPage2.DragOver
        If e.Data.GetDataPresent("FileDrop") Then
            e.Effect = DragDropEffects.Copy
        End If
    End Sub
    Private Sub TabPage2_DragDrop(ByVal sender As Object, _
				ByVal e As System.Windows.Forms.DragEventArgs) _
				Handles TabPage2.DragDrop
        If e.Data.GetDataPresent("FileDrop") Then
            Dim fic As String = DirectCast(e.Data.GetData("FileDrop", True), String())(0)
            abrirFichero(fic)
        End If
    End Sub
    Private Sub btnExaminar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) Handles btnExaminar.Click
        ' Abrir un fichero del disco duro local                     (13/Ago/05)
        Dim openFD As New OpenFileDialog
        With openFD
            .Title = "Abrir un fichero"
            .Filter = "Ficheros de texto (*.txt;*.ini;*.cfg;*.xml)|*.txt;*.ini;*.cfg;*.xml" & _
				"|Todos los ficheros (*.*)|*.*"
            If txtFichero.Text = "" Then
                .InitialDirectory = System.IO.Directory.GetCurrentDirectory()
            Else
                .FileName = txtFichero.Text
            End If
            If .ShowDialog = DialogResult.OK Then
                txtFichero.Text = .FileName
                abrirFichero(.FileName)
            End If
        End With
    End Sub
    Private Sub abrirFichero(ByVal fic As String)
        ' Leer el contenido del fichero y asignarlo al textbox      (13/Ago/05)
        Dim sr As System.IO.StreamReader = Nothing
        Try
            sr = New System.IO.StreamReader(fic, System.Text.Encoding.Default)
            txtDatos.Text = sr.ReadToEnd
            sr.Close()
        Catch ex As Exception
            If Not sr Is Nothing Then
                sr.Close()
            End If
            MessageBox.Show("ERROR al abrir el fichero:" & vbCrLf & ex.Message, _
				"Abrir fichero desde formulario externo", _
				MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub btnSelDir_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) Handles btnSelDir.Click
        ' Seleccionar un directorio y mostrar en el textbox los ficheros que contiene
        Dim fbd As New FolderBrowserDialog
        fbd.ShowNewFolderButton = True
        fbd.Description = "Selecciona el directorio para mostrar el contenido"
        fbd.RootFolder = Environment.SpecialFolder.Desktop
        If fbd.ShowDialog = DialogResult.OK Then
            Dim fis() As System.IO.FileInfo
            fis = New System.IO.DirectoryInfo(fbd.SelectedPath).GetFiles()
            ' Añadir el nombre de cada fichero del directorio al textbox
            Dim sb As New System.Text.StringBuilder
            For Each fi As System.IO.FileInfo In fis
                sb.AppendFormat("{0} - {1}{2}", fi.Name, fi.LastWriteTime, vbCrLf)
            Next
            txtDatos.Text = sb.ToString
        End If
    End Sub

    Private Sub btnEliminar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) Handles btnEliminar.Click
        ' Eliminar el fichero indicado en txtFichero
        If MessageBox.Show("¿Quieres borrar el fichero " & txtFichero.Text & "?", _
				"Eliminar un fichero", _
				MessageBoxButtons.YesNo, MessageBoxIcon.Question, _
				MessageBoxDefaultButton.Button2) = DialogResult.Yes Then
            Try
                System.IO.File.Delete(txtFichero.Text)
            Catch ex As Exception
                MessageBox.Show("ERROR al intentar borrar el fichero" & txtFichero.Text & _
				vbCrLf & ex.Message, "Eliminar fichero", _
				MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            End Try
        End If
    End Sub

    Private Sub btnGuardar_Click(ByVal sender As System.Object, _
				ByVal e As System.EventArgs) Handles btnGuardar.Click
        ' Guardar el contenido del textbox en el fichero indicado en txtFichero
        Dim sw As System.IO.StreamWriter = Nothing
        Try
            sw = New System.IO.StreamWriter(txtFichero.Text, False, System.Text.Encoding.Default)
            sw.Write(txtDatos.Text)
            sw.Close()
        Catch ex As Exception
            If Not sw Is Nothing Then
                sw.Close()
            End If
            MessageBox.Show("ERROR al guardar el fichero:" & vbCrLf & ex.Message, _
				"Guardar fichero desde formulario externo", _
				MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
End Class

 


la Luna del Guille o... el Guille que está en la Luna... tanto monta...