none
versión del motor de base de datos Microsoft.ACE.OLEDB.12.0 que tiene instalado un usuario. RRS feed

  • Pregunta

  • Hola a todos:

    Precisaría saber que motor de access tiene instalado el usuario, si bien es el access 2007 o bien el 2010 o superior. Esto lo preciso para que el usuario pueda instalarlo directamente desde el Submain y no tener que enviarlo a la dirección de microsoft, etc., es decir al aceptar un cuadro de diálogo, ya lo redirijo a dicha instalación.

    Tengo el procedimiento que ya me indica el motor que necesita (lo realizó el Sr. Enrique Martínez) y el cual funciona a la perfección siendo lo único que necesito es que si es de 32 bytes el office indicarle el motor que necesita si el 2007 o el superior al 2010. He de comentar que dicho motor lo necesito saber primero si quiere trabajar con access y no con SqlCompact que es la base que de entrada capta el submain y después porque aunque sea compact o sql server, cuando realiza una importación de datos desde Excel necesita ese motor.

    Resumiendo os pongo los dos procedimientos y solo necesito indicarle si precisa el motor de access 2007 o el 2010.

    Imports System.Globalization
    Imports System.Reflection
    Imports System.Runtime.InteropServices
    
    
    
    Friend Class MicrosoftAceHelper
    
        ''' <summary>
        ''' Devuelve una cadena alfanumérica con la arquitectura del procesador.
        ''' </summary>
        Private Shared ReadOnly Property CurrentProcessArchitecture As String
            Get
                ' Se necesita .NET 3.5 o superior, por lo que habrá que
                ' referenciar el ensamblado que corresponda:
                '
                ' Microsoft.Build.Utilities.v3.5
                ' Microsoft.Build.Utilities.v4.0
                '
                Return Microsoft.Build.Utilities.ProcessorArchitecture.CurrentProcessArchitecture
            End Get
        End Property
    
        ''' <summary>
        ''' Indica si el sistema operativo es de 32 bits.
        ''' </summary>
        Friend Shared ReadOnly Property Is32BitOperatingSystem As Boolean
            Get
                Try
                    Dim dic As IDictionary = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine)
    
                    ' De la máquina
                    Dim value As String = Convert.ToString(dic("PROCESSOR_ARCHITECTURE"), CultureInfo.CurrentCulture)
    
                    Return value.Equals("x86", StringComparison.InvariantCultureIgnoreCase)
                Catch
                    Return False
                End Try
            End Get
        End Property
    
        ''' <summary>
        '''  Determina si el proceso actual es un proceso de 32 bits.
        ''' </summary>
        Friend Shared ReadOnly Property Is32BitProcess As Boolean
            Get
                Return CurrentProcessArchitecture.Equals("x86", StringComparison.InvariantCultureIgnoreCase)
            End Get
        End Property
    
        ''' <summary>
        ''' Indica si el sistema operativo es de 64 bits.
        ''' </summary>
        Friend Shared ReadOnly Property Is64BitOperatingSystem As Boolean
            Get
                Try
                    Dim dic As IDictionary = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine)
    
                    ' De la máquina
                    Dim value As String = Convert.ToString(dic("PROCESSOR_ARCHITECTURE"), CultureInfo.CurrentCulture)
    
                    Return value.Equals("AMD64", StringComparison.InvariantCultureIgnoreCase)
    
                Catch
                    Return False
                End Try
            End Get
        End Property
    
        ''' <summary>
        ''' Determina si el proceso actual es un proceso de 64 bits.
        ''' </summary>
        Friend Shared ReadOnly Property Is64BitProcess As Boolean
            Get
                Return CurrentProcessArchitecture.Equals("AMD64", StringComparison.CurrentCultureIgnoreCase)
            End Get
        End Property
    
        ''' <summary>
        ''' Indica si el sistema operativo es IA64.
        ''' </summary>
        Friend Shared ReadOnly Property IsIA64OperatingSystem As Boolean
            Get
                Try
                    Dim dic As IDictionary = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine)
    
                    ' De la máquina
                    Dim value As String = Convert.ToString(dic("PROCESSOR_ARCHITECTURE"), CultureInfo.CurrentCulture)
    
                    Return value.Equals("IA64", StringComparison.CurrentCultureIgnoreCase)
    
                Catch
                    Return False
                End Try
            End Get
        End Property
    
        ''' <summary>
        ''' Indica si se encuentra instalado en el equipo
        ''' el proveedor de datos Microsoft ACE.
        ''' </summary>
        ''' <author>Enrique M. Montejo - 2011</author>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Friend Shared Function IsAceProviderInstalled() As Boolean
    
            Dim com As Object = Nothing
    
            Try
                ' Intentamos crear una instancia de la clase Microsoft.ACE.OLEDB.12.0
                ' mediante su identificador de clase, que de existir se encontrará
                ' registrado en la siguiente clave del registro de Windows.
                '
                ' HKEY_CLASSES_ROOT\CLSID\{3BE786A0-0366-4F5C-9434-25CF162E475E}
                '
                ' En un sistema operativo de 64 bits que tenga instalada una versión
                ' de 32 bits del proveedor de datos Microsoft.ACE.OLEDB.12.0, se
                ' encontrará registrado en ésta otra clave del registro de Windows.
                '
                ' HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID\{3BE786A0-0366-4F5C-9434-25CF162E475E}
                '
                Dim g As New Guid("{3BE786A0-0366-4F5C-9434-25CF162E475E}")
                Dim ty As Type = Type.GetTypeFromCLSID(g)
                com = Activator.CreateInstance(ty, BindingFlags.Default, Nothing, Nothing, Nothing, Nothing)
    
            Catch ex As Runtime.InteropServices.COMException
                ' Si el GUID no existe se habrá producido una excepción del
                ' tipo COMException con el siguiente mensaje de error:
                '
                ' Error al recuperar un generador de clases COM para el componente con CLSID
                ' {3BE786A0-0366-4F5C-9434-25CF162E475E} debido al siguiente error: 80040154
                ' clase no registrada.
                '
                ' En lugar de devolver la excepción devuelvo el valor False.
                '
                Return False
    
            Finally
                Try
                    If (Not com Is Nothing) Then
                        ' Liberar todas las referencias del contenedor RCW.
                        Marshal.FinalReleaseComObject(com)
                    End If
    
                Catch
                    ' Sin implementación.
                End Try
    
                com = Nothing
    
            End Try
    
            ' Si se ha creado la instancia del objeto especificado es porque
            ' existe el proveedor de datos Microsoft.ACE.OLEDB.12.0.
            '
            Return True
    
        End Function
    
    End Class

     Private Shared Sub VersionSistemaOperativoInstaladoAccess()
    
            ' Verificar si se encuentra instalado el proveedor de datos
            ' Microsoft.ACE.OLEDB.12.0, con independencia de la arquitectura
            ' que tenga el procesador actual.
            '
            Dim existe As Boolean = MicrosoftAceHelper.IsAceProviderInstalled()
    
            If (Not existe) Then
    
                ' Comprobar si el proceso actual de nuestra aplicación es de 64 bits.
                '
                If ((MicrosoftAceHelper.Is64BitProcess) AndAlso
                    ((MicrosoftAceHelper.Is64BitOperatingSystem) OrElse (MicrosoftAceHelper.IsIA64OperatingSystem))) Then
                    ' El proceso actual de nuesta aplicación es de 64 bits y el sistema operativo es
                    ' también de 64 bits o Intel Itanium: se requiere Access 2010 o superior de 64 bits.
                    '
                    'MessageBox.Show("Se requiere el Componente redistribuible del motor de base de datos de Microsoft Access 2010 o superior de 64 bits.")
                    '' http://www.microsoft.com/es-es/download/details.aspx?id=13255
                    Dim respuesta As DialogResult = MessageBox.Show("Se requiere el Componente redistribuible del motor de base de datos de Microsoft Access 2010 o superior de 64 bits." & vbCrLf &
                      " Componente de Access 2010 o superior: http://www.microsoft.com/es-es/download/details.aspx?id=13255 " & vbCrLf &
                      " Puede acceder directamente al mismo desde la página de instrucciones que se le ha remitido pulsando el link que corresponda." & vbCrLf &
                      "", "Financial System. - Motor de Access", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
                ElseIf (MicrosoftAceHelper.Is32BitProcess) Then
                    ' El proceso actual de nuestra aplicación es de 32 bits, con independencia
                    ' que el sistema operativo sea de 32 o de 64 bits: se requiere Access 2007
                    ' o superior de 32 bits.
                    '
                    'MessageBox.Show("Se requiere el Componente de conectividad de datos de Microsoft Access 2007 o superior de 32 bits.")
                    ' Componente de Access 2007: http://www.microsoft.com/es-es/download/details.aspx?id=23734
                    ' Componente de Access 2010: http://www.microsoft.com/es-es/download/details.aspx?id=13255
    
                    Dim respuesta As DialogResult = MessageBox.Show("Se requiere el Componente redistribuible del motor de base de datos de Microsoft Access 2007 o superior de 32 bits." & vbCrLf &
                      " Componente de Access 2007: http://www.microsoft.com/es-es/download/details.aspx?id=23734 " & vbCrLf &
                      " Componente de Access 2010: http://www.microsoft.com/es-es/download/details.aspx?id=13255" & vbCrLf &
                      " Puede acceder directamente al mismo desde la página de instrucciones que se le ha remitido pulsando el link que corresponda." & vbCrLf &
                      "", "Financial System. - Motor de Access", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
                End If
    
                End
            Else
                'No diremos nada si el motor instalado es correcto. Ahora es para las pruebas.
                '  MessageBox.Show("Se encuentra instalado el proveedor de datos Microsoft.ACE.OLEDB.12.0.")
    
            End If
        End Sub

    Y también si puede ser, desearía que si el usuario ha cambiado de office al mismo tiempo que instala el motor para el nuevo office y en caso de que tenga instalado el 2007 u otro, lo pueda desinstalar automáticamente y quedase sustituido por el que pide el procedimiento, ya que no puede haber dos motores diferentes instalados.

    Muchas gracias a todos.

    Un saludo.,

    Gemma





    sábado, 17 de diciembre de 2016 11:41

Respuestas

  • "gemma_campillo" preguntó:

    > Precisaría saber que motor de access tiene instalado el usuario, si bien es el
    > access 2007 o bien el 2010 o superior. Esto lo preciso para que el usuario pueda
    > instalarlo directamente desde el Submain y no tener que enviarlo a la dirección
    > de microsoft, etc., es decir al aceptar un cuadro de diálogo, ya lo redirijo a
    > dicha instalación.

    ¡Madre mía! ¿Todavía continuas con ese tema? Creía que ya estaba más que superado. :-(

    Mejor será que edites el Asunto de tu mensaje, porque más que saber si el usuario tiene instalado Office (que es de pago), entiendo que la pregunta se refiere a saber qué versión del motor de base de datos Microsoft.ACE.OLEDB.12.0 tiene instalado.

    Y la versión del citado proveedor dependerá de la versión de FinalcialSytem que ejecute el usuario, si ejecuta una versión de 32 o de 64 bits de FinalcialSystem.exe.

    Mira a ver si el siguiente esquema te despeja las dudas que observo continuas teniendo:

    Sistema Operativo Windows de 32 bits

    • Requerimientos:
      - FinalcialSytem de 32 bits
      - Access de 32 bits

           Si la función IsAceProviderInstalled devuelve False es porque no tiene instalado el motor de
           base de datos Microsoft.ACE.OLEDB.12.0 de 32 bits: --> Instalar Access 2007 o superior de 32 bits.

           - ¿Que no desea instalar Access?
              Entonces instalar el Componente redistribuible del motor de base de datos
              de Microsoft Access 2010 de 32 bits: AccessDatabaseEngine.exe

            https://www.microsoft.com/es-es/download/details.aspx?id=13255

    Sistema Operativo Windows de 64 bits

    • Requerimientos:
      - FinalcialSytem de 64 bits
      - Office de 64 bits

           Si la función IsAceProviderInstalled devuelve False es porque no tiene instalado el motor de
           base de datos Microsoft.ACE.OLEDB.12.0 de 64 bits: --> instalar Access 2010 o superior de 64 bits.

           - ¿Que no desea instalar Access?
              Entonces instalar el Componente redistribuible del motor de base de datos de
              Microsoft Access 2010 de 64 bits: AccessDatabaseEngine_X64.exe

             https://www.microsoft.com/es-es/download/details.aspx?id=13255

    Sistema Operativo Windows de 64 bits y Access de 32 bits instalado

    En este supuesto el usuario tiene un Windows de 64 bits, pero tiene instalada la versión de 32 bits del motor de base de datos Microsoft.ACE.OLEDB.12.0.

    • Requerimientos:
      - FinalcialSytem de 32 bits

        Aquí la función IsAceProviderInstalled devolverá True, y si devuelve False es porque estará ejecutando
        la versión de 64 bits de FinalcialSystem.exe.

        En éste supuesto especial, el usuario tiene que ejecutar la versión de 32 bits de FinalcialSytem, te guste o no te guste. ;-)


    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.





    sábado, 17 de diciembre de 2016 16:15
    Moderador
  • Vamos a ver si el siguiente código te proporciona una ayuda extra.

    Inserta en el archivo donde tienes definida la clase MicrosoftAceHelper, y ANTES DE SU DECLARACIÓN, la siguiente enumeración:

    Friend Enum VersionProveedorACE
        None = 0
        Access2007x32 = 1
        Access2010x32 = 2
        Access2010x64 = 3
    End Enum
    
    ' Aquí comienza la clase MicrosoftAceHelper
    '
    ' Friend Class MicrosoftAceHelper

    Y en la propia clase MicrosoftAceHelper, inserta esta función nueva:

        Friend Shared Function VersionAccessParaInstalar() As VersionProveedorACE
    
            ' Verificar si se encuentra instalado el proveedor de datos
            ' Microsoft.ACE.OLEDB.12.0, con independencia de la arquitectura
            ' que tenga el procesador actual.
            '
            Dim existe As Boolean = MicrosoftAceHelper.IsAceProviderInstalled()
    
            Dim version As VersionProveedorACE
    
            If (Not existe) Then
    
                ' Comprobar si el proceso actual de nuestra aplicación es de 64 bits.
                '
                If ((MicrosoftAceHelper.Is64BitProcess) AndAlso
                    ((MicrosoftAceHelper.Is64BitOperatingSystem) OrElse (MicrosoftAceHelper.IsIA64OperatingSystem))) Then
                    ' El proceso actual de nuesta aplicación es de 64 bits y el sistema operativo es
                    ' también de 64 bits o Intel Itanium: se requiere Access 2010 o superior de 64 bits.
                    '
                    version = VersionProveedorACE.Access2010x64
    
                ElseIf (MicrosoftAceHelper.Is32BitProcess) Then
                    ' El proceso actual de nuestra aplicación es de 32 bits, con independencia
                    ' que el sistema operativo sea de 32 o de 64 bits: se requiere Access 2007
                    ' o superior de 32 bits.
                    '
                    version = VersionProveedorACE.Access2010x32
    
                End If
    
            Else
                ' Se encuentra instalado el motor de base de datos Microsoft.ACE.OLEDB.12.0
                version = VersionProveedorACE.None
    
            End If
    
            Return version
    
        End Function

    Ahora, cuando desees obtener la versión de Access que hay que instalar, ejecutarías lo siguiente:

       Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Dim CrLf As String = Environment.NewLine
    
            Dim versionOffice As VersionProveedorACE = MicrosoftAceHelper.VersionAccessParaInstalar()
    
            Dim msg As String = String.Empty
    
            If (versionOffice = VersionProveedorACE.Access2010x32) Then
                msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                    "motor de base de datos correspondiente a Microsoft Access 2007 o superior " &
                    "de 32 bits." & CrLf & CrLf &
                    "El componente de Access 2010 de 32 bits lo puede descargar desde el " &
                    "siguiente enlace: http://www.microsoft.com/es-es/download/details.aspx?id=13255"
    
            ElseIf (versionOffice = VersionProveedorACE.Access2010x64) Then
                msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                      "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                      "de 64 bits." & CrLf & CrLf &
                      "El componente de Access 2010 de 64 bits lo puede descargar desde el " &
                      "siguiente enlace: http://www.microsoft.com/es-es/download/details.aspx?id=13255"
            Else
                msg = "No se necesita ninguna version de Access."
    
            End If
    
            MessageBox.Show(msg)
    
        End Sub


    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.


    sábado, 17 de diciembre de 2016 17:12
    Moderador
  • "gemma_campillo" escribió:

    > El tema ya lo tenía claro, ...

    ¿Estás segura de ello? ;-)

    > ... lo que no tenía claro era por ejemplo en el caso de 32 bytes y el cliente
    > tiene el office 2010 instalado y yo le estoy metiendo el 2007 entonces el
    > tendrá que instalar el motor de access 2007.

    El Office 2010 instalado, ¿de 32 o de 64 bits? ¿Qué versión es la que tiene instalada?

    Aparte, no te debe interesar el Office que tiene instalado, porque de lo que estamos hablando es si el cliente tiene o no instalada la versión adecuada del proveedor de datos Microsoft.ACE.OLEDB.12.0, que es el que nos permite interactuar con bases de datos Microsoft Access, así como con algunos ISAM instalables (últimamente, para Excel y Texto).

    ¡Mujer! Piensa que si tiene instalada alguna versión profesional de Microsoft Office, puede que tenga instalado el citado proveedor porque se supone que tiene instalado Microsoft Access. Pero, ¿y si tiene una versión de Office estándar?

    Y entiendo que si el cliente tiene instalado el motor de datos de Access 2010, tú no deberías instalarle el motor de Access 2007, porque ¿para qué quieres hacer eso?

    Estás haciendo uso de la función llamada IsAceProviderInstalled, que precisamente te está indicando si el usuario tiene instalada una versión adecuada del proveedor Microsoft.ACE.OLEDB.12.0 para utilizarla con el proceso actual de tu aplicación. Pues tan solo tienes que leer el resultado de la función: True (todo está correcto); False (no está correcto: actuar en consecuencia).

    > El cliente solo instalará el motor para base de datos 2007 o 2010 o superior.
    > Eso se lo quiero hacer sin que tenga que acudir a buscarlo en las instrucciones
    > y después en la web, de esta manera ya le indico que va a instalar tal motor o
    > tal otro, tal como he hecho con el motor del SQL Compact y con el motor de los
    > informes de Crystal Reports.

    Olvídate de Access 2007. ¿Sabes para qué tiene sentido a fecha de hoy (17/12/2016) instalar exclusivamente los Componentes redistribuibles de Access 2007? Pues para una persona que tenga un sistema operativo de 64 bits, tenga instalado Access 2010 o superior de 64 bits, y se dedique al desarrollo de aplicaciones de bases de datos. Es decir, que tenga instalado Visual Studio (que es una aplicación de 32 bits) y desee hacer pruebas de su aplicación para 32 y 64 bits. Ese es mi caso, y posiblemente el de muchos de nosotros.

    Cuando desde Visual Studio compile su proyecto para 32 bits, estará utilizando los componentes de Access 2007 de 32 bits, y cuando compile su proyecto para 64 bits, utilizará los componentes de Access 2010 o superior de 64 bits. Si no se dan esas circunstancias, ¿para qué quieres instalarle a tu cliente una versión de Access que el próximo mes de enero cumplirá ¡¡10 años!!, que para una persona es nada, pero para una aplicación informática, es toda una vida. ;-)

    Ignoro si de tu aplicación tienes efectuadas dos compilaciones: una para 32 bits y otra para 64 bits. Pues dependiendo de lo que tu cliente tenga instalado en el equipo, así deberá de ADQUIRIR una u otra.


    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.


    sábado, 17 de diciembre de 2016 16:56
    Moderador
  • "gemma_campillo" escribió:

    > Mi versión de Access actual es la 2016, antes tenía la 2007 y si quiero hacer
    > una actualización a los clientes que instalaron en su momento la de access 2007
    > para 32 bytes, ahora, será necesario cambiarla por la del motor 2010 o superior
    > para 32 bytes. Eso lo he probado y funciona correctamente, ahora lo único que me
    > quedará será borrar automáticamente la versión antigua del motor de access y
    > sustituirla por la nueva, eso lo necesitaré hacer de desde el código para que el
    > usuario no se moleste en hacer nada.

    ¿Y qué tiene que ver que tú estés utilizando Access 2016 (32 o 64 bits) y un cliente tuyo tenga Access 2007 (sólo en versión de 32 bits)? Es como si me dices que viajas en un Mercedes y yo en un SEAT Panda. ¿Qué tiene que ver lo uno con lo otro? Y anteriormente escribías que tenías claro el tema. ¡Sí! ¡Ya lo veo! :-))

    ¡Vamos a ver, "Gemma de mi alma"! ¿Tu aplicación trabaja con los objetos propios de la biblioteca de objetos de Microsoft Access? ¿En tu proyecto tienes alguna referencia a la biblioteca Microsoft.Office.Interop.Access? Si no tienes la citada referencia, ¿qué más da que tu tengas instalado en tu equipo Access 2016 y un cliente Access 2007? Te repito por enésima vez que no estás trabajando con ninguna aplicación de Microsoft Office, que solamente estás trabajando con el proveedor de datos Microsoft.ACE.OLEDB.12.0, el cual se instala con Microsoft Access o con los Componentes redistribuibles de Access 2007 y de Access 2010, no existiendo éstos para versiones de Access 2013 o de Access 2016, salvo que yo esté equivocado o no sepa encontrarlos.

    Distinto sería que la versión de Access 2016 del citado proveedor incluyera nuevas características no disponibles en versiones anteriores, y encima, tu las utilizaras en tu programa. En este caso sí tendrías que actualizarle al cliente el "dichoso" proveedor. Pero si no es así, no tienes por qué actualizarle nada.

    Eso sí. Cierta vez te comenté que si le has establecido una contraseña a la base de datos de Access mediante el propio Access 2010 o superior, entonces esa base de datos no se va a poder abrir con Access 2007. ¿Te acuerdas?

    > Entonces lo que tengo que mirar únicamente es instalarle ese motor y borrar
    > el de 2007 si es que lo tenía instalado.

    Yo que tú no desinstalaría nada, y tampoco lo instalaría. Que sea el cliente el que tome esa decisión y asuma las consecuencias que se produzca por su instalación o desinstalación.


    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.



    sábado, 17 de diciembre de 2016 17:33
    Moderador
  • "gemma_campillo" escribió:

    > Al final la llamada a la versión del motor la he dejado así, ...

    Buenos días, Gemma:

    ¡No me repitas código! Cuando en un mismo procedimiento, módulo o clase se duplica el código (que es lo que estás haciendo con el objeto Process), ese código es susceptible de ejecutarlo en un método aparte:

        Private Shared Function InstallAccessDatabaseEngine(version As VersionProveedorACE) As Boolean
    
            ' El método se encargará de instalar la versión redistribuible de los Componentes del
            ' motor de base de datos de Access que se corresponda con la versión especificada.
            '
            Dim rutaEjecutable As String = Application.StartupPath
    
            If (version = VersionProveedorACE.Access2007x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine07.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x64) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine_X64.exe”)
    
            End If
    
            Dim exited As Boolean
    
            Using proces As New Process()
                proces.StartInfo.FileName = rutaEjecutable
                proces.Start()
                proces.WaitForExit()
                exited = proces.HasExited
            End Using
    
            Return exited
    
        End Function

    Entiendo que el ejecutable correspondiente al motor de Access de 64 bits también se encuentra en una carpeta llamada "InstalacionMotorAccess", ya que en tu código no aparece dicha carpeta:

    >  proces.StartInfo.FileName = RutaEjecutable & “\AccessDatabaseEngine_X64.exe”

    Y ahora el procedimiento VersionAInstalarDeAccess se quedará mucho más reducido, claro y de fácil mantenimiento:

        Private Shared Sub VersionAInstalarDeAccess()
    
            ' Obtener la versión del motor de Access que hay que instalar.
            Dim versionAccess As VersionProveedorACE = MicrosoftAceHelper.VersionAccessParaInstalar()
    
            ' Si la versión es distinta de VersionProveedorACE.None, procedemos a su instalación.
            If (versionAccess <> VersionProveedorACE.None) Then
    
                Dim CrLf As String = Environment.NewLine
                Dim msg As String = String.Empty
                Dim respuesta As DialogResult
    
                If (versionAccess = VersionProveedorACE.Access2007x32) Then
                    msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                          "motor de base de datos correspondiente a Microsoft Access 2007 de 32 bits."
    
                ElseIf (versionAccess = VersionProveedorACE.Access2010x32) Then
                    msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                          "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                          "de 32 bits."
    
                ElseIf (versionAccess = VersionProveedorACE.Access2010x64) Then
                    msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                          "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                          "de 64 bits."
                End If
    
                ' El símbolo MessageBoxIcon.Question no se recomienda
                ' https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ES-ES&k=k(System.Windows.Forms.MessageBoxIcon.Question);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.6);k(DevLang-VB)&rd=true
                '
                respuesta = MessageBox.Show(msg & CrLf & CrLf & "¿Quiere proceder a su instalación?",
                                            "Financial System", MessageBoxButtons.OKCancel, MessageBoxIcon.Information)
    
                If (respuesta = DialogResult.OK) Then
                    Try
                        Dim exited As Boolean = InstallAccessDatabaseEngine(versionAccess)
                        If (exited) Then
                            msg = "El proceso de instalación del motor de Access finalizó correctamente." & CrLf &
                                  "Pulse para continuar."
                        End If
    
                    Catch ex As Exception
                        msg = "Error en instalación del motor Access Database.'" & CrLf & ex.Message & CrLf &
                              "Acepte para continuar."
                    End Try
    
                    MessageBox.Show(msg, "Financial System", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
                End If
    
            End If
    
        End Sub

    Prueba de nuevo, vaya a ser que me haya equivocado en alguna parte.


    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.





    domingo, 18 de diciembre de 2016 8:07
    Moderador
  • "gemma_campillo" escribió:

    > Bueno Enrique, sigo con ello y te envío una actualización
    > para que veas como ha quedado todo.

    ¡Espera, espera! ¡No tengas tantas prisas!

    Observo que:

        1º) Ejecutas tu aplicación

        2º) Si falta el motor de Access, inicias un nuevo proceso para instalarlo.

    Y digo yo que tu aplicación continua en ejecución hasta que finalice la instalación del motor de Access.

    Si es así, no veo yo muy normal que digamos que tu aplicación continúe en ejecución, porque lo correcto sería:

        3º) Cerrar la aplicación

        4º) Que el usuario la reinicie cuando haya finalizado el proceso de instalación del motor de Access.

    Ten en cuenta que tu aplicación necesita que se encuentren instalados los componentes necesarios, por lo que aquella tendrá que reiniciarse.

    Para ello, tendrías que lanzar el proceso de instalación del motor de Access en un subproceso diferente del subproceso actual de tu aplicación. Si lo deseas probar, modifica el procedimiento VersionAInstalarDeAccess por éste otro:

    Imports System.Threading

    Private Shared Sub VersionAInstalarDeAccess() ' Obtener la versión del motor de Access que hay que instalar. Dim versionAccess As VersionProveedorACE = MicrosoftAceHelper.VersionAccessParaInstalar() ' Si la versión es distinta de VersionProveedorACE.None, procedemos a su instalación. If (versionAccess <> VersionProveedorACE.None) Then Dim CrLf As String = Environment.NewLine Dim msg As String = String.Empty Dim respuesta As DialogResult If (versionAccess = VersionProveedorACE.Access2007x32) Then msg = "Se requiere que se encuentre instalado el Componente redistribuible del " & "motor de base de datos correspondiente a Microsoft Access 2007 de 32 bits." ElseIf (versionAccess = VersionProveedorACE.Access2010x32) Then msg = "Se requiere que se encuentre instalado el Componente redistribuible del " & "motor de base de datos correspondiente a Microsoft Access 2010 o superior " & "de 32 bits." ElseIf (versionAccess = VersionProveedorACE.Access2010x64) Then msg = "Se requiere que se encuentre instalado el Componente redistribuible del " & "motor de base de datos correspondiente a Microsoft Access 2010 o superior " & "de 64 bits." End If ' El símbolo MessageBoxIcon.Question no se recomienda ' https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ES-ES&k=k(System.Windows.Forms.MessageBoxIcon.Question);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.6);k(DevLang-VB)&rd=true ' respuesta = MessageBox.Show(msg & CrLf & CrLf & "¿Quiere proceder a su instalación?", "Financial System", MessageBoxButtons.OKCancel, MessageBoxIcon.Information) If (respuesta = DialogResult.OK) Then ' Creamos un subproceso. Dim t As New Thread(AddressOf InstallAccessDatabaseEngine) ' Iniciamos el proceso de instalación. t.Start(versionAccess) End If

                ' Se haya pulsado Aceptar o Cancelar, SIEMPRE cerramos nuestra aplicación,
    ' porque se supone que NO ESTÁN INSTALADOS los componentes requeridos.
    '
                Application.Exit() End If End Sub


    Y el método InstallAccessDatabaseEngine se encargaría exclusivamente de instalar los Componentes redistribuibles que se le hayan especificado, desapareciendo definitivamente tu aplicación del Administrador de tareas cuando el subproceso iniciado anteriormente haya finalizado, que se supone será cuando el programa de instalación de los componentes de Access haya terminado:

        Private Shared Sub InstallAccessDatabaseEngine(versionAccess As Object)
    
            ' El método se encargará de instalar la versión redistribuible de los Componentes del
            ' motor de base de datos de Access que se corresponda con la versión especificada.
            '
            Dim version As VersionProveedorACE = CType(versionAccess, VersionProveedorACE)
            Dim rutaEjecutable As String = Application.StartupPath
            Dim msg As String = String.Empty
            Dim CrLf As String = Environment.NewLine
    
            If (version = VersionProveedorACE.Access2007x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine07.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x64) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine_X64.exe”)
    
            End If
    
            Try
                Using proces As New Process()
                    proces.StartInfo.FileName = rutaEjecutable
                    proces.Start()
    
                    ' Esperar INDEFINIDAMENTE hasta que finalice el proceso asociado.
                    proces.WaitForExit()
    
                    ' Si el proceso se está ejecutando en un equipo remoto,
                    ' se desencadenará una NotSupportedException cuando se
                    ' acceda a la propiedad HasExited.
                    ' https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ES-ES&k=k(System.Diagnostics.Process.HasExited);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.6);k(DevLang-VB)&rd=true
                    '
                    ' Será mejor que no consultes el valor de la propiedad
                    ' HasExited, ya que ésta lo único que nos dice es si
                    ' ha terminado el proceso o no, pero no nos indica si
                    ' éste ha acabado satisfactoriamente o no, por lo que
                    ' evitamos que se produzca una NotSupoortedException en
                    ' el supuesto de que el proceso se esté ejecutando de
                    ' manera remota (en un equipo diferente al equipo local).
                    '
                    ' Dim exited As Boolean = proces.HasExited
                End Using
    
                ' Llegado aquí se supone que el proceso de instalación ha finalizado.
                '
                msg = "El proceso de instalación del motor de Access finalizó correctamente." & CrLf &
                      "Pulse para continuar."
    
            Catch ex As Exception
                msg = String.Format("Se ha producido un error en la instalación del motor Access.{0}'{1}'{2}Acepte para continuar.",
                                     CrLf, ex.Message, CrLf)
            End Try
    
            ' Evitar mostrar cualquier mensaje
            ' MessageBox.Show(msg, "Financial System", MessageBoxButtons.OK, MessageBoxIcon.Information)
            '
            ' En cualquier caso, lo correcto sería escribir aquí el mensaje (msg)
            ' en el archivo Log de nuestra aplicación.
    End Sub

    Igualmente entiendo que deberías de evitar mostrarle al usuario cualquier mensaje, tanto si se ha instalado satisfactoriamente como no los componentes de Access, ya que será el propio programa de instalación el que se lo indique.

    En todo caso, podrías indicar al final del procedimiento InstallAccessDatabaseEngine que se escriba la descripción del mensaje en el archivo Log de tu aplicación, si es que tienes alguno habilitado para ello, claro está. De todas maneras, lo dejo a tu elección.

    ¡Venga! Prueba de nuevo. ;-)


    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.





    domingo, 18 de diciembre de 2016 9:34
    Moderador
  • "gemma_campillo" escribió:

    > solo me quedará incorporarle el borrado automático del motor que tenga que ya se como se hace.
    >
    > Bueno, otra cosa, lo dejo como está y que el cliente decida que quiere hacer, menos complicaciones.

    ¡Ay! ¡Una sabia decisión!

    Imagina que un cliente tuyo tiene instalado los Componentes redistribuibles de Access 2007 porque tiene otro programa, diferente al tuyo, que lo utiliza para lo que le venga en gana, y ahora llega el programa de Gemma y se lo desinstala sin su permiso, dejándole "colgado" el otro programa. ¿Qué necesidad tienes de meterte en esos berenjenales? Lo mismo el programa continua funcionando si le instalas los Componentes de Access 2010 de 32 bits, pero creo que el ejemplo muestra que no hay que excederse en nuestros cometidos.

    Limítate a que tu programa haga su trabajo de la mejor manera posible, y deja que el cliente instale/desinstale con él estime oportuno. Tú te tienes que limitar a indicarle los requerimientos que necesita tu programa, y que él sea el que tome la decisión de instalarlos.

    > Solo utilizo la biblioteca Microsoft.Office.Interop.Excel para la importación de datos.

    Pero ¿eso no lo hacías con el ISAM para Excel del proveedor Microsoft.ACE.OLEDB.12.0? Si es así, para nada te sirve la citada biblioteca de Excel. ¿Has intentado eliminar la referencia y compilar de nuevo la aplicación para ver si aparecen errores relacionados con Excel? Antes de eliminarla, recuerda la versión que tienes referenciada por si tienes que volver a referenciarla ;-)


    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.




    sábado, 17 de diciembre de 2016 17:54
    Moderador
  • "gemma_campillo" escribió:

    > Solo que alguno de los que tienen que actualizar, tendrán el motor del
    > 2007 y van a tener que desinstalarlo e instalar el del 2010, pero eso
    > se lo haré saber en las instrucciones.

    Si desde tu programa se instalan/desinstalan otros programas, incluidos los Componentes redistribuibles de Access, digo yo que la cuenta del usuario que ejecute tu programa tendrá que pertenecer al grupo Administradores, porque si no es así, va a instalar/desinstalar lo que yo sé. ;-)

    Te comento que, afortunadamente, cada vez son más las empresas, pequeñas y grandes, que van restringiendo permisos a sus empleados en temas de ejecución, instalación y desintalación de programas, mayormente por temas de seguridad, de tal manera que las cuentas de estos son de usuarios normales y corrientes. Comento esto porque si tu aplicación requiere que se ejecute con permisos de Administrador, está claro que pocos usuarios van a poder ejecutarla satisfactoriamente, por lo que te llegarán las quejas de los clientes.

    Con todo esto te quiero decir, aunque no sea necesario hacer hincapié en el tema, que nuestras aplicaciones hay que procurar desarrollarlas para que sean ejecutadas por cuentas de usuarios con privilegios mínimos, salvo que estemos desarrollando una aplicación con fines de mantenimiento del sistema operativo, por poner un ejemplo, donde se requiere que la aplicación sea ejecutada necesariamente por una cuenta perteneciente al grupo Administradores, y de cuya ejecución se encargará la persona designada para administrar el sistema informático de la empresa.


    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.





    sábado, 17 de diciembre de 2016 18:23
    Moderador

Todas las respuestas

  • "gemma_campillo" preguntó:

    > Precisaría saber que motor de access tiene instalado el usuario, si bien es el
    > access 2007 o bien el 2010 o superior. Esto lo preciso para que el usuario pueda
    > instalarlo directamente desde el Submain y no tener que enviarlo a la dirección
    > de microsoft, etc., es decir al aceptar un cuadro de diálogo, ya lo redirijo a
    > dicha instalación.

    ¡Madre mía! ¿Todavía continuas con ese tema? Creía que ya estaba más que superado. :-(

    Mejor será que edites el Asunto de tu mensaje, porque más que saber si el usuario tiene instalado Office (que es de pago), entiendo que la pregunta se refiere a saber qué versión del motor de base de datos Microsoft.ACE.OLEDB.12.0 tiene instalado.

    Y la versión del citado proveedor dependerá de la versión de FinalcialSytem que ejecute el usuario, si ejecuta una versión de 32 o de 64 bits de FinalcialSystem.exe.

    Mira a ver si el siguiente esquema te despeja las dudas que observo continuas teniendo:

    Sistema Operativo Windows de 32 bits

    • Requerimientos:
      - FinalcialSytem de 32 bits
      - Access de 32 bits

           Si la función IsAceProviderInstalled devuelve False es porque no tiene instalado el motor de
           base de datos Microsoft.ACE.OLEDB.12.0 de 32 bits: --> Instalar Access 2007 o superior de 32 bits.

           - ¿Que no desea instalar Access?
              Entonces instalar el Componente redistribuible del motor de base de datos
              de Microsoft Access 2010 de 32 bits: AccessDatabaseEngine.exe

            https://www.microsoft.com/es-es/download/details.aspx?id=13255

    Sistema Operativo Windows de 64 bits

    • Requerimientos:
      - FinalcialSytem de 64 bits
      - Office de 64 bits

           Si la función IsAceProviderInstalled devuelve False es porque no tiene instalado el motor de
           base de datos Microsoft.ACE.OLEDB.12.0 de 64 bits: --> instalar Access 2010 o superior de 64 bits.

           - ¿Que no desea instalar Access?
              Entonces instalar el Componente redistribuible del motor de base de datos de
              Microsoft Access 2010 de 64 bits: AccessDatabaseEngine_X64.exe

             https://www.microsoft.com/es-es/download/details.aspx?id=13255

    Sistema Operativo Windows de 64 bits y Access de 32 bits instalado

    En este supuesto el usuario tiene un Windows de 64 bits, pero tiene instalada la versión de 32 bits del motor de base de datos Microsoft.ACE.OLEDB.12.0.

    • Requerimientos:
      - FinalcialSytem de 32 bits

        Aquí la función IsAceProviderInstalled devolverá True, y si devuelve False es porque estará ejecutando
        la versión de 64 bits de FinalcialSystem.exe.

        En éste supuesto especial, el usuario tiene que ejecutar la versión de 32 bits de FinalcialSytem, te guste o no te guste. ;-)


    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.





    sábado, 17 de diciembre de 2016 16:15
    Moderador
  • Hola Enrique:

    El tema ya lo tenía claro, lo que no tenía claro era por ejemplo en el caso de 32 bytes y el cliente tiene el office 2010 instalado y yo le estoy metiendo el 2007 entonces el tendrá que instalar el motor de access 2007.

    Mira lo que me has puesto es lo que necesita:

    >>

    Sistema Operativo Windows de 32 bits

    • Requerimientos:
      - FinancialSytem de 32 bits
      - Access de 32 bits

           Si la función IsAceProviderInstalled devuelve False es porque no tiene instalado el motor de
           base de datos Microsoft.ACE.OLEDB.12.0 de 32 bits: --> Instalar Access 2007 o superior de 32 bits.

           - ¿Que no desea instalar Access?
              Entonces instalar el Componente redistribuible del motor de base de datos
              de Microsoft Access 2010 de 32 bits: AccessDatabaseEngine.exe

    <<

    El cliente solo instalará el motor para base de datos 2007 o 2010 o superior. Eso se lo quiero hacer sin que tenga que acudir a buscarlo en las instrucciones y después en la web, de esta manera ya le indico que va a instalar tal motor o tal otro, tal como he hecho con el motor del SQL Compact y con el motor de los informes de Crystal Reports.

    Bueno, ahora lo tengo claro porque mediante el IsAceProviderInstalled detecto que es lo que le falta instalar si es que le falta algo.

    Bueno, ya está, voy a arreglarlo y lo dejo acabado.

    Te agradezco tu ayuda como siempre.

    Un fuerte abrazo.

    Gemma

    sábado, 17 de diciembre de 2016 16:31
  • "gemma_campillo" escribió:

    > El tema ya lo tenía claro, ...

    ¿Estás segura de ello? ;-)

    > ... lo que no tenía claro era por ejemplo en el caso de 32 bytes y el cliente
    > tiene el office 2010 instalado y yo le estoy metiendo el 2007 entonces el
    > tendrá que instalar el motor de access 2007.

    El Office 2010 instalado, ¿de 32 o de 64 bits? ¿Qué versión es la que tiene instalada?

    Aparte, no te debe interesar el Office que tiene instalado, porque de lo que estamos hablando es si el cliente tiene o no instalada la versión adecuada del proveedor de datos Microsoft.ACE.OLEDB.12.0, que es el que nos permite interactuar con bases de datos Microsoft Access, así como con algunos ISAM instalables (últimamente, para Excel y Texto).

    ¡Mujer! Piensa que si tiene instalada alguna versión profesional de Microsoft Office, puede que tenga instalado el citado proveedor porque se supone que tiene instalado Microsoft Access. Pero, ¿y si tiene una versión de Office estándar?

    Y entiendo que si el cliente tiene instalado el motor de datos de Access 2010, tú no deberías instalarle el motor de Access 2007, porque ¿para qué quieres hacer eso?

    Estás haciendo uso de la función llamada IsAceProviderInstalled, que precisamente te está indicando si el usuario tiene instalada una versión adecuada del proveedor Microsoft.ACE.OLEDB.12.0 para utilizarla con el proceso actual de tu aplicación. Pues tan solo tienes que leer el resultado de la función: True (todo está correcto); False (no está correcto: actuar en consecuencia).

    > El cliente solo instalará el motor para base de datos 2007 o 2010 o superior.
    > Eso se lo quiero hacer sin que tenga que acudir a buscarlo en las instrucciones
    > y después en la web, de esta manera ya le indico que va a instalar tal motor o
    > tal otro, tal como he hecho con el motor del SQL Compact y con el motor de los
    > informes de Crystal Reports.

    Olvídate de Access 2007. ¿Sabes para qué tiene sentido a fecha de hoy (17/12/2016) instalar exclusivamente los Componentes redistribuibles de Access 2007? Pues para una persona que tenga un sistema operativo de 64 bits, tenga instalado Access 2010 o superior de 64 bits, y se dedique al desarrollo de aplicaciones de bases de datos. Es decir, que tenga instalado Visual Studio (que es una aplicación de 32 bits) y desee hacer pruebas de su aplicación para 32 y 64 bits. Ese es mi caso, y posiblemente el de muchos de nosotros.

    Cuando desde Visual Studio compile su proyecto para 32 bits, estará utilizando los componentes de Access 2007 de 32 bits, y cuando compile su proyecto para 64 bits, utilizará los componentes de Access 2010 o superior de 64 bits. Si no se dan esas circunstancias, ¿para qué quieres instalarle a tu cliente una versión de Access que el próximo mes de enero cumplirá ¡¡10 años!!, que para una persona es nada, pero para una aplicación informática, es toda una vida. ;-)

    Ignoro si de tu aplicación tienes efectuadas dos compilaciones: una para 32 bits y otra para 64 bits. Pues dependiendo de lo que tu cliente tenga instalado en el equipo, así deberá de ADQUIRIR una u otra.


    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.


    sábado, 17 de diciembre de 2016 16:56
    Moderador
  • Hola Enrique:

    Mi versión de Access actual es la 2016, antes tenía la 2007 y si quiero hacer una actualización a los clientes que instalaron en su momento la de access 2007 para 32 bytes, ahora, será necesario cambiarla por la del motor 2010 o superior para 32 bytes. Eso lo he probado y funciona correctamente, ahora lo único que me quedará será borrar automáticamente la versión antigua del motor de access y sustituirla por la nueva, eso lo necesitaré hacer de desde el código para que el usuario no se moleste en hacer nada.

    Ten en cuenta que ahora la aplicación se distribuye con sql compact pero claro, si ha de importar datos desde Excel necesita el motor de access para 2010 o superior:" Componente de Access 2010: http://www.microsoft.com/es-es/download/details.aspx?id=13255".

    Entonces lo que tengo que mirar únicamente es instalarle ese motor y borrar el de 2007 si es que lo tenía instalado.

    Bueno, me pongo a ello para solucionarlo.

    Una brazo.

    Gemma


    sábado, 17 de diciembre de 2016 17:07
  • Vamos a ver si el siguiente código te proporciona una ayuda extra.

    Inserta en el archivo donde tienes definida la clase MicrosoftAceHelper, y ANTES DE SU DECLARACIÓN, la siguiente enumeración:

    Friend Enum VersionProveedorACE
        None = 0
        Access2007x32 = 1
        Access2010x32 = 2
        Access2010x64 = 3
    End Enum
    
    ' Aquí comienza la clase MicrosoftAceHelper
    '
    ' Friend Class MicrosoftAceHelper

    Y en la propia clase MicrosoftAceHelper, inserta esta función nueva:

        Friend Shared Function VersionAccessParaInstalar() As VersionProveedorACE
    
            ' Verificar si se encuentra instalado el proveedor de datos
            ' Microsoft.ACE.OLEDB.12.0, con independencia de la arquitectura
            ' que tenga el procesador actual.
            '
            Dim existe As Boolean = MicrosoftAceHelper.IsAceProviderInstalled()
    
            Dim version As VersionProveedorACE
    
            If (Not existe) Then
    
                ' Comprobar si el proceso actual de nuestra aplicación es de 64 bits.
                '
                If ((MicrosoftAceHelper.Is64BitProcess) AndAlso
                    ((MicrosoftAceHelper.Is64BitOperatingSystem) OrElse (MicrosoftAceHelper.IsIA64OperatingSystem))) Then
                    ' El proceso actual de nuesta aplicación es de 64 bits y el sistema operativo es
                    ' también de 64 bits o Intel Itanium: se requiere Access 2010 o superior de 64 bits.
                    '
                    version = VersionProveedorACE.Access2010x64
    
                ElseIf (MicrosoftAceHelper.Is32BitProcess) Then
                    ' El proceso actual de nuestra aplicación es de 32 bits, con independencia
                    ' que el sistema operativo sea de 32 o de 64 bits: se requiere Access 2007
                    ' o superior de 32 bits.
                    '
                    version = VersionProveedorACE.Access2010x32
    
                End If
    
            Else
                ' Se encuentra instalado el motor de base de datos Microsoft.ACE.OLEDB.12.0
                version = VersionProveedorACE.None
    
            End If
    
            Return version
    
        End Function

    Ahora, cuando desees obtener la versión de Access que hay que instalar, ejecutarías lo siguiente:

       Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    
            Dim CrLf As String = Environment.NewLine
    
            Dim versionOffice As VersionProveedorACE = MicrosoftAceHelper.VersionAccessParaInstalar()
    
            Dim msg As String = String.Empty
    
            If (versionOffice = VersionProveedorACE.Access2010x32) Then
                msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                    "motor de base de datos correspondiente a Microsoft Access 2007 o superior " &
                    "de 32 bits." & CrLf & CrLf &
                    "El componente de Access 2010 de 32 bits lo puede descargar desde el " &
                    "siguiente enlace: http://www.microsoft.com/es-es/download/details.aspx?id=13255"
    
            ElseIf (versionOffice = VersionProveedorACE.Access2010x64) Then
                msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                      "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                      "de 64 bits." & CrLf & CrLf &
                      "El componente de Access 2010 de 64 bits lo puede descargar desde el " &
                      "siguiente enlace: http://www.microsoft.com/es-es/download/details.aspx?id=13255"
            Else
                msg = "No se necesita ninguna version de Access."
    
            End If
    
            MessageBox.Show(msg)
    
        End Sub


    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.


    sábado, 17 de diciembre de 2016 17:12
    Moderador
  • Mientras tu escribías ésta respuesta yo te estaba respondiendo con otro mensaje.

    "gemma_campillo" escribió:

    > Ten en cuenta que ahora la aplicación se distribuye con sql compact pero claro,
    > si ha de importar datos desde Excel necesita el motor de access para 2010 o
    > superior:" Componente de Access 2010: http://www.microsoft.com/es-es/download/details.aspx?id=13255".

    Respóndeme a lo siguiente: ¿tienes una compilación de FinalcialSytem para 32 bits y otra para 64 bits, o solamente tiene una para 32 bits?


    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.

    sábado, 17 de diciembre de 2016 17:17
    Moderador
  • Hola maestro:

    Al final siempre me lo arreglas todo, eres la ostia. Estaba puesta en ello pero la experiencia en un grado amigo.

    Fíjate lo bien que queda que ahora se lo des too hecho al cliente, el va apretando botoncitos y todo a funcionar.

    Ya tengo hecha toda la conversión de tablas de access a decimal y después desde otra pantalla ya dentro de la aplicación, convierte la base en sql compact o sql server, va de película, me ha costado pero ahora va perfecto.

    Bueno, a lo que íbamos, voy ya a copiarlo directamente porque siempre está bien hecho y a ponerle los mensajes para que lo instale, nada.

    Maestro Enrique, solo me quedará incorporarle el borrado automático del motor que tenga que ya se como se hace.

    Muchas gracias como siempre querido amigo, eres un cascarrabias especial o muy especial para mí.

    Un abrazo maestro.

    Gemma

    sábado, 17 de diciembre de 2016 17:21
  • "gemma_campillo" escribió:

    > Mi versión de Access actual es la 2016, antes tenía la 2007 y si quiero hacer
    > una actualización a los clientes que instalaron en su momento la de access 2007
    > para 32 bytes, ahora, será necesario cambiarla por la del motor 2010 o superior
    > para 32 bytes. Eso lo he probado y funciona correctamente, ahora lo único que me
    > quedará será borrar automáticamente la versión antigua del motor de access y
    > sustituirla por la nueva, eso lo necesitaré hacer de desde el código para que el
    > usuario no se moleste en hacer nada.

    ¿Y qué tiene que ver que tú estés utilizando Access 2016 (32 o 64 bits) y un cliente tuyo tenga Access 2007 (sólo en versión de 32 bits)? Es como si me dices que viajas en un Mercedes y yo en un SEAT Panda. ¿Qué tiene que ver lo uno con lo otro? Y anteriormente escribías que tenías claro el tema. ¡Sí! ¡Ya lo veo! :-))

    ¡Vamos a ver, "Gemma de mi alma"! ¿Tu aplicación trabaja con los objetos propios de la biblioteca de objetos de Microsoft Access? ¿En tu proyecto tienes alguna referencia a la biblioteca Microsoft.Office.Interop.Access? Si no tienes la citada referencia, ¿qué más da que tu tengas instalado en tu equipo Access 2016 y un cliente Access 2007? Te repito por enésima vez que no estás trabajando con ninguna aplicación de Microsoft Office, que solamente estás trabajando con el proveedor de datos Microsoft.ACE.OLEDB.12.0, el cual se instala con Microsoft Access o con los Componentes redistribuibles de Access 2007 y de Access 2010, no existiendo éstos para versiones de Access 2013 o de Access 2016, salvo que yo esté equivocado o no sepa encontrarlos.

    Distinto sería que la versión de Access 2016 del citado proveedor incluyera nuevas características no disponibles en versiones anteriores, y encima, tu las utilizaras en tu programa. En este caso sí tendrías que actualizarle al cliente el "dichoso" proveedor. Pero si no es así, no tienes por qué actualizarle nada.

    Eso sí. Cierta vez te comenté que si le has establecido una contraseña a la base de datos de Access mediante el propio Access 2010 o superior, entonces esa base de datos no se va a poder abrir con Access 2007. ¿Te acuerdas?

    > Entonces lo que tengo que mirar únicamente es instalarle ese motor y borrar
    > el de 2007 si es que lo tenía instalado.

    Yo que tú no desinstalaría nada, y tampoco lo instalaría. Que sea el cliente el que tome esa decisión y asuma las consecuencias que se produzca por su instalación o desinstalación.


    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.



    sábado, 17 de diciembre de 2016 17:33
    Moderador
  • Hola:

    Que lo tengo claro ahora más que antes. Solo utilizo la biblioteca Microsoft.Office.Interop.Excel

    para la importación de datos.

    Bueno, otra cosa, lo dejo como está y que el cliente decida que quiere hacer, menos complicaciones.

    Maestro, gracias otra vez y si a veces te digo que si lo entiendo, casi siempre lo entiendo, es para que no te cabrees, porque ya sabes que soy a veces dura de mollera y si te digo cualquier barbaridad te cabreas y con razón.

    En fin, deja de trabajar un rato para los demás y descansa o ve la tele o vete a comprar los turrones.

    Un abrazo querido amigo.

    Gemma

    sábado, 17 de diciembre de 2016 17:41
  • "gemma_campillo" escribió:

    > solo me quedará incorporarle el borrado automático del motor que tenga que ya se como se hace.
    >
    > Bueno, otra cosa, lo dejo como está y que el cliente decida que quiere hacer, menos complicaciones.

    ¡Ay! ¡Una sabia decisión!

    Imagina que un cliente tuyo tiene instalado los Componentes redistribuibles de Access 2007 porque tiene otro programa, diferente al tuyo, que lo utiliza para lo que le venga en gana, y ahora llega el programa de Gemma y se lo desinstala sin su permiso, dejándole "colgado" el otro programa. ¿Qué necesidad tienes de meterte en esos berenjenales? Lo mismo el programa continua funcionando si le instalas los Componentes de Access 2010 de 32 bits, pero creo que el ejemplo muestra que no hay que excederse en nuestros cometidos.

    Limítate a que tu programa haga su trabajo de la mejor manera posible, y deja que el cliente instale/desinstale con él estime oportuno. Tú te tienes que limitar a indicarle los requerimientos que necesita tu programa, y que él sea el que tome la decisión de instalarlos.

    > Solo utilizo la biblioteca Microsoft.Office.Interop.Excel para la importación de datos.

    Pero ¿eso no lo hacías con el ISAM para Excel del proveedor Microsoft.ACE.OLEDB.12.0? Si es así, para nada te sirve la citada biblioteca de Excel. ¿Has intentado eliminar la referencia y compilar de nuevo la aplicación para ver si aparecen errores relacionados con Excel? Antes de eliminarla, recuerda la versión que tienes referenciada por si tienes que volver a referenciarla ;-)


    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.




    sábado, 17 de diciembre de 2016 17:54
    Moderador
  • ¡Ay! ¡Una sabia decisión!

    Si, si. Tal como está, que va perfecto. No me meto en más historias.

    Solo que alguno de los que tienen que actualizar, tendrán el motor del 2007 y van a tener que desinstalarlo e instalar el del 2010, pero eso se lo haré saber en las instrucciones.

    Un abrazo.

    Gemma

    sábado, 17 de diciembre de 2016 18:00
  • "gemma_campillo" escribió:

    > Solo que alguno de los que tienen que actualizar, tendrán el motor del
    > 2007 y van a tener que desinstalarlo e instalar el del 2010, pero eso
    > se lo haré saber en las instrucciones.

    Si desde tu programa se instalan/desinstalan otros programas, incluidos los Componentes redistribuibles de Access, digo yo que la cuenta del usuario que ejecute tu programa tendrá que pertenecer al grupo Administradores, porque si no es así, va a instalar/desinstalar lo que yo sé. ;-)

    Te comento que, afortunadamente, cada vez son más las empresas, pequeñas y grandes, que van restringiendo permisos a sus empleados en temas de ejecución, instalación y desintalación de programas, mayormente por temas de seguridad, de tal manera que las cuentas de estos son de usuarios normales y corrientes. Comento esto porque si tu aplicación requiere que se ejecute con permisos de Administrador, está claro que pocos usuarios van a poder ejecutarla satisfactoriamente, por lo que te llegarán las quejas de los clientes.

    Con todo esto te quiero decir, aunque no sea necesario hacer hincapié en el tema, que nuestras aplicaciones hay que procurar desarrollarlas para que sean ejecutadas por cuentas de usuarios con privilegios mínimos, salvo que estemos desarrollando una aplicación con fines de mantenimiento del sistema operativo, por poner un ejemplo, donde se requiere que la aplicación sea ejecutada necesariamente por una cuenta perteneciente al grupo Administradores, y de cuya ejecución se encargará la persona designada para administrar el sistema informático de la empresa.


    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.





    sábado, 17 de diciembre de 2016 18:23
    Moderador
  • Hola Enrique:

    Efectivamente la aplicación no requiere permisos de administrador. Así lo tengo el app.manifest y funciona perfectamente, por ahí no hay problemas.

    De cualquier forma, gracias por recordármelo que siempre van bien tus didácticas explicaciones, ya lo sabes.

    Un abrazo querido amigo.

    Gemma

    sábado, 17 de diciembre de 2016 21:09
  • Hola maestro, buenos días:

    Ya está todo funcionando correctamente. He hecho varias pruebas y no da ninguna excepción.

    Al final la llamada a la versión del motor la he dejado así, aunque entiendo que el if del 2007 sobre, pero bueno, lo dejo así y solo he cambiado el nombre de la descarga añadiéndole el 07, ya que el nombre del ejecutable es el mismo que para la versión 2010 de 32 bytes.

    Private Shared Sub VersionAInstalarDeAccess()
            Try
                Dim respuesta As DialogResult
                Dim RutaEjecutable As String = Application.StartupPath
    
                Dim CrLf As String = Environment.NewLine
    
                Dim versionOffice As VersionProveedorACE = MicrosoftAceHelper.VersionAccessParaInstalar()
    
                ' Dim msg As String = String.Empty
                If (versionOffice = VersionProveedorACE.Access2007x32) Then
                    respuesta = MessageBox.Show("Se requiere que se encuentre instalado el Componente redistribuible del " &
                        "motor de base de datos correspondiente a Microsoft Access 2007  " &
                        "de 32 bits." & CrLf & CrLf & "¿Quiere proceder a su instalación?", "Financial System", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)
    
                    If respuesta = System.Windows.Forms.DialogResult.Cancel Then
                        Return
                    Else
                        Dim proces As New Process()
                        proces.StartInfo.FileName = RutaEjecutable & “\InstalacionMotorAccess\AccessDatabaseEngine07.exe”
                        proces.Start()
                        proces.WaitForExit()
                        If proces.HasExited Then
                            respuesta = MessageBox.Show("El proceso de instalación del motor de Access, finalizó correctamente." & vbCrLf &
                                "Pulse para continuar.", "Financial System", MessageBoxButtons.OK, MessageBoxIcon.Information)
                        End If
                    End If
    
                ElseIf (versionOffice = VersionProveedorACE.Access2010x32) Then
                    respuesta = MessageBox.Show("Se requiere que se encuentre instalado el Componente redistribuible del " &
                        "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                        "de 32 bits." & CrLf & CrLf & "¿Quiere proceder a su instalación?", "Financial System", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)
    
                    If respuesta = System.Windows.Forms.DialogResult.Cancel Then
                        Return
                    Else
                        Dim proces As New Process()
                        proces.StartInfo.FileName = RutaEjecutable & “\InstalacionMotorAccess\AccessDatabaseEngine.exe”
                        proces.Start()
                        proces.WaitForExit()
                        If proces.HasExited Then
                            respuesta = MessageBox.Show("El proceso de instalación del motor de Access, finalizó correctamente." & vbCrLf &
                                "Pulse para continuar.", "Financial System", MessageBoxButtons.OK, MessageBoxIcon.Information)
                        End If
                    End If
    
                ElseIf (versionOffice = VersionProveedorACE.Access2010x64) Then
                    respuesta = MessageBox.Show("Se requiere que se encuentre instalado el Componente redistribuible del " &
                      "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                      "de 64 bits." & CrLf & CrLf & "¿Quiere proceder a su instalación?", "Financial System", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)
    
                    If respuesta = System.Windows.Forms.DialogResult.Cancel Then
                        Return
                    Else
                        Dim proces As New Process()
                        proces.StartInfo.FileName = RutaEjecutable & “\AccessDatabaseEngine_X64.exe”
                        proces.Start()
                        proces.WaitForExit()
                        If proces.HasExited Then
                            respuesta = MessageBox.Show("El proceso de instalación del motor de Access, finalizó correctamente." & vbCrLf &
                                "Pulse para continuar.", "Financial System", MessageBoxButtons.OK, MessageBoxIcon.Information)
                        End If
                    End If
    
                End If
    
            Catch ex As Exception
                MessageBox.Show("Error en instalación del motor Access Database'" & vbCrLf & ex.Message & vbCrLf &
                   "Acepte para continuar.", "FINANCIAL SYSTEM", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End Sub

    He puesto los ejecutables en una carpeta (ya lo ves en la ruta) y nada más. He borrado desde el panel de control el motor y lo vuelve a crear sin problemas. Ahora ya lo tengo todo automatizado para el usuario, el programa le va pidiendo si tiene que instalar el SqlCompact, el motor de los informes o el motor del access.

    Un fuerte abrazo.

    Gemma

    domingo, 18 de diciembre de 2016 5:44
  • "gemma_campillo" escribió:

    > Al final la llamada a la versión del motor la he dejado así, ...

    Buenos días, Gemma:

    ¡No me repitas código! Cuando en un mismo procedimiento, módulo o clase se duplica el código (que es lo que estás haciendo con el objeto Process), ese código es susceptible de ejecutarlo en un método aparte:

        Private Shared Function InstallAccessDatabaseEngine(version As VersionProveedorACE) As Boolean
    
            ' El método se encargará de instalar la versión redistribuible de los Componentes del
            ' motor de base de datos de Access que se corresponda con la versión especificada.
            '
            Dim rutaEjecutable As String = Application.StartupPath
    
            If (version = VersionProveedorACE.Access2007x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine07.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x64) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine_X64.exe”)
    
            End If
    
            Dim exited As Boolean
    
            Using proces As New Process()
                proces.StartInfo.FileName = rutaEjecutable
                proces.Start()
                proces.WaitForExit()
                exited = proces.HasExited
            End Using
    
            Return exited
    
        End Function

    Entiendo que el ejecutable correspondiente al motor de Access de 64 bits también se encuentra en una carpeta llamada "InstalacionMotorAccess", ya que en tu código no aparece dicha carpeta:

    >  proces.StartInfo.FileName = RutaEjecutable & “\AccessDatabaseEngine_X64.exe”

    Y ahora el procedimiento VersionAInstalarDeAccess se quedará mucho más reducido, claro y de fácil mantenimiento:

        Private Shared Sub VersionAInstalarDeAccess()
    
            ' Obtener la versión del motor de Access que hay que instalar.
            Dim versionAccess As VersionProveedorACE = MicrosoftAceHelper.VersionAccessParaInstalar()
    
            ' Si la versión es distinta de VersionProveedorACE.None, procedemos a su instalación.
            If (versionAccess <> VersionProveedorACE.None) Then
    
                Dim CrLf As String = Environment.NewLine
                Dim msg As String = String.Empty
                Dim respuesta As DialogResult
    
                If (versionAccess = VersionProveedorACE.Access2007x32) Then
                    msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                          "motor de base de datos correspondiente a Microsoft Access 2007 de 32 bits."
    
                ElseIf (versionAccess = VersionProveedorACE.Access2010x32) Then
                    msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                          "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                          "de 32 bits."
    
                ElseIf (versionAccess = VersionProveedorACE.Access2010x64) Then
                    msg = "Se requiere que se encuentre instalado el Componente redistribuible del " &
                          "motor de base de datos correspondiente a Microsoft Access 2010 o superior " &
                          "de 64 bits."
                End If
    
                ' El símbolo MessageBoxIcon.Question no se recomienda
                ' https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ES-ES&k=k(System.Windows.Forms.MessageBoxIcon.Question);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.6);k(DevLang-VB)&rd=true
                '
                respuesta = MessageBox.Show(msg & CrLf & CrLf & "¿Quiere proceder a su instalación?",
                                            "Financial System", MessageBoxButtons.OKCancel, MessageBoxIcon.Information)
    
                If (respuesta = DialogResult.OK) Then
                    Try
                        Dim exited As Boolean = InstallAccessDatabaseEngine(versionAccess)
                        If (exited) Then
                            msg = "El proceso de instalación del motor de Access finalizó correctamente." & CrLf &
                                  "Pulse para continuar."
                        End If
    
                    Catch ex As Exception
                        msg = "Error en instalación del motor Access Database.'" & CrLf & ex.Message & CrLf &
                              "Acepte para continuar."
                    End Try
    
                    MessageBox.Show(msg, "Financial System", MessageBoxButtons.OK, MessageBoxIcon.Information)
    
                End If
    
            End If
    
        End Sub

    Prueba de nuevo, vaya a ser que me haya equivocado en alguna parte.


    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.





    domingo, 18 de diciembre de 2016 8:07
    Moderador
  • Hola maestro:

    Claro, el código queda mucho mejor, no había reparado en ello.

    También me había dejado el poner la carpeta para el de 64 bits.

    Bueno maestro, muchas gracias, ahora queda mucho más limpio y fácil de leer.

    Siempre aprendo cosas contigo.

    También al usuario se le facilita mucho las cosas al ver que la propia aplicación le va diciendo las cosas que necesita ir haciendo en la instalación, sin enviarlo a ningún lado, el va aceptando y ya está.

    Bueno Enrique, sigo con ello y te envío una actualización para que veas como ha quedado todo.

    Un fuerte abrazo querido amigo.

    Gemma

    domingo, 18 de diciembre de 2016 8:50
  • "gemma_campillo" escribió:

    > Bueno Enrique, sigo con ello y te envío una actualización
    > para que veas como ha quedado todo.

    ¡Espera, espera! ¡No tengas tantas prisas!

    Observo que:

        1º) Ejecutas tu aplicación

        2º) Si falta el motor de Access, inicias un nuevo proceso para instalarlo.

    Y digo yo que tu aplicación continua en ejecución hasta que finalice la instalación del motor de Access.

    Si es así, no veo yo muy normal que digamos que tu aplicación continúe en ejecución, porque lo correcto sería:

        3º) Cerrar la aplicación

        4º) Que el usuario la reinicie cuando haya finalizado el proceso de instalación del motor de Access.

    Ten en cuenta que tu aplicación necesita que se encuentren instalados los componentes necesarios, por lo que aquella tendrá que reiniciarse.

    Para ello, tendrías que lanzar el proceso de instalación del motor de Access en un subproceso diferente del subproceso actual de tu aplicación. Si lo deseas probar, modifica el procedimiento VersionAInstalarDeAccess por éste otro:

    Imports System.Threading

    Private Shared Sub VersionAInstalarDeAccess() ' Obtener la versión del motor de Access que hay que instalar. Dim versionAccess As VersionProveedorACE = MicrosoftAceHelper.VersionAccessParaInstalar() ' Si la versión es distinta de VersionProveedorACE.None, procedemos a su instalación. If (versionAccess <> VersionProveedorACE.None) Then Dim CrLf As String = Environment.NewLine Dim msg As String = String.Empty Dim respuesta As DialogResult If (versionAccess = VersionProveedorACE.Access2007x32) Then msg = "Se requiere que se encuentre instalado el Componente redistribuible del " & "motor de base de datos correspondiente a Microsoft Access 2007 de 32 bits." ElseIf (versionAccess = VersionProveedorACE.Access2010x32) Then msg = "Se requiere que se encuentre instalado el Componente redistribuible del " & "motor de base de datos correspondiente a Microsoft Access 2010 o superior " & "de 32 bits." ElseIf (versionAccess = VersionProveedorACE.Access2010x64) Then msg = "Se requiere que se encuentre instalado el Componente redistribuible del " & "motor de base de datos correspondiente a Microsoft Access 2010 o superior " & "de 64 bits." End If ' El símbolo MessageBoxIcon.Question no se recomienda ' https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ES-ES&k=k(System.Windows.Forms.MessageBoxIcon.Question);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.6);k(DevLang-VB)&rd=true ' respuesta = MessageBox.Show(msg & CrLf & CrLf & "¿Quiere proceder a su instalación?", "Financial System", MessageBoxButtons.OKCancel, MessageBoxIcon.Information) If (respuesta = DialogResult.OK) Then ' Creamos un subproceso. Dim t As New Thread(AddressOf InstallAccessDatabaseEngine) ' Iniciamos el proceso de instalación. t.Start(versionAccess) End If

                ' Se haya pulsado Aceptar o Cancelar, SIEMPRE cerramos nuestra aplicación,
    ' porque se supone que NO ESTÁN INSTALADOS los componentes requeridos.
    '
                Application.Exit() End If End Sub


    Y el método InstallAccessDatabaseEngine se encargaría exclusivamente de instalar los Componentes redistribuibles que se le hayan especificado, desapareciendo definitivamente tu aplicación del Administrador de tareas cuando el subproceso iniciado anteriormente haya finalizado, que se supone será cuando el programa de instalación de los componentes de Access haya terminado:

        Private Shared Sub InstallAccessDatabaseEngine(versionAccess As Object)
    
            ' El método se encargará de instalar la versión redistribuible de los Componentes del
            ' motor de base de datos de Access que se corresponda con la versión especificada.
            '
            Dim version As VersionProveedorACE = CType(versionAccess, VersionProveedorACE)
            Dim rutaEjecutable As String = Application.StartupPath
            Dim msg As String = String.Empty
            Dim CrLf As String = Environment.NewLine
    
            If (version = VersionProveedorACE.Access2007x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine07.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x32) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine.exe")
    
            ElseIf (version = VersionProveedorACE.Access2010x64) Then
                rutaEjecutable = IO.Path.Combine(rutaEjecutable, "InstalacionMotorAccess\AccessDatabaseEngine_X64.exe”)
    
            End If
    
            Try
                Using proces As New Process()
                    proces.StartInfo.FileName = rutaEjecutable
                    proces.Start()
    
                    ' Esperar INDEFINIDAMENTE hasta que finalice el proceso asociado.
                    proces.WaitForExit()
    
                    ' Si el proceso se está ejecutando en un equipo remoto,
                    ' se desencadenará una NotSupportedException cuando se
                    ' acceda a la propiedad HasExited.
                    ' https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ES-ES&k=k(System.Diagnostics.Process.HasExited);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.6);k(DevLang-VB)&rd=true
                    '
                    ' Será mejor que no consultes el valor de la propiedad
                    ' HasExited, ya que ésta lo único que nos dice es si
                    ' ha terminado el proceso o no, pero no nos indica si
                    ' éste ha acabado satisfactoriamente o no, por lo que
                    ' evitamos que se produzca una NotSupoortedException en
                    ' el supuesto de que el proceso se esté ejecutando de
                    ' manera remota (en un equipo diferente al equipo local).
                    '
                    ' Dim exited As Boolean = proces.HasExited
                End Using
    
                ' Llegado aquí se supone que el proceso de instalación ha finalizado.
                '
                msg = "El proceso de instalación del motor de Access finalizó correctamente." & CrLf &
                      "Pulse para continuar."
    
            Catch ex As Exception
                msg = String.Format("Se ha producido un error en la instalación del motor Access.{0}'{1}'{2}Acepte para continuar.",
                                     CrLf, ex.Message, CrLf)
            End Try
    
            ' Evitar mostrar cualquier mensaje
            ' MessageBox.Show(msg, "Financial System", MessageBoxButtons.OK, MessageBoxIcon.Information)
            '
            ' En cualquier caso, lo correcto sería escribir aquí el mensaje (msg)
            ' en el archivo Log de nuestra aplicación.
    End Sub

    Igualmente entiendo que deberías de evitar mostrarle al usuario cualquier mensaje, tanto si se ha instalado satisfactoriamente como no los componentes de Access, ya que será el propio programa de instalación el que se lo indique.

    En todo caso, podrías indicar al final del procedimiento InstallAccessDatabaseEngine que se escriba la descripción del mensaje en el archivo Log de tu aplicación, si es que tienes alguno habilitado para ello, claro está. De todas maneras, lo dejo a tu elección.

    ¡Venga! Prueba de nuevo. ;-)


    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.





    domingo, 18 de diciembre de 2016 9:34
    Moderador
  • Hola Enrique:

    Ya está corregido y funciona perfectamente.

    Me parecía a mi o creía, que no era necesario reiniciar la aplicación, pero se ve que estaba equivocada.

    Bueno, ahora está todo tal como me has indicado y el también creía que si el proceso "proces.HasExited" era correcto, quería decir que se había instalado todo correctamente. Bueno, hoy es día de aprendizaje como siempre. Cuantas cosas tiene el .NET que desconozco o me creo una osa y después no es. En fin...

    Gracias otra vez maestro, cada vez está más perfecto el tema este.

    Un fuerte abrazo como siempre.

    Gemma

    domingo, 18 de diciembre de 2016 10:32