Pergunta

Tenho de restringir a minha .net 4 aplicação de WPF, de modo que ele pode ser executado apenas uma vez por máquina.Note que eu disse por máquina, não por sessão.
Eu implementado única instância de aplicativos usando um simples mutex até agora, mas, infelizmente, como um mutex é por sessão.

Existe uma maneira de criar uma máquina grande mutex ou existe alguma outra solução para implementar uma única instância por aplicação de uma máquina?

Foi útil?

Solução

Eu faria isso com um objeto mutex global que deve ser mantido para a vida útil do seu aplicativo.

MutexSecurity oMutexSecurity;

//Set the security object
oMutexSecurity = new MutexSecurity();
oMutexSecurity.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), MutexRights.FullControl, AccessControlType.Allow));

//Create the global mutex and set its security
moGlobalMutex = new Mutex(True, "Global\\{5076d41c-a40a-4f4d-9eed-bf274a5bedcb}", bFirstInstance);
moGlobalMutex.SetAccessControl(oMutexSecurity);

Onde bFirstInstance Retorna se esta for a primeira instância do seu aplicativo em execução globalmente. Se você omitisse a parte global do Mutex ou a substituiu pelo local, o mutex seria apenas por sessão (é uma probabilidade de como seu código atual está funcionando).

Eu acredito que recebi essa técnica primeiro de Jon Skeet.

O tópico do MSDN no Mutex Objeto explica sobre os dois escopos para um objeto Mutex e destaca por que isso é importante ao usar serviços de terminal (consulte a segunda para a última nota).

Outras dicas

Eu acho que o que você precisa fazer é usar um sistema sempahore para controlar as instâncias de sua aplicação.

Se você criar um objeto Semáforo usando um construtor que aceita um nome, ele é associado com um sistema operacional de semáforo com esse nome.

Chamado de sistema de semáforos são visíveis em todo o sistema operacional, e pode ser usado para sincronizar as atividades dos processos.

EDITAR:Note que eu não estou ciente de que esta abordagem funciona em várias sessões do windows em uma máquina.Eu acho que deveria ter como seu sistema operacional a nível de construir, mas eu não posso dizer com certeza como eu ainda não testei dessa forma.

EDIT 2:Eu não sabia, mas depois de ler Stevo2000 a resposta, eu fiz alguns olhando bem, e acho que o "Global\" prefixo para fazer o objeto aplicável para o espaço de nomes global, seria aplicável aos semáforos bem e semáforo, se criado, desta forma, deve funcionar.

Você pode abrir um arquivo com direitos exclusivos em algum lugar no % ProgramData % A segunda instância que inicia tentará abrir o mesmo arquivo e falhar se ele já estiver aberto.

Que tal usar o registro?

  1. Você pode criar um registry entry under HKEY_LOCAL_MACHINE.
  2. Que o valor seja o flag Se o aplicativo for iniciado ou não.
  3. Encrypt the key usando algum padrão symmetric key encryption Método para que ninguém mais possa adulterar o valor.
  4. On application start-up check for the key e abortar continue em conformidade.
  5. Não se esqueça de obfuscate your assembly, que faz essa peça de descriptografia de criptografia, para que ninguém possa invadir a chave no registro, olhando para o código no refletor.

Eu fiz algo semelhante uma vez.

Ao olhar para a lista de aplicativos, verifiquei todos os processos em execução para um processo com nome idêntico e, se existisse, não permitiria iniciar o programa.

Isso não é à prova de balas, é claro, pois se outro aplicativo tiver exatamente o mesmo nome do processo, seu aplicativo nunca será iniciado, mas se você usar um nome não genérico, provavelmente será mais do que bom o suficiente.

Por uma questão de completude, gostaria de acrescentar o seguinte que acabei de encontrar agora:
este local na rede Internet tem uma abordagem interessante no envio de mensagens Win32 para outros processos. Isso corrigiria o problema do usuário renomear a montagem para ignorar o teste e de outros conjuntos com o mesmo nome.
Eles estão usando a mensagem para ativar a janela principal do outro processo, mas parece que a mensagem pode ser uma mensagem dummy usada apenas para verificar se o outro processo está respondendo a ele para saber se é o nosso processo ou não.

Observe que ainda não o testei.

Veja abaixo o exemplo completo de como um único aplicativo Instace é feito no WPF 3.5

public class SingleInstanceApplicationWrapper :
Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
{
public SingleInstanceApplicationWrapper()
{
// Enable single-instance mode.
this.IsSingleInstance = true;
}
// Create the WPF application class.
private WpfApp app;
protected override bool OnStartup(
Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
{
app = new WpfApp();
app.Run();
return false;
}
// Direct multiple instances.
protected override void OnStartupNextInstance(
Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)
{
if (e.CommandLine.Count > 0)
{
app.ShowDocument(e.CommandLine[0]);
}
}
}

Segunda parte:

public class WpfApp : System.Windows.Application
{
protected override void OnStartup(System.Windows.StartupEventArgs e)
{
base.OnStartup(e);
WpfApp.current = this;
// Load the main window.
DocumentList list = new DocumentList();
this.MainWindow = list;
list.Show();
// Load the document that was specified as an argument.
if (e.Args.Length > 0) ShowDocument(e.Args[0]);
}
public void ShowDocument(string filename)
{
try
{
Document doc = new Document();
doc.LoadFile(filename);
doc.Owner = this.MainWindow;
doc.Show();
// If the application is already loaded, it may not be visible.
// This attempts to give focus to the new window.
doc.Activate();
}
catch
{
MessageBox.Show("Could not load document.");
}
}
}

Terceira parte:

 public class Startup
    {
    [STAThread]
    public static void Main(string[] args)
    {
    SingleInstanceApplicationWrapper wrapper =
    new SingleInstanceApplicationWrapper();
    wrapper.Run(args);
    }
    }

Pode ser necessário adicionar referências à Soem e adicionar algumas declarações, mas isso é um trabalho.

Você também pode baixar uma solução completa de exemplo vs, baixando o código -fonte do livro de aqui.

Retirado de "Pro WPF em C#3 2008, Apress, Matthew MacDonald", compre o livro é ouro. Eu fiz.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top