Desenvolvimento - C#
Criando Aplicações Limitadas a Uma Única Instância (Single Instance)
Neste artigo, veremos como criar aplicações que permitem apenas uma instância em execução no computador utilizando as tecnologias da API Win32, Visual C++ 6, Visual Basic 6 e .NET Framework 2.0 (VB.NET e C Sharp).
por Leandro Alves SantosExistem casos em que precisamos impossibilitar que um usuário abra uma aplicação caso a mesma já esteja aberta.
Como exemplo, podemos analisar duas aplicações da Microsoft: a Calculadora e o Windows Media Player. Se tentarmos abrir n vezes a calculadora, serão abertas n instâncias, por outro lado, se fizermos o mesmo com o Windows Media Player, continuaremos apenas com uma instância aberta.
Para realizarmos essa tarefa, podemos utilizar um objeto mutex. Mutex é um objeto criado no kernel do sistema operacional que permite a sincronização entre processos. Os objetos mutex devem conter um nome único. É interessante utilizarmos um GUID (Globally Unique Identifier) como nome do mutex. Um GUID pode ser gerado através da ferramenta guidgen.exe.
Figura 1: Ferramenta guidgen.exe
Quando nossa aplicação for iniciada, podemos identificar se esse objeto mutex já existe através de seu nome e no caso de sua existência, podemos afirmar que a nossa aplicação já está aberta, então encerramos a instância que o usuário está tentando abrir.
A seguir, veremos como criar aplicações que permitem apenas uma instância em execução com API Win32, em Visual Basic e também na plataforma .NET.
Aplicações "Single Instance" com API Win32
Para criarmos uma aplicação que permite apenas uma instância aberta no computador, podemos utilizar a função CreateMutex da API Win32. Ao trabalhar com essa função, nós temos três cenários que devem ser tratados:
- Se um mutex com o mesmo nome já foi criado, a função retorna um handle para o objeto existente e a função GetLastError retorna o erro 183 (ERROR_ALREADY_EXISTS).
- Se um mutex com o nome que passamos como parâmetro para a função ainda não foi criado, o mutex é criado e o handle para o objeto é retornado.
- Se ocorrer algum erro na execução da função, o valor retornado será NULL.
Abaixo temos o código do método WinMain de uma aplicação Win32 criada com o Visual C++ 6. O trecho em negrito chama o método CreateMutex, verifica o seu retorno e se ocorreu o erro que indica a já existência desse mutex:
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HANDLE mutex = CreateMutex( NULL, FALSE, "nome_do_objeto_mutex");
if ( GetLastError() == ERROR_ALREADY_EXISTS || mutex == NULL )
return FALSE;
MSG msg;
HACCEL hAccelTable;
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_HELLO, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_HELLO);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
Aplicações "Single Instance" no Visual Basic
Com o Visual Basic, podemos criar uma aplicação "Single Instance" de forma muito simples através do objeto App.
O objeto App possui uma série de propriedades com informações a respeito da nossa aplicação. Uma dessas propriedades indica a existência de uma instância da nossa aplicação rodando no computador. O nome dessa propriedade é: PrevInstance.
Abaixo temos o método Main de uma aplicação desenvolvida em Visual Basic 6. No código deste método verificamos se já existe uma instância da aplicação em execução, caso não exista, carregamos o formulário da aplicação.
Sub Main()If Not App.PrevInstance Then
Form1.Show
End If
End Sub
Aplicações "Single Instance" no .NET Framework 2.0
No .NET Framework temos a classe Mutex. Com essa classe podemos criar o objeto mutex para que possamos saber se a aplicação já está aberta no computador.
Com o VB.NET, precisamos simplesmente marcar a opção "Make single instance application" nas propriedades do nosso projeto, mas essa opção não está disponível para projetos em C Sharp, nesse caso, utilizamos a classe Mutex.
Figura 2: Opções de um projeto VB.NET
Com um projeto em C Sharp, precisamos verificar se o objeto mutex já existe no computador através da função OpenExisting. Esse método é executado dentro de um bloco Try/Catch porque, no caso da não existência do mutex, uma exceção WaitHandleCannotBeOpenedException será disparada.
Na seqüência verificamos se a função OpenExisting retornou um objeto mutex. Se a nossa variável "mutex" permanecer nula, criamos o objeto mutex e deixamos a aplicação seguir com a execução do form inicial do projeto, se um objeto foi retornado pela função, um objeto mutex com o mesmo nome já existe, ou seja, a nossa aplicação já está sendo executada, então saímos do método Main, com isso, a aplicação é encerrada.
static void Main(){
String nomeMutex = "nome_do_objeto_mutex";
System.Threading.Mutex mutex = null;
try
{
mutex = System.Threading.Mutex.OpenExisting(nomeMutex);
}
catch (System.Threading.WaitHandleCannotBeOpenedException)
{
}
if (mutex == null)
{
mutex = new System.Threading.Mutex(true, nomeMutex);
}
else
{
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
Como podemos ver neste artigo, criar uma aplicação que permite a execução de apenas uma instância é uma tarefa simples. Vale lembrar também que, as API"s Win32, podem ser utilizadas no Visual Basic e na plataforma .NET.