使用EventWaitHandle确保跨多个用户的单个实例

时间:2012-08-08 10:03:34

标签: c# user-accounts single-instance event-wait-handle

合作者使用Processing建立了一个原型,连接到Sparkfun RFID阅读器,我认为使用USB串行连接。我们已将原型部署到一些试验者身上。我愚蠢地忽视了家庭和一种常见的使用场景是用户切换。因此,我正在编写一个包装器,确保只有一个原型应用程序实例在机器上的所有用户上运行。

我正在测试我作为一个简单的控制台应用程序的第一次尝试。这是代码:

    static void Main(string[] args)
    {
        // http://stackoverflow.com/a/2590446/575530
        var users = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
        var rule = new EventWaitHandleAccessRule(users, EventWaitHandleRights.FullControl, AccessControlType.Allow);
        var security = new EventWaitHandleSecurity();
        security.AddAccessRule(rule);
        bool createdStartup;
        using (var whStartup = new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppStartupEvent", out createdStartup, security))
        {
            bool createdShutdown;
            using (var whShutdown = new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppShutdownEvent", out createdShutdown, security))
            {
                Console.WriteLine("Let other instances shutdown");
                whStartup.Set();
                Console.WriteLine("If other instances exist wait for them to shutdown");
                if (!createdShutdown)
                {
                    whShutdown.WaitOne();
                }
                whShutdown.Reset();
                Console.WriteLine("Start tray app");
                var tokenProc = Process.Start(@"C:\Temp\FAMILY3_WIN\TokensApp.exe");
                Console.WriteLine(tokenProc.ProcessName);
                Console.WriteLine("Wait to see if another instance to tries to start");
                whStartup.Reset();
                whStartup.WaitOne();
                Console.WriteLine("Shutdown if another instance starts");
                //if (tokenProc != null) tokenProc.Kill();
                foreach (var process in Process.GetProcesses())
                {
                    if (process.ProcessName.StartsWith("javaw"))
                    {
                        process.Kill();
                    }
                }
                whShutdown.Set();
            }
        }
        Console.WriteLine("Done...");
        Console.ReadLine();
    }

(注意我知道这些代码存在问题:(1)杀死不是正在运行的原型的Java进程;(2)没有代码可以同时响应大量实例,一次只有两个。但那是不是我的问题是什么。)

在单个用户帐户下测试此功能正常。我可以启动我的应用程序,它反过来启动原型,如果我启动我的应用程序的第二个实例,第一个实例将杀死原型的初始实例,然后第二个实例重新启动原型的另一个实例。

但如果我尝试从两个不同的用户帐户执行此操作,则会失败(无声)。如果我

  1. 启动我的应用程序实例,启动原型
  2. 切换用户
  3. 启动我的应用程序实例然后启动它 没有我的应用程序从第1步开始的原型首先关闭现有的 实例
  4. 任何人都可以看到我的代码有什么问题吗?我应该如何在同一台机器上的几个同时用户会话中使用EventWaitHandle?

1 个答案:

答案 0 :(得分:0)

总是这样,在写了一个很长的问题后几分钟,答案就会浮现在脑海中!

我以EventWaitHandle的名义错误地使用斜杠。例如,替换构造函数调用:

new EventWaitHandle(false, EventResetMode.AutoReset, "Global/AaltoTokensAppShutdownEvent", out createdShutdown, security)

这一个:

new EventWaitHandle(false, EventResetMode.AutoReset, @"Global\AaltoTokensAppShutdownEvent", out createdShutdown, security)

解决了我的问题。