none
OpenFileDialog no abre archivo de directorios con restricción de permisos de seguridad

    Pregunta

  • Hola muy buenas noches;

    Probando una aplicación prototipo que estoy realizando, y probando varias funcionalidades de la misma, me he encontrado con una inquietud. Resulta que al tratar de abrir un archivo de mi aplicación por medio de la opción Abrir, o desde el explorador de windows(previamente ya he registrado la aplicación con su extensión en el equipo), por ejemplo si el archivo que esta ubicado en el Disco local C, no lo abre.

    Investigando, observo que tiene que ver por que hay ciertos directorios que por temas de seguridad el sistema operativo restringe el control de acceso, y que que para que mi aplicación pueda acceder a esos archivos, debo hacer uso de las clases FileIoPermissions, FileSecurity, nose si deben usarse otra más.

    He declarado este método para probar:

        Private Sub Permiso_archivo_disco_Read(ByVal path As String)
            Try
                'Se realiza un llamado de acceso a leer en la ruta.
                '
                Dim file_permissions As New FileIOPermission(FileIOPermissionAccess.Read, path)
                '
                'Se forza a que se permita la lectura en el directorio.
                file_permissions.Demand()
                '
            Catch ex As Security.SecurityException
                '
                'Se muestra un mensaje con la excepción encontrada.
                XtraEditors.XtraMessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)
                '
            Catch ex As IOException
                '
                'Otro tipo de errores.
                XtraEditors.XtraMessageBox.Show(ex.Message, My.Application.Info.Title, MessageBoxButtons.OK, MessageBoxIcon.Error)
                '
            End Try
        End Sub

    En el evento Click del botón Abrir, tengo implementado el siguiente código:

    Private Sub bbi_abrir_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbi_abrir.ItemClick
    
            'Ruta del archvo que desea abrir.
            Dim fileName As String = String.Empty
            'Nombre del archivo que desea abrir, sin la ruta.
            Dim nameFile As String = String.Empty
    
            ' Seleccionamos un archivo para abrir.
            '
            Using ofd As New OpenFileDialog()
                ofd.Filter = "Archivos del proyecto(.exa)" & "|*.exa|Todos los archivos|*.*"
                Dim dr As DialogResult = ofd.ShowDialog()
                If (dr <> DialogResult.OK) Then Return
                fileName = ofd.FileName
                nameFile = ofd.SafeFileName
            End Using
    
            Try
                ' El archivo no se encuentra abierto por otro proceso diferente.
                '
                ' Iniciamos una nueva instancia de la aplicación. Para ello le
                ' especificamos al constructor del objeto ProcessStartInfo la
                ' ruta completa del ejecutable de la aplicación.
                '
                '
                'Se pasa el argumento, que corresponde al archivo que se desea abrir. 
                'Obtenemos la ruta de acceso del archivo a abrir, tenienco en cuenta de que el nombre del archivo
                'o las carpetas pueden tener espacios en blanco y/o caracteres alfanuméricos, que necesitan enviarse
                'a la línea de comandos entre comillas dobles para que se pueda leer correctamente. Se hace uso de Chr(34)
                'que inserta las comillas dobles al inicio de la ruta y al final. Por ejemplo el archivo se llama Ejemplo 23
                'y sino se hace uso de las comillas dobles al inicio y al final sólo leería E.
                Dim startInfo As New ProcessStartInfo(Application.ExecutablePath) With
                {
                    .Arguments = String.Format("{0}", Chr(34) & System.IO.Path.GetFullPath(fileName) & Chr(34))
                }
    
                'Iniciamos una nueva instancia de la aplicación.
                Process.Start(startInfo)
    
            Catch ex As Exception
    
                ' Se ha producido un error.
                'Ojo puede darse el caso de intentar abrir un archivo con una secuencia vacìa.
                'Ojo puede darse el caso de intentar abrir un archivo con una secuencia vacìa.
                XtraEditors.XtraMessageBox.Show(ex.Message, ex.GetType().FullName,
                                                         MessageBoxButtons.OK, MessageBoxIcon.Error)
    
            End Try
    
        End Sub

    Mi duda está, en que en el evento Click del botón Abrir, luego de que verifico*:

     If (dr <> DialogResult.OK) Then Return

    *implementé el método Permiso_archivo_disco_Read, pero no funciona. ¿Cuál es entonces el procedimiento para permitir abrir archivos de directorios con restricciones de seguridad?. Yo tengo que luego desearilziar dicho archivo, y cargarlo a una instancia de mi aplicación, cuestión que no sucede.

    Muchas gracias.





    Harold Alonso Quintero Pineda Ingeniero Civil Universidad Francisco de Paula Santander Ocaña Correo: haroldpineda1401@outlook.com Cel: 3158700970


    miércoles, 26 de abril de 2017 1:48

Respuestas

  • "Harold Quintero Pineda" preguntó:

    > ... cuando intenté desde el explorador de windows copiar el archivo no me
    > lo permitía, mostrándome un mensaje de que la acción no se pudo completar
    > por que el archivo está abierto por mi aplicación; es el mismo caso cuando
    > se quiere eliminar, o cambiar el nombre, estos dos últimos casos que es lo
    > normal en cualquier aplicación. ¿Cómo hago para que al crear el FilsStream,
    > indicarle que si se permita copiar el archivo desde el explorador?.

    Si el archivo que intentas copiar, renombrar o eliminar se encuentra actualmente bloqueado, bien por el propio sistema operativo o por tu aplicación, ¿cómo pretendes llevar a cabo tal acción?

    Es como cuando bloqueas el archivo que el usuario abre desde tu aplicación. Si éste lo bloqueas al abrirlo y lo desbloqueas al cerrarlo, ¿cómo quieres que alguien o algo lo desbloquee externamente? Sería totalmente incongruente. ¿O no lo crees tú así?

    > El código que uso es este al crear el Stream:
    >
    > fs = New FileStream(rutaArchivo, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)

    Esa secuencia de lectura/escritura (FileAccess.ReadWrite) NO ESTÁ COMPARTIDA (FileShared.None), por lo que el archivo se bloqueará cuando se abra, tal y como así quiero recordar que demandabas en tu pregunta sobre la forma de bloquear un archivo abierto desde tu aplicación.

    La pregunta sería ahora: ¿has cambiado de opinión y deseas que los archivos que abres desde tu aplicación no se encuentren bloqueados? Si la respuesta es afirmativa, tan solo tienes que eliminar el valor FileShare.None, o asignarle algún otro valor diferente para compartirlo en módo lectura (FileShare.Read), en modo escritura (FileShare.Write), o en modo de lectura escritura (FileShare.ReadWrite), pero mientras que asignes el valor FileShared.None, el archivo estará bloqueado (no compartido con otras secuencias o acciones que deseen abrirlo o realizar una acción sobre el mismo, bien desde el Explorador de archivos de Windows o desde otra aplicación externa) hasta que se cierre la secuencia que utilizastes para abrirlo.

    FileShare (Enumeración)

    Creo que te estás complicando demasiado la vida con éste tema, y la solución es muy simple: si un archivo no se puede abrir, o realizar una acción sobre el mismo, porque se encuentra bloqueado, captura la excepción y actúa en consecuencia, y no entres en si solamente puedes leer su contenido, porque todo dependerá del modo en que el programador decidió compartir el archivo abierto, valor éste que ignoro por completo si se puede conocer de antemano.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    jueves, 4 de mayo de 2017 6:27
    Moderador
  • "Harold Quintero Pineda" preguntó:

    > ¿Es posible al menos permitir LEER los archivos independientemente si se abre
    > desde un directorio que requiere privilegios elevados, por medio de código
    > dentro de mi aplicación?

    Si el usuario que ejecuta la aplicación es el propietario del archivo que se desea abrir, o pertenece al grupo Administradores, puede que sea posible LEER un archivo por medio del código de tu aplicación. Pero si hablamos de un usuario normal y corriente, con los mínimos privilegios posibles, me parece a mí que va a ser bastante complicado que puede acceder a un archivo donde el propio sistema operativo le está denegando el acceso.

    Para que lo puedas comprobar, te he preparado un pequeño ejemplo basado en el código que encontrarás en el siguiente enlace:

    Método File.SetAccessControl (String, FileSecurity)

    Imports System.IO
    Imports System.Security.AccessControl
    Imports System.Text
    
    Public Class Form1
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            ' Indicamos la ruta de un archivo existente en la raíz
            ' de la unidad donde se encuentra instalado el sistema
            ' operativo:
            '
            Dim fileName As String = "C:\Prueba.bin" 
    
            Dim fSecurity As FileSecurity = Nothing
            Dim accessRule As FileSystemAccessRule = Nothing
    
            Try
                Dim buffer As Byte() = Nothing
    
                ' Especificar una Lista de Control de Acceso (ACL)
                fSecurity = File.GetAccessControl(fileName)
    
                ' Permitirle permiso de lectura al usuario actual.
                accessRule = New FileSystemAccessRule(My.User.Name, FileSystemRights.ReadData, AccessControlType.Allow)
                fSecurity.AddAccessRule(accessRule)
    
                ' Establecer la nueva configuración de acceso.
                File.SetAccessControl(fileName, fSecurity)
    
                MessageBox.Show("Reglas establecidas.")
    
                ' Abrir la secuencia con el archivo utilizando el control de acceso establecido
                '
                Using fs As New FileStream(fileName, FileMode.Open, FileSystemRights.ReadData, FileShare.Read, 4096, FileOptions.None, fSecurity)
                    Dim length As Int32 = CInt(fs.Length - 1)
                    buffer = New Byte(length) {}
                    fs.Read(buffer, 0, length)
                End Using
    
                ' Leer el contenido del archivo
                MessageBox.Show(Encoding.Unicode.GetString(buffer))
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
    
            Finally
                If (Not fSecurity Is Nothing) Then
                    ' Eliminar las reglas de acceso establecidas anteriormente.
                    fSecurity.RemoveAccessRule(accessRule)
    
                    ' Establecer la nueva configuración de acceso.
                    File.SetAccessControl(fileName, fSecurity)
                    MessageBox.Show("Reglas eliminadas")
                End If
    
            End Try
    
        End Sub
    
        Private Shared Function OpenFileDialog() As String
    
            Dim fileName As String = String.Empty
    
            Using ofd As New OpenFileDialog()
                ofd.Filter = "Todos los archivos|*.*"
                Dim dr As DialogResult = ofd.ShowDialog()
                If (dr = DialogResult.OK) Then
                    fileName = ofd.FileName
                End If
            End Using
    
            Return fileName
    
        End Function
    
    End Class

    Para que observes su funcionamiento, tendrás que buscar un archivo que sepas con total seguridad que no puedes acceder al mismo desde el Explorador de Windows, aunque tu cuenta pertenezca al grupo Administradores, porque si puedes acceder al mismo desde el Explorador de Windows, de nada sirve el ejemplo.

    Cuando ejecutes el ejemplo, y siempre y cuando tu cuenta de usuario pertenezca al grupo Administradores, podrás leer el archivo, pero si no es así, obtendrás una excepción a la hora de invocar al método File.GetAccessControl (Intento de realizar una operación no válida), simplemente porque el código llamador no dispone del permiso requerido.

    Fíjate que al objeto FileStream le tienes que especificar el objeto FileSecurity configurado:

        Using fs As New FileStream(fileName, FileMode.Open, FileSystemRights.ReadData,
                                   FileShare.Read, 4096, FileOptions.None, fSecurity)

    Igualmente observa que hemos abierto un archivo donde no hemos utilizado ningún cuadro de diálogo para obtener su ruta:

        ' Indicamos la ruta de un archivo existente en la raíz
        ' de la unidad donde se encuentra instalado el sistema
        ' operativo:
        '
        Dim fileName As String = "C:\Prueba.bin"

    Ahora, modifica esa línea por esta otra, donde se abrirá el clásico cuadro de diálogo Abrir para que el usuario pueda seleccionar un archivo:

         Dim fileName As String = OpenFileDialog()
         If (fileName.Length = 0) Then
             Return
         End If

    Si seleccionas un archivo al que no tienes acceso, no me vayas a preguntar cómo evitar la excepción que te muestra el propio cuadro de diálogo, porque me adelanto a indicarte que lo ignoro por completo. Por tanto, ¿para qué quieres abrir un archivo al que no tienes acceso si el propio cuadro de diálogo Abrir te va a impedir que lo puedas seleccionar? De verdad que no lo entiendo. ¿?

    Y dicho esto, te pregunto: ¿por qué esa especie de "capricho" en intentar guardar archivos dónde no tenemos permisos suficientes. ¿No crees que es una pérdida de tiempo total teniendo disponibles miles de carpetas donde podemos guardar los archivos que posteriormente abriremos para deserializarlos?

    Eso por un lado, y por otro, ¿qué seguridad tendría el sistema operativo si cualquier usuario, con los mínimos privilegios posibles, puede elevarse los permisos para acceder a cualquier archivo desde nuestra aplicación donde el sistema operativo le está denegando el acceso?

    Y por último, aunque tu aplicación conceda permisos a diestro y siniestro a todo usuario que la utilice para que pueda acceder a aquellos archivos a los que no tiene acceso, ¿tú crees que un Administrador del sistema va a autorizar que esa aplicación se instale en los equipos de una empresa cualquiera? Sería una irresponsabilidad total por su parte.

    Si yo fuera el Administrador de esa empresa, te puedes imaginar dónde iría una aplicación con esas características. ;-)

    ¿Quieres un consejo gratuito? Olvídate de querer guardar y abrir archivos donde el sistema operativo no lo permita, y emplea el tiempo que dedicas a evitar la protección del sistema operativo en cuestiones más productivas. Al menos, eso es lo que yo hago. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.






    miércoles, 3 de mayo de 2017 17:26
    Moderador
  • "Harold Quintero Pineda" escribió:

    > ... Resulta que al tratar de abrir un archivo de mi aplicación por
    > medio de la opción Abrir, o desde el explorador de windows(...),
    > por ejemplo si el archivo que esta ubicado en el Disco local C,
    > no lo abre.
    >
    > Investigando, observo que tiene que ver por que hay ciertos directorios
    > que por temas de seguridad el sistema operativo restringe el control de
    > acceso, ...
    >

    Efectivamente así es. Si tienes cualquier archivo (no es necesario que sean aquellos que utiliza tu aplicación) almacenado en la raíz de cualquier unidad, y peor aún, en aquella donde se encuentra instalado el propio sistema operativo, o en muchas otras que están protegidas por el sistema, un usuario normal y corriente (y puede que hasta un usuario perteneciente al grupo Administradores), NO PUEDE ABRIR UNA SECUENCIA EN MODO DE ESCRITURA, de ahí que a la hora de ejecutar en tu programa la apertura de la secuencia en modo de lectura y escritura (FileAccess.ReadWrite):    

    fs = New FileStream(rutaArchivo, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)

    obtendrás la excepción que estás teniendo, porque la misma te está diciendo que no tienes los preceptivos permisos para escribir (y puede que tampoco los tengas para leer) los datos existentes en dicho archivo, con independencia que quieres serializarlos, deserializarlos o tirarlos al "cubo de la basura".

    > ¿Cuál es entonces el procedimiento para permitir abrir archivos de
    > directorios con restricciones de seguridad?. Yo tengo que luego
    > desearilziar dicho archivo, y cargarlo a una instancia de mi aplicación,
    > cuestión que no sucede.

    Desde tu propia aplicación, poco vas a poder hacer, salvo CAPTURAR LA EXCEPCIÓN que estás obteniendo en el bloque Catch, por si deseas indicarle al usuario de una "manera elegante" que tiene disponible en las diversas unidades del disco duro, muchas otras carpetas donde puede guardar el archivo, y que no se encapriche en guardarla en la raíz de una unidad concreta (C:, D:, F:) o en cualquier otra carpeta protegida por el sistema operativo.

    Ya te comenté el otro día que tú no puedes pasarte por alto la seguridad del sistema operativo, concediéndole a los usuarios más permisos que los que realmente tienen. Si el usuario necesita disponer de más privilegios, lo que tiene que hacer es hablar con el Administrador del sistema, que es la persona que sabrá si se los tiene que conceder o no.

    Tú limítate a capturar la excepción para que tu programa no finalice de manera anómala, abrupta, y deja los temas de seguridad al sistema operativo y a los Administradores del sistema. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    jueves, 27 de abril de 2017 10:13
    Moderador

Todas las respuestas

  • "Harold Quintero Pineda" escribió:

    > ... Resulta que al tratar de abrir un archivo de mi aplicación por
    > medio de la opción Abrir, o desde el explorador de windows(...),
    > por ejemplo si el archivo que esta ubicado en el Disco local C,
    > no lo abre.
    >
    > Investigando, observo que tiene que ver por que hay ciertos directorios
    > que por temas de seguridad el sistema operativo restringe el control de
    > acceso, ...
    >

    Efectivamente así es. Si tienes cualquier archivo (no es necesario que sean aquellos que utiliza tu aplicación) almacenado en la raíz de cualquier unidad, y peor aún, en aquella donde se encuentra instalado el propio sistema operativo, o en muchas otras que están protegidas por el sistema, un usuario normal y corriente (y puede que hasta un usuario perteneciente al grupo Administradores), NO PUEDE ABRIR UNA SECUENCIA EN MODO DE ESCRITURA, de ahí que a la hora de ejecutar en tu programa la apertura de la secuencia en modo de lectura y escritura (FileAccess.ReadWrite):    

    fs = New FileStream(rutaArchivo, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)

    obtendrás la excepción que estás teniendo, porque la misma te está diciendo que no tienes los preceptivos permisos para escribir (y puede que tampoco los tengas para leer) los datos existentes en dicho archivo, con independencia que quieres serializarlos, deserializarlos o tirarlos al "cubo de la basura".

    > ¿Cuál es entonces el procedimiento para permitir abrir archivos de
    > directorios con restricciones de seguridad?. Yo tengo que luego
    > desearilziar dicho archivo, y cargarlo a una instancia de mi aplicación,
    > cuestión que no sucede.

    Desde tu propia aplicación, poco vas a poder hacer, salvo CAPTURAR LA EXCEPCIÓN que estás obteniendo en el bloque Catch, por si deseas indicarle al usuario de una "manera elegante" que tiene disponible en las diversas unidades del disco duro, muchas otras carpetas donde puede guardar el archivo, y que no se encapriche en guardarla en la raíz de una unidad concreta (C:, D:, F:) o en cualquier otra carpeta protegida por el sistema operativo.

    Ya te comenté el otro día que tú no puedes pasarte por alto la seguridad del sistema operativo, concediéndole a los usuarios más permisos que los que realmente tienen. Si el usuario necesita disponer de más privilegios, lo que tiene que hacer es hablar con el Administrador del sistema, que es la persona que sabrá si se los tiene que conceder o no.

    Tú limítate a capturar la excepción para que tu programa no finalice de manera anómala, abrupta, y deja los temas de seguridad al sistema operativo y a los Administradores del sistema. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    jueves, 27 de abril de 2017 10:13
    Moderador
  • Muy buenos días señor Montejo;

    De antemano muchas gracias por su respuesta. Hice lo que me dijo, y capturé el error también en el Main. Aunque tengo una duda y agradeciera si pudiese ayudarme. ¿Es posible al menos permitir LEER los archivos independientemente si se abre desde un directorio que requiere privilegios elevados, por medio de código dentro de mi aplicación?. Esa es mi duda, pues esa es mi intención, al menos poder LEER el archivo, para posteriormente desearilizarlo y cargarlo al programa. Cre que esto puede hacerse con una clase Permissions?

    Muchas gracias por todo.


    Harold Alonso Quintero Pineda Ingeniero Civil Universidad Francisco de Paula Santander Ocaña Correo: haroldpineda1401@outlook.com Cel: 3158700970


    miércoles, 3 de mayo de 2017 13:36
  • "Harold Quintero Pineda" preguntó:

    > ¿Es posible al menos permitir LEER los archivos independientemente si se abre
    > desde un directorio que requiere privilegios elevados, por medio de código
    > dentro de mi aplicación?

    Si el usuario que ejecuta la aplicación es el propietario del archivo que se desea abrir, o pertenece al grupo Administradores, puede que sea posible LEER un archivo por medio del código de tu aplicación. Pero si hablamos de un usuario normal y corriente, con los mínimos privilegios posibles, me parece a mí que va a ser bastante complicado que puede acceder a un archivo donde el propio sistema operativo le está denegando el acceso.

    Para que lo puedas comprobar, te he preparado un pequeño ejemplo basado en el código que encontrarás en el siguiente enlace:

    Método File.SetAccessControl (String, FileSecurity)

    Imports System.IO
    Imports System.Security.AccessControl
    Imports System.Text
    
    Public Class Form1
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            ' Indicamos la ruta de un archivo existente en la raíz
            ' de la unidad donde se encuentra instalado el sistema
            ' operativo:
            '
            Dim fileName As String = "C:\Prueba.bin" 
    
            Dim fSecurity As FileSecurity = Nothing
            Dim accessRule As FileSystemAccessRule = Nothing
    
            Try
                Dim buffer As Byte() = Nothing
    
                ' Especificar una Lista de Control de Acceso (ACL)
                fSecurity = File.GetAccessControl(fileName)
    
                ' Permitirle permiso de lectura al usuario actual.
                accessRule = New FileSystemAccessRule(My.User.Name, FileSystemRights.ReadData, AccessControlType.Allow)
                fSecurity.AddAccessRule(accessRule)
    
                ' Establecer la nueva configuración de acceso.
                File.SetAccessControl(fileName, fSecurity)
    
                MessageBox.Show("Reglas establecidas.")
    
                ' Abrir la secuencia con el archivo utilizando el control de acceso establecido
                '
                Using fs As New FileStream(fileName, FileMode.Open, FileSystemRights.ReadData, FileShare.Read, 4096, FileOptions.None, fSecurity)
                    Dim length As Int32 = CInt(fs.Length - 1)
                    buffer = New Byte(length) {}
                    fs.Read(buffer, 0, length)
                End Using
    
                ' Leer el contenido del archivo
                MessageBox.Show(Encoding.Unicode.GetString(buffer))
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
    
            Finally
                If (Not fSecurity Is Nothing) Then
                    ' Eliminar las reglas de acceso establecidas anteriormente.
                    fSecurity.RemoveAccessRule(accessRule)
    
                    ' Establecer la nueva configuración de acceso.
                    File.SetAccessControl(fileName, fSecurity)
                    MessageBox.Show("Reglas eliminadas")
                End If
    
            End Try
    
        End Sub
    
        Private Shared Function OpenFileDialog() As String
    
            Dim fileName As String = String.Empty
    
            Using ofd As New OpenFileDialog()
                ofd.Filter = "Todos los archivos|*.*"
                Dim dr As DialogResult = ofd.ShowDialog()
                If (dr = DialogResult.OK) Then
                    fileName = ofd.FileName
                End If
            End Using
    
            Return fileName
    
        End Function
    
    End Class

    Para que observes su funcionamiento, tendrás que buscar un archivo que sepas con total seguridad que no puedes acceder al mismo desde el Explorador de Windows, aunque tu cuenta pertenezca al grupo Administradores, porque si puedes acceder al mismo desde el Explorador de Windows, de nada sirve el ejemplo.

    Cuando ejecutes el ejemplo, y siempre y cuando tu cuenta de usuario pertenezca al grupo Administradores, podrás leer el archivo, pero si no es así, obtendrás una excepción a la hora de invocar al método File.GetAccessControl (Intento de realizar una operación no válida), simplemente porque el código llamador no dispone del permiso requerido.

    Fíjate que al objeto FileStream le tienes que especificar el objeto FileSecurity configurado:

        Using fs As New FileStream(fileName, FileMode.Open, FileSystemRights.ReadData,
                                   FileShare.Read, 4096, FileOptions.None, fSecurity)

    Igualmente observa que hemos abierto un archivo donde no hemos utilizado ningún cuadro de diálogo para obtener su ruta:

        ' Indicamos la ruta de un archivo existente en la raíz
        ' de la unidad donde se encuentra instalado el sistema
        ' operativo:
        '
        Dim fileName As String = "C:\Prueba.bin"

    Ahora, modifica esa línea por esta otra, donde se abrirá el clásico cuadro de diálogo Abrir para que el usuario pueda seleccionar un archivo:

         Dim fileName As String = OpenFileDialog()
         If (fileName.Length = 0) Then
             Return
         End If

    Si seleccionas un archivo al que no tienes acceso, no me vayas a preguntar cómo evitar la excepción que te muestra el propio cuadro de diálogo, porque me adelanto a indicarte que lo ignoro por completo. Por tanto, ¿para qué quieres abrir un archivo al que no tienes acceso si el propio cuadro de diálogo Abrir te va a impedir que lo puedas seleccionar? De verdad que no lo entiendo. ¿?

    Y dicho esto, te pregunto: ¿por qué esa especie de "capricho" en intentar guardar archivos dónde no tenemos permisos suficientes. ¿No crees que es una pérdida de tiempo total teniendo disponibles miles de carpetas donde podemos guardar los archivos que posteriormente abriremos para deserializarlos?

    Eso por un lado, y por otro, ¿qué seguridad tendría el sistema operativo si cualquier usuario, con los mínimos privilegios posibles, puede elevarse los permisos para acceder a cualquier archivo desde nuestra aplicación donde el sistema operativo le está denegando el acceso?

    Y por último, aunque tu aplicación conceda permisos a diestro y siniestro a todo usuario que la utilice para que pueda acceder a aquellos archivos a los que no tiene acceso, ¿tú crees que un Administrador del sistema va a autorizar que esa aplicación se instale en los equipos de una empresa cualquiera? Sería una irresponsabilidad total por su parte.

    Si yo fuera el Administrador de esa empresa, te puedes imaginar dónde iría una aplicación con esas características. ;-)

    ¿Quieres un consejo gratuito? Olvídate de querer guardar y abrir archivos donde el sistema operativo no lo permita, y emplea el tiempo que dedicas a evitar la protección del sistema operativo en cuestiones más productivas. Al menos, eso es lo que yo hago. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.






    miércoles, 3 de mayo de 2017 17:26
    Moderador
  • Muy buenas tardes señor Montejo;

    Usted tiene toda la razón, aunque ya había controlado la excepción en el Main, mostrándole al usuario que no puede abrir el archivo, y que deb abrirlo desde otra ruta(a forma de resumen eso hoce con un MsgBox), quería ver la posibilidad de si abrir el archivo, pero solo iba a ser de solo LECTURA, y cuando intentara guardar los cambios no se lo permitiera y que tendría que guardarlo en otra parte del Disco. Se que es algo poco lógico, pero la idea era al menos permitirle ver el archivo al usuario, un estilo SOLO LECTURA.

    Agradezco sus consejos, y los voy a aplicar, para como usted dice no perder tiempo en este tipo de cosas. Probé su ejemplo, y funciona de maravilla, lo tendré mjuy en cuenta para otra aplicación que pienso desarrollar con BD.

    Por último señor Montejo, y saliendo un poco del hilo, probando la aplicación en la cual usted me ha ayudado tanto, cuando intenté desde el explorador de windows copiar el archivo no me lo permitía, mostrándome un mensaje de que la acción no se pudo completar por que el archivo está abierto por mi aplicación; es el mismo caso cuando se quiere eliminar, o cambiar el nombre, estos dos últimos casos que es lo normal en cualquier aplicación. ¿Cómo hago para que al crear el FilsStream, indicarle que si se permita copiar el archivo desde el explorador?. El código que uso es este al crear el Stream:

     fs = New FileStream(rutaArchivo, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)

    Muchas gracias por todo.



    Harold Alonso Quintero Pineda Ingeniero Civil Universidad Francisco de Paula Santander Ocaña Correo: haroldpineda1401@outlook.com Cel: 3158700970

    miércoles, 3 de mayo de 2017 20:01
  • "Harold Quintero Pineda" preguntó:

    > ... cuando intenté desde el explorador de windows copiar el archivo no me
    > lo permitía, mostrándome un mensaje de que la acción no se pudo completar
    > por que el archivo está abierto por mi aplicación; es el mismo caso cuando
    > se quiere eliminar, o cambiar el nombre, estos dos últimos casos que es lo
    > normal en cualquier aplicación. ¿Cómo hago para que al crear el FilsStream,
    > indicarle que si se permita copiar el archivo desde el explorador?.

    Si el archivo que intentas copiar, renombrar o eliminar se encuentra actualmente bloqueado, bien por el propio sistema operativo o por tu aplicación, ¿cómo pretendes llevar a cabo tal acción?

    Es como cuando bloqueas el archivo que el usuario abre desde tu aplicación. Si éste lo bloqueas al abrirlo y lo desbloqueas al cerrarlo, ¿cómo quieres que alguien o algo lo desbloquee externamente? Sería totalmente incongruente. ¿O no lo crees tú así?

    > El código que uso es este al crear el Stream:
    >
    > fs = New FileStream(rutaArchivo, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)

    Esa secuencia de lectura/escritura (FileAccess.ReadWrite) NO ESTÁ COMPARTIDA (FileShared.None), por lo que el archivo se bloqueará cuando se abra, tal y como así quiero recordar que demandabas en tu pregunta sobre la forma de bloquear un archivo abierto desde tu aplicación.

    La pregunta sería ahora: ¿has cambiado de opinión y deseas que los archivos que abres desde tu aplicación no se encuentren bloqueados? Si la respuesta es afirmativa, tan solo tienes que eliminar el valor FileShare.None, o asignarle algún otro valor diferente para compartirlo en módo lectura (FileShare.Read), en modo escritura (FileShare.Write), o en modo de lectura escritura (FileShare.ReadWrite), pero mientras que asignes el valor FileShared.None, el archivo estará bloqueado (no compartido con otras secuencias o acciones que deseen abrirlo o realizar una acción sobre el mismo, bien desde el Explorador de archivos de Windows o desde otra aplicación externa) hasta que se cierre la secuencia que utilizastes para abrirlo.

    FileShare (Enumeración)

    Creo que te estás complicando demasiado la vida con éste tema, y la solución es muy simple: si un archivo no se puede abrir, o realizar una acción sobre el mismo, porque se encuentra bloqueado, captura la excepción y actúa en consecuencia, y no entres en si solamente puedes leer su contenido, porque todo dependerá del modo en que el programador decidió compartir el archivo abierto, valor éste que ignoro por completo si se puede conocer de antemano.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    jueves, 4 de mayo de 2017 6:27
    Moderador
  • Muy buenas noches señor Montejo;

    Si, la idea es bloquear el archivo, tal cual usted me ha venido instruyendo, pero dado que apenas entro en esto de los Streams, no sabía que al usar FileShare.None, también me iba a impedir copiar el archivo(puede ser a otra ruta o simplemente enviar a una USB, entre otras) cuando la aplicación lo esta usando, es por eso que me entró la duda. Ahora sabiendo, y habiendo entendido por completo, la forma de compartir el archivo que yo andaba buscando se acomodad a FileShare.Read. Como usted me ha dicho, resuelta esta duda, creo que doy por terminado mi prototipo de aplicación respecto a la forma más correcta desde lo que yo quería lograr al tratar de que mi programa tuviese su propio formato.

    Gracias por todo su apoyo señor Montejo, y de ahora en adelante poco a poco empezaré a desarrollar un programa que ya empecé con los requeremientos, en un área del conocimiento de mi carrera de Ingeniería llamda Geotecnia.

    Muchas gracias por todo. Dios me lo bendiga.


    Harold Alonso Quintero Pineda Ingeniero Civil Universidad Francisco de Paula Santander Ocaña Correo: haroldpineda1401@outlook.com Cel: 3158700970

    jueves, 4 de mayo de 2017 23:17