none
En propiedades del proyecto hay una opción Convertir aplicación de instancia única ¿dónde se puede ver el código que hace esa conversión?

    Pregunta

  • Me refiero a esta opción de la opción Aplicación, de Propiedades del proyecto:

    ¿es posible ver el código que hace que la aplicación sea de instancia única?

    martes, 1 de noviembre de 2016 23:17

Respuestas

  • "James-2016" escribió:

    > es que al inicializar el proyecto desde un procedimiento Sub Main es
    > necesario deshabilitar el marco de trabajo de la aplicación y con eso
    > ya no hay la posibilidad de activar la opción Convertir la aplicación
    > de instancia única.
    >
    > Entonces la consulta es que aún iniciando desde Sub Main, si cambio el
    > valor de esa propiedad, vía código, igual puedo hacer que la aplicación
    > sea de instancia única? y ese valor lo puedo cambiar desde un módulo o
    > desde un formulario cualquiera?

    Si no tienes habilitado el marco de trabajo de la aplicación no puedes acceder a la propiedad IsSingleInstance; tienes que comprobar si la aplicación se está ejecutando en un proceso para activarla cuando el usuario intente crear una segunda instancia de la misma. Y esto mismo hace ya unos cuantos años nos lo enseñó el maestro Eduardo A. Morcillo:

    Comprobar si hay una instancia previa de nuestra aplicación

    Crea en tu proyecto una nueva clase y "pegas" el código que aparece en el enlace indicado:

    Imports System.Reflection
    Imports System.Runtime.InteropServices
    Imports System.Threading
    
    ''' <summary>
    ''' Comprobar si hay una instancia previa de nuestra aplicación
    ''' </summary>
    ''' <author>Eduardo A. Morcillo</author>
    ''' <remarks>http://www.mvps.org/emorcillo/es/codigo/grl/previnst.shtml</remarks>
    Public NotInheritable Class PrevInstance
    
        <DllImport("user32.dll")>
        Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
        End Function
    
        Private Shared _mutex As Mutex
        Private Shared _owned As Boolean
    
        Shared Sub New()
    
            ' Get the full name of the assembly
            ' that started the process
            Dim name As String = Assembly.GetEntryAssembly().FullName
    
            ' Create a mutex using the assembly name.
            ' After the call _owned will be True if this thread 
            ' created and owns the mutex. Otherwise it will be 
            ' False, which means that a previous instance created it.
            _mutex = New Mutex(True, name, _owned)
    
        End Sub
    
        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Returns whether a previous instance of the process exists.
        ''' </summary>
        ''' <history>
        '''  [Eduardo Morcillo] 01/11/2004 Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Shared ReadOnly Property Exists() As Boolean
            Get
                Return Not _owned
            End Get
        End Property
    
        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Returns an instance of System.Diagnostics.Process that represents the
        ''' previous instance process.
        ''' </summary>
        ''' <history>
        '''  [Eduardo Morcillo] 01/11/2004 Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Private Shared ReadOnly Property Process() As Process
            Get
                If (Not _owned) Then
    
                    ' Get the current process
                    Dim currentProcess As Process = Process.GetCurrentProcess
    
                    ' Get the processes with the name of current process
                    Dim processes() As Process = Process.GetProcessesByName(currentProcess.ProcessName)
    
                    ' Enumerate the processes
                    For Each proc As Process In processes
    
                        ' Check if the process is not the current process
                        If (proc.Id <> currentProcess.Id) Then
    
                            ' Dispose the objects
                            currentProcess.Dispose()
    
                            Return proc
    
                        End If
    
                    Next
    
                End If
    
                Return Nothing
            End Get
        End Property
    
        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Activates the previous instance window.
        ''' </summary>
        ''' <returns>Whether the window was activated or not.</returns>
        ''' <history>
        '''  [Eduardo Morcillo] 01/11/2004 Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Shared Function Activate() As Boolean
    
            Dim prev As Process = PrevInstance.Process
            Dim flag As Boolean
    
            If (Not prev Is Nothing) Then
    
                ' Refresh the process object to ensure
                ' it contains a valid window handle
                prev.Refresh()
    
                ' Set the foreground window 
                flag = SetForegroundWindow(prev.MainWindowHandle())
    
                ' Dispose the object
                prev.Dispose()
    
            End If
    
            Return flag
    
        End Function
    
    End Class
    

    Y ahora, en el procedimiento Sub Main de inicio de tu aplicación, ejecuta lo siguiente:

    Public Module Module1 Friend Sub Main() If (Not PrevInstance.Exists) Then ' No existe una instancia previa de la aplicación. ' Habilitamos los estilos visuales Application.EnableVisualStyles() ' Mostramos el formulario de inicio de la aplicación. Application.Run(New Form1())

            ' Se ha cerrado el formulario de inicio; si
            ' procede, guardamos My.Settings al cerrar.
            '
            ' My.Settings.Save()

    Else ' Existe una instancia previa de la aplicación; la activamos PrevInstance.Activate() End If

    End Sub End Module



    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.

    • Marcado como respuesta James-2016 jueves, 3 de noviembre de 2016 20:55
    jueves, 3 de noviembre de 2016 20:25
    Moderador

Todas las respuestas

  • "James-2016" preguntó:

    > En propiedades del proyecto hay una opción Convertir aplicación de instancia
    > única ¿dónde se puede ver el código que hace esa conversión?

    La verdad es que no sé a qué código te refieres, porque si habilitas la opción que comentas, lo único que harás es establecer el valor True a la propiedad IsSingleInstance del objeto My.Application, y si no la habilitas el valor será False, que es el valor predeterminado.

    Si deseas ver el código donde se asigna el valor True/False a dicha propiedad, abre el archivo Application.Designer.vb del proyecto y dirígete al constructor del objeto MyApplication:


    Dicho archivo se encuentra oculto. Para mostrar su contenido, haz clic con el ratón sobre el icono que indica "Mostrar todos los archivos" que aparece en la ventana Explorador de soluciones, haciendo posteriormente doble clic para abrirlo en el editor de Visual Studio.


    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, 3 de noviembre de 2016 16:05
    Moderador
  • ah ok, es una propiedad y es que al inicializar el proyecto desde un procedimiento Sub Main es necesario deshabilitar el marco de trabajo de la aplicación y con eso ya no hay la posibilidad de activar la opción Convertir la aplicación de instancia única.

    Entonces la consulta es que aún iniciando desde Sub Main, si cambio el valor de esa propiedad, vía código, igual puedo hacer que la aplicación sea de instancia única? y ese valor lo puedo cambiar desde un módulo o desde un formulario cualquiera?




    • Editado James-2016 jueves, 3 de noviembre de 2016 18:30
    jueves, 3 de noviembre de 2016 18:09
  • "James-2016" escribió:

    > es que al inicializar el proyecto desde un procedimiento Sub Main es
    > necesario deshabilitar el marco de trabajo de la aplicación y con eso
    > ya no hay la posibilidad de activar la opción Convertir la aplicación
    > de instancia única.
    >
    > Entonces la consulta es que aún iniciando desde Sub Main, si cambio el
    > valor de esa propiedad, vía código, igual puedo hacer que la aplicación
    > sea de instancia única? y ese valor lo puedo cambiar desde un módulo o
    > desde un formulario cualquiera?

    Si no tienes habilitado el marco de trabajo de la aplicación no puedes acceder a la propiedad IsSingleInstance; tienes que comprobar si la aplicación se está ejecutando en un proceso para activarla cuando el usuario intente crear una segunda instancia de la misma. Y esto mismo hace ya unos cuantos años nos lo enseñó el maestro Eduardo A. Morcillo:

    Comprobar si hay una instancia previa de nuestra aplicación

    Crea en tu proyecto una nueva clase y "pegas" el código que aparece en el enlace indicado:

    Imports System.Reflection
    Imports System.Runtime.InteropServices
    Imports System.Threading
    
    ''' <summary>
    ''' Comprobar si hay una instancia previa de nuestra aplicación
    ''' </summary>
    ''' <author>Eduardo A. Morcillo</author>
    ''' <remarks>http://www.mvps.org/emorcillo/es/codigo/grl/previnst.shtml</remarks>
    Public NotInheritable Class PrevInstance
    
        <DllImport("user32.dll")>
        Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
        End Function
    
        Private Shared _mutex As Mutex
        Private Shared _owned As Boolean
    
        Shared Sub New()
    
            ' Get the full name of the assembly
            ' that started the process
            Dim name As String = Assembly.GetEntryAssembly().FullName
    
            ' Create a mutex using the assembly name.
            ' After the call _owned will be True if this thread 
            ' created and owns the mutex. Otherwise it will be 
            ' False, which means that a previous instance created it.
            _mutex = New Mutex(True, name, _owned)
    
        End Sub
    
        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Returns whether a previous instance of the process exists.
        ''' </summary>
        ''' <history>
        '''  [Eduardo Morcillo] 01/11/2004 Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Shared ReadOnly Property Exists() As Boolean
            Get
                Return Not _owned
            End Get
        End Property
    
        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Returns an instance of System.Diagnostics.Process that represents the
        ''' previous instance process.
        ''' </summary>
        ''' <history>
        '''  [Eduardo Morcillo] 01/11/2004 Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Private Shared ReadOnly Property Process() As Process
            Get
                If (Not _owned) Then
    
                    ' Get the current process
                    Dim currentProcess As Process = Process.GetCurrentProcess
    
                    ' Get the processes with the name of current process
                    Dim processes() As Process = Process.GetProcessesByName(currentProcess.ProcessName)
    
                    ' Enumerate the processes
                    For Each proc As Process In processes
    
                        ' Check if the process is not the current process
                        If (proc.Id <> currentProcess.Id) Then
    
                            ' Dispose the objects
                            currentProcess.Dispose()
    
                            Return proc
    
                        End If
    
                    Next
    
                End If
    
                Return Nothing
            End Get
        End Property
    
        ''' -----------------------------------------------------------------------------
        ''' <summary>
        ''' Activates the previous instance window.
        ''' </summary>
        ''' <returns>Whether the window was activated or not.</returns>
        ''' <history>
        '''  [Eduardo Morcillo] 01/11/2004 Created
        ''' </history>
        ''' -----------------------------------------------------------------------------
        Public Shared Function Activate() As Boolean
    
            Dim prev As Process = PrevInstance.Process
            Dim flag As Boolean
    
            If (Not prev Is Nothing) Then
    
                ' Refresh the process object to ensure
                ' it contains a valid window handle
                prev.Refresh()
    
                ' Set the foreground window 
                flag = SetForegroundWindow(prev.MainWindowHandle())
    
                ' Dispose the object
                prev.Dispose()
    
            End If
    
            Return flag
    
        End Function
    
    End Class
    

    Y ahora, en el procedimiento Sub Main de inicio de tu aplicación, ejecuta lo siguiente:

    Public Module Module1 Friend Sub Main() If (Not PrevInstance.Exists) Then ' No existe una instancia previa de la aplicación. ' Habilitamos los estilos visuales Application.EnableVisualStyles() ' Mostramos el formulario de inicio de la aplicación. Application.Run(New Form1())

            ' Se ha cerrado el formulario de inicio; si
            ' procede, guardamos My.Settings al cerrar.
            '
            ' My.Settings.Save()

    Else ' Existe una instancia previa de la aplicación; la activamos PrevInstance.Activate() End If

    End Sub End Module



    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.

    • Marcado como respuesta James-2016 jueves, 3 de noviembre de 2016 20:55
    jueves, 3 de noviembre de 2016 20:25
    Moderador
  • ok, gracias, tema resuelto.
    jueves, 3 de noviembre de 2016 20:55