buenas queria preguntarles cual es la forma mas adecuada a hacer esto, basicamente es que tengo una aplicacion hecha en vb.net winform y que lee archivos csv, la aplicacion esta asociada a la extension es decir que al hacer doble clic sobre el archivo inicia y carga el contenido en mi aplicación, uno de los detalles es que si quiero abrir otro archivo se me abre la aplicacion otra ves y lo que quiero es que se abra solo en una.
Estaba leyendo por internet que esto se puede hacer mediante:
1) la api "SendMessage" es decir al iniciar y comprobar si el proceso esta activo y si lo esta enviar los archivos que pasan Environment.GetCommandLineArgs()
y luego cerrar la aplicacion.
2)lo mismo que el anterior solo que en ves de verificar si el proceso esta activo usar MUTEX.
3)Hacerlo mediante el WindowsFormsApplicationBase, es decir heredar una clase de WindowsFormsApplicationBase estableciendo la propiedad IsSingleInstance en TRUE.
4) Mediante: Dynamic Data Exchange (DDE) - (Esto si que no tengo mucha idea)
Cual de estas formas deberia usar??
Gracias
Cita de: OscarCadenas_91 en 22 Febrero 2018, 18:08 PM
Duda - Como restringir la aplicacion a una instancia?
Solo tienes que hacer un simple click en esta casilla...
(https://i.imgur.com/KNDuesy.png)
Si estuvieramos hablando de C# entonces la cosa cambiaría, ya que a Microsoft y los devs. de Visual Studio les gusta complicarle la vida a los que programan en C#, jeje, lo apropiado sería crear (y apropiarse de) un MUTEX usando la clase
Mutex.
Saludos!
muchas gracias por responder
pero aun me queda por resolver como capturar el archivo que intento abrir es decir ya no se abre otra ves pero no puedo obtener el nuevo archivo que intento abrir en mi aplicacion
Cita de: OscarCadenas_91 en 23 Febrero 2018, 00:59 AM
pero aun me queda por resolver como capturar el archivo que intento abrir es decir ya no se abre otra ves pero no puedo obtener el nuevo archivo que intento abrir en mi aplicacion
Pensé que ya sabrías como. Puedes usar cualquier tipo de intercomunicación entre procesos (IPC) como por ejemplo MMF (
memory mapped file) para compartir un bloque de memoria entre tus procesos y escribir los argumentos recibidos en el stream, o iguálmente lo puedes hacer con una
named pipe, o con un
socket si me apuras. Tambien puedes usar la clase
EventWaitHandle para crear un 'semáforo' global entre tus procesos, aunque ello implicaría la necesidad de adaptar tu código para volverlo asíncrono (ya que la idea sería detener la ejecución de un thread y enviar una señal de reanudación al iniciar la próxima instancia de tu aplicación con los nuevos argumentos). En fin, formas de hacerlo hay muchas. Yo lo que considero más simple para este escenario en concreto sería declarar una clase que implemente la interfaz
INotifyPropertyChanged, y listo.
Te muestro un ejemplo completo mediante la implementación de
INotifyPropertyChanged:
CommandLineNotifier.vb
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Public Class CommandLineNotifier : Implements INotifyPropertyChanged
Public Property Arguments As ReadOnlyCollection(Of String)
Get
Return Me.argumentsB
End Get
Set(ByVal value As ReadOnlyCollection(Of String))
If (value.Any()) AndAlso Not (value.Equals(Me.argumentsB)) Then
Me.argumentsB = value
Me.NotifyPropertyChanged()
End If
End Set
End Property
Private argumentsB As ReadOnlyCollection(Of String)
Private Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Shared Event ArgumentsReceived As EventHandler(Of ReadOnlyCollection(Of String))
Public Sub New(ByVal notifyCurrentArguments As Boolean)
If (notifyCurrentArguments) Then
Me.Arguments = New ReadOnlyCollection(Of String)(Environment.GetCommandLineArgs().Skip(1).ToArray())
End If
End Sub
Private Sub NotifyPropertyChanged(<CallerMemberName> Optional ByVal propertyName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Private Sub CommandLineNotifier_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
Handles Me.PropertyChanged
Select Case (e.PropertyName)
Case NameOf(Arguments)
If (CommandLineNotifier.ArgumentsReceivedEvent IsNot Nothing) Then
RaiseEvent ArgumentsReceived(Me, Me.argumentsB)
End If
Case Else
Throw New NotImplementedException()
End Select
End Sub
End Class
ApplicationEvents.vb (la clase donde se controlan los eventos de la aplicación)
Imports Microsoft.VisualBasic.ApplicationServices
Namespace My
Partial Friend Class MyApplication
Public Shared CommandLineNotifier As CommandLineNotifier
Public Sub MyApplication_StartupNextInstance(sender As Object, e As StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
If (e.CommandLine.Any) Then
My.MyApplication.CommandLineNotifier.Arguments = e.CommandLine
End If
End Sub
End Class
End Namespace
Form1.vb
Imports System.Collections.ObjectModel
Public Class Form1
Public Sub New()
MyClass.InitializeComponent()
AddHandler CommandLineNotifier.ArgumentsReceived, AddressOf Me.CommandLineNotifier_ArgumentsReceived
My.MyApplication.CommandLineNotifier = New CommandLineNotifier(notifyCurrentArguments:=True)
End Sub
Public Sub CommandLineNotifier_ArgumentsReceived(sender As Object, e As ReadOnlyCollection(Of String))
' En este ejemplo añado los nuevos argumentos recibidos, a un ListBox.
Me.ListBox1.Items.AddRange(DirectCast(sender, CommandLineNotifier).Arguments.ToArray())
End Sub
End Class
Saludos.
Muchisimas gracias elektro era justo lo que necesitaba ;-) , gracias por tomarte el tiempo en ayudarme.
Salu2 :D