简体   繁体   English

防止用户运行一个流程的多个实例

[英]Preventing a user from running more than one instance of a process

I am not an experienced programmer so any advice/guidance/examples would be appreciated! 我不是一个经验丰富的程序员,所以任何建议/指导/示例都将不胜感激! I have a windows form application in C# (.Net framework 4.5) that is replacing a windows service (issues with the Session0 variable were encountered). 我在C#(.Net Framework 4.5)中有一个Windows窗体应用程序正在替换Windows服务(遇到了Session0变量的问题)。 The application needs to open a process, (I'll be using Notepad as an example) and check every 5minutes whether Notepad is still open. 该应用程序需要打开一个进程(以记事本为例),每隔5分钟检查一次记事本是否仍处于打开状态。 If Notepad is not open, the form application must open an instance of it. 如果未打开记事本,则窗体应用程序必须打开它的一个实例。 The application must stop a user from opening another instance of Notepad, if it is already open. 该应用程序必须阻止用户打开另一个记事本实例(如果已打开)。 My coding currently closes all instances of Notepad. 我的编码当前关闭所有记事本实例。 I simply need the application to stop a second instance of Notepad to be opened. 我只需要应用程序停止第二个记事本实例被打开。 The problem is that the user is not allowed to interact with the application at all, as you will note in the coding the user doesn't even see the form. 问题是,根本不允许用户与应用程序进行交互,因为您会在编码中注意到,用户甚至看不到表单。 Here is my coding thus far: 到目前为止,这是我的编码:

    private void Form1_Load(object sender, EventArgs e)
    {
        this.ShowInTaskbar = false;
        this.Visible = false;
        //handle Elapsed event
        myTimer.Tick += new EventHandler(OnElapsedTime);
        //This statement is used to set interval to 5 minute (= 300,000 milliseconds)
        myTimer.Interval = 60000;//300000;
        //enabling the timer
        myTimer.Enabled = true;
        WatchForProcessStart("Notepad.exe");
    }

     private void OnElapsedTime(object source, EventArgs e)
    {
        bool status = IsProcessOpen("notepad");
          if (status == true)
          {
              //TraceService("Notepad is already open" + DateTime.Now);
          }
          else
          {
            Process process = new Process();
            process.StartInfo.FileName = "notepad.exe";
            process.EnableRaisingEvents = true;
            process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
            process.Start();
            //TraceService("Notepad opened" + DateTime.Now);
          }
    }

     public bool IsProcessOpen(string procName)
     {
         System.Diagnostics.Process[] proc = System.Diagnostics.Process.GetProcessesByName(procName);
         if (proc.Length > 0)
         {
             return true;
         }
         else
         {
             return false;
         }
     }

     private ManagementEventWatcher WatchForProcessStart(string processName)
     {
         string queryString =
             "SELECT TargetInstance" +
             "  FROM __InstanceCreationEvent " +
             "WITHIN  10 " +
             " WHERE TargetInstance ISA 'Win32_Process' " +
             "   AND TargetInstance.Name = '" + processName + "'";

         // The dot in the scope means use the current machine
         string scope = @"\\.\root\CIMV2";

         // Create a watcher and listen for events
         ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
         watcher.EventArrived += ProcessStarted;
         watcher.Start();
         return watcher;
     }

     private void ProcessStarted(object sender, EventArrivedEventArgs e)
     {
         ManagementBaseObject targetInstance = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value;
         string processName = targetInstance.Properties["Name"].Value.ToString();
         bool status = IsProcessOpen("notepad");
         if (status == true)
         {
             System.Diagnostics.Process.Start("cmd.exe", "/c taskkill /IM notepad.exe");
         }
         else
         {
             Process process = new Process();
             process.StartInfo.FileName = "notepad.exe";
             process.EnableRaisingEvents = true;
             process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
             process.Start();
         }
     }

Wrap it up in a Mutex 将其包裹在Mutex中

 var mutexId = "MyApplication";
 using (var mutex = new Mutex(false, mutexId))
 {
    if (!mutex.WaitOne(0, false))
    {
       MessageBox.Show("Only one instance of the application is allowed!", "Info", MessageBoxButtons.OK, MessageBoxIcon.Hand);
       return;
    }
    // Do scome work
 }

If you want to restrict it to one instance per machine, the mutexId needs to be prefixed with Global\\ 如果要将其限制为每台计算机一个实例,则必须在mutexId的前面加上Global \\

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM