VB.NET - Permitindo somente uma instância da sua aplicação
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 |
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 !
Eu sei , é apenas VB.NET , mas eu gosto...
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências: