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...![]()
José Carlos Macoratti