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 Santos



Existem 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.

Leandro Alves Santos

Leandro Alves Santos - Visite o blog do autor: http://weblogs.pontonetpt.com/las/.