IMPEDIR ABERTURA MAIS DE UMA VEZ DO SOFTWARE

PROGRAMADORVB6 07/06/2011 13:47:29
#376067
Olá boa tarde.
Como posso impedir que a minha aplicação não seja carregada em duplicado.
em VB6 fazia :
If App.PrevInstance Then
MsgBox [Ô]A aplicação já se encontra aberta![Ô], vbCritical, App.EXEName
End
End If

Em VB.Net não sei.
Alguém me pode indicar uma maneira de o fazer (Estável) e o mais correcto?
Grato desde já pela vossa atenção
Atentamente.
ProgramadorVB6
FROSTYNHO 07/06/2011 13:55:29
#376069
Resposta escolhida
PROGRAMADORVB6 07/06/2011 14:03:03
#376071
Mas isso é viavel, como acontece no VB6 ?
FROSTYNHO 07/06/2011 14:05:49
#376072
é o modo mais simples que conheço, só não sei, se tem como enviar uma mensagem como no seu exemplo acima, mas ele empede de abrir 2 veses o seu projeto.
MARCELOSN 07/06/2011 15:07:10
#376080
Boa tarde


Segue dados do Site:

VB.NET - Permitindo somente uma instância da sua aplicação
http://www.macoratti.net/vbn_ins1.htm


===========================================================================

Como podemos fazer para saber se já existe uma instância da nossa aplicação em execução no VB.NET ?

Nota: No Visual Basic a tarefa era simples e o código usado com mais frequência era o seguinte:

Private Sub Form_Load()
Dim cap As String

If App.PrevInstance Then
[ô] Informe ao usuário que já existe uma instância rodando.
MsgBox [Ô]Já existe uma instância desta aplicação em execução.[Ô], vbCritical

[ô] ativa outra instância
cap = Me.Caption
Me.Caption = [Ô][Ô]
AppActivate cap

[ô] Sai.
Unload Me
End If
End Sub

E no VB.NET , alguém se habilita a mostrar como fazer ??

Alguém rapidamente poderia propor a solução que utiliza o namespace System.Diagnostics. Ela funciona assim:

Utilizando a classe Process do citado namespace temos acesso ao método GetProcessByName que retorna uma array com o nome dos processos que estão sendo executados. O código é enxuto e é mostrado com duas possibilidades abaixo:

Dim emExecucao As Boolean

1- verificando quantos elementos o array possui , se possuir mais de um então existe duas instâncias
emExecucao = Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length > 1

2- verificando o limite superior do array , se for maior que zero então existe duas instâncias
emExecucao = Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).GetUpperBound(0) > 0


Acima temos as duas formas de verificar se existe mais de uma instância da aplicação rodando:

1- Na primeira eu estou verificando se o tamanho do array retornado pelo método GetProcessesByName para o processo atual : GetCurrentProcess.ProcessName é maior que 1 , se for então temos duas instância da aplicação rodando.

2- No segundo eu verifico o limite superior do array retornado para o processo atual , se for maior que zero então eu tenho duas cópias da instãncia rodando.

Nota: Uma solução um pouco mais sofisticada pode ser obtida na função abaixo:
Public Shared Function VerificaInstancia() As Process

[ô]obtem o nome do processo atual
Dim processoAtual As Process = Process.GetCurrentProcess()
Dim processosRodando As Process() = Process.GetProcessesByName(processoAtual.ProcessName)

[ô]percorre os processos em execução com o mesmo nome
Dim processo As Process
For Each processo In processosRodando
[ô]Ignora o processo atual
If processo.Id <> processoAtual.Id Then
[ô]esteja certo que o processo esta rodando a partir de um arquivo EXE.
If [Assembly].GetExecutingAssembly().Location.Replace([Ô]/[Ô], [Ô]\[Ô]) = processoAtual.MainModule.FileName Then
[ô]Retorna a outra instância do processo
Return process
End If
End If
Next processo
[ô]Se nenhuma outra instância estiver em execução retorna null.
Return Nothing
End Function

Mas existe um problema com este método. Ele se baseia no nome do processo (nome do executável) , se o usuário mudar o nome do executável ele vai poder rodar a aplicação duas vezes.

Chegamos a um impasse ?

A solução também é simples. Basta usar a classe Mutex do namespace System.Threading. O código é o seguinte :
Dim objMutex As Mutex

objMutex = New Mutex(False, [Ô]SINGLE_INSTANCE_APP_MUTEX[Ô])

If objMutex.WaitOne(0, False) = False Then
objMutex.Close()
objMutex = Nothing
MessageBox.Show([Ô]Já existe uma instância rodando desta aplicação.[Ô])
End
End If

Uma solução mais elegante ainda seria implementar o pattern Singleton . O que é isto ??

O padrão de projeto Singleton é apenas uma estratégia para certificar de que existe somente uma única instância de um objeto particular.

Como implementar o padrão Singleton no VB.NET ?

Podemos fazer isto em duas etapas.

1- Certificar que cada construtor na classe que implementa o pattern Singleton não é do tipo Public. Todos os construtores devem ser protected ou private.

2- Implementar um método estático (shared) que cria somente uma única instância da classe.

Resolvido o problema. Como ?

Como um usuário não pode invocar construtores private ou protected eles não podem criar instâncias da classe exceto na forma que você definiu ; os métodos membros podem no entanto invocar métodos private e protected e podem chamar seu construtor não Public. Você então entra em cena e controla o número de instâncias que deseja executar. Abaixo um modelo:

Public Class Singleton

Private Shared FInstance As Singleton = Nothing

Private Sub New()

End Sub

Public Shared ReadOnly Property Instance()
Get
If (FInstance Is Nothing) Then
FInstance = New Singleton()
End If

Return FInstance
End Get
End Property

End Class

E em C# como podemos fazer o mesmo serviço ?

1- Inicie um novo projeto do tipo Visual C# e Windows Application

2- Acrescente a seguinte linha de código no inicio do código : using System.Diagnostics;

3- Localize [STAThread] na aplicação. Você deverá encontrar algo parecido com o código abaixo:
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

4- Copie o código abaixo antes da linha de código já existente:

[STAThread]
static void Main()
{
Process aProcess = Process.GetCurrentProcess();
string aProcName = aProcess.ProcessName;

if (Process.GetProcessesByName(aProcName).Length > 1)
{
MessageBox.Show([Ô]The application is already running!![Ô],[Ô]Test[Ô],MessageBoxButtons.OK,MessageBoxIcon.Stop);
Application.ExitThread();
}
Application.Run(new Form1());
}

Pronto !
PROGRAMADORVB6 08/06/2011 14:10:51
#376183
Olá boa tarde.
Estive exprimentar os vários métodos apresentados e reparei que o 1º que o nosso colega FROSTYNHO indicou é o mais viável.
Não quero eu dizer que o segundo não o faça com eficiência, mas para algumas situações , nomeadamente que tem o programa minimizado na taskbar, não funciona logo.
Bem posto isto quero agradecer a todos vós que colaboraram e tentaram ajudar.
Atentamente.
Até uma próxima.
ProgramadorVB6
Tópico encerrado , respostas não são mais permitidas