简体   繁体   English

检查我的Windows应用程序是否正在运行

[英]Checking if my Windows application is running

How do I check if my C# Windows application is running ? 如何检查C#Windows应用程序是否正在运行?

I know that I can check the process name but the name can be changed if the exe changes. 我知道我可以检查进程名称,但是如果exe更改,则可以更改名称。

Is there any way to have a hash key or something to make my application unique? 有什么方法可以使用哈希键或其他使我的应用程序具有唯一性的方法吗?

public partial class App : System.Windows.Application
{
    public bool IsProcessOpen(string name)
    {
        foreach (Process clsProcess in Process.GetProcesses()) 
        {
            if (clsProcess.ProcessName.Contains(name))
            {
                return true;
            }
        }

        return false;
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        // Get Reference to the current Process
        Process thisProc = Process.GetCurrentProcess();

        if (IsProcessOpen("name of application.exe") == false)
        {
            //System.Windows.MessageBox.Show("Application not open!");
            //System.Windows.Application.Current.Shutdown();
        }
        else
        {
            // Check how many total processes have the same name as the current one
            if (Process.GetProcessesByName(thisProc.ProcessName).Length > 1)
            {
                // If ther is more than one, than it is already running.
                System.Windows.MessageBox.Show("Application is already running.");
                System.Windows.Application.Current.Shutdown();
                return;
            }

            base.OnStartup(e);
        }
    }

The recommended way is to use a Mutex. 推荐的方法是使用Mutex。 You can check out a sample here : http://www.codeproject.com/KB/cs/singleinstance.aspx 您可以在此处签出示例: http : //www.codeproject.com/KB/cs/singleinstance.aspx

In specific the code: 具体代码如下:


        /// 
        /// check if given exe alread running or not
        /// 
        /// returns true if already running
        private static bool IsAlreadyRunning()
        {
            string strLoc = Assembly.GetExecutingAssembly().Location;
            FileSystemInfo fileInfo = new FileInfo(strLoc);
            string sExeName = fileInfo.Name;
            bool bCreatedNew;

            Mutex mutex = new Mutex(true, "Global\\"+sExeName, out bCreatedNew);
            if (bCreatedNew)
                mutex.ReleaseMutex();

            return !bCreatedNew;
        }

For my WPF application i've defined global app id and use semaphore to handle it. 对于我的WPF应用程序,我已经定义了全局应用程序ID并使用信号量来处理它。

public partial class App : Application
{      
    private const string AppId = "c1d3cdb1-51ad-4c3a-bdb2-686f7dd10155";

    //Passing name associates this sempahore system wide with this name
    private readonly Semaphore instancesAllowed = new Semaphore(1, 1, AppId);

    private bool WasRunning { set; get; }

    private void OnExit(object sender, ExitEventArgs e)
    {
        //Decrement the count if app was running
        if (this.WasRunning)
        {
            this.instancesAllowed.Release();
        }
    }

    private void OnStartup(object sender, StartupEventArgs e)
    {
        //See if application is already running on the system
        if (this.instancesAllowed.WaitOne(1000))
        {
            new MainWindow().Show();
            this.WasRunning = true;
            return;
        }

        //Display
        MessageBox.Show("An instance is already running");

        //Exit out otherwise
        this.Shutdown();
    }
}

you need a way to say that "i am running" from the app, 您需要一种方法来通过应用说“我正在跑步”,

1) open a WCF ping service 2) write to registry/file on startup and delete on shutdown 3) create a Mutex 1)打开WCF ping服务2)启动时写入注册表/文件,关机时删除3)创建Mutex

... i prefer the WCF part because you may not clean up file/registry correctly and Mutex seems to have its own issues ...我更喜欢WCF部分,因为您可能无法正确清理文件/注册表,并且Mutex似乎有其自身的问题

Mutex and Semaphore didn't work in my case (I tried them as suggested, but it didn't do the trick in the application I developed). Mutex和Semaphore在我的情况下不起作用(我按照建议尝试了它们,但是在我开发的应用程序中却没有用)。 The answer abramlimpin provided worked for me, after I made a slight modification. 在我稍加修改后, abramlimpin提供的答案对我有用

This is how I got it working finally. 这就是我最终使它工作的方式。 First, I created some helper functions: 首先,我创建了一些辅助函数:

public static class Ext
{
   private static string AssemblyFileName(this Assembly myAssembly)
    {
        string strLoc = myAssembly.Location;
        FileSystemInfo fileInfo = new FileInfo(strLoc);
        string sExeName = fileInfo.Name;
        return sExeName;
    }

    private static int HowManyTimesIsProcessRunning(string name)
    {
        int count = 0;
        name = name.ToLowerInvariant().Trim().Replace(".exe", "");
        foreach (Process clsProcess in Process.GetProcesses())
        {
            var processName = clsProcess.ProcessName.ToLowerInvariant().Trim();
            // System.Diagnostics.Debug.WriteLine(processName);
            if (processName.Contains(name))
            {
                count++;
            };
        };
        return count;
    }

    public static int HowManyTimesIsAssemblyRunning(this Assembly myAssembly)
    {
        var fileName = AssemblyFileName(myAssembly);
        return HowManyTimesIsProcessRunning(fileName);
    }
}

Then, I added the following to the main method: 然后,我将以下内容添加到main方法中:

[STAThread]
static void Main()
{
    const string appName = "Name of your app";

    // Check number of instances running:
    // If more than 1 instance, cancel this one.
    // Additionally, if it is the 2nd invocation, show a message and exit.
    var numberOfAppInstances = Assembly.GetExecutingAssembly().HowManyTimesIsAssemblyRunning();
    if (numberOfAppInstances == 2)
    {
       MessageBox.Show("The application is already running!
        +"\nClick OK to close this dialog, then switch to the application by using WIN + TAB keys.",
        appName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
    };
    if (numberOfAppInstances >= 2)
    {
        return;
    };
}

If you invoke the application a 3rd, 4th ... time, it does not show the warning any more and just exits immediately. 如果您第三次,第四次调用该应用程序,它将不再显示警告,而是立即退出。

Checkout: What is a good pattern for using a Global Mutex in C# ? 结帐: 在C#中使用Global Mutex的良好模式是什么

// unique id for global mutex - Global prefix means it is global to the machine
const string mutex_id = "Global\\{B1E7934A-F688-417f-8FCB-65C3985E9E27}";

static void Main(string[] args)
{
    using (var mutex = new Mutex(false, mutex_id))
    {
        // edited by Jeremy Wiebe to add example of setting up security for multi-user usage
        // edited by 'Marc' to work also on localized systems (don't use just "Everyone") 
        var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
        var securitySettings = new MutexSecurity();
        securitySettings.AddAccessRule(allowEveryoneRule);
        mutex.SetAccessControl(securitySettings);

        //edited by acidzombie24
        var hasHandle = false;
        try
        {
            try
            {
                // note, you may want to time out here instead of waiting forever
                //edited by acidzombie24
                //mutex.WaitOne(Timeout.Infinite, false);
                hasHandle = mutex.WaitOne(5000, false);
                if (hasHandle == false) return;//another instance exist
            }
            catch (AbandonedMutexException)
            {
                // Log the fact the mutex was abandoned in another process, it will still get aquired
            }

            // Perform your work here.
        }
        finally
        {
            //edit by acidzombie24, added if statemnet
            if (hasHandle)
                mutex.ReleaseMutex();
        }
    }
}

I really simplistic way I guess would be, for every exe that is running, you could create/open a file on disk in a known location (c:\\temp) with a special name "yourapp.lock" and then just count how many of those there are. 我猜想我的方式非常简单,对于每个正在运行的exe,您都可以在磁盘上的已知位置(c:\\ temp)上创建/打开一个文件,并使用特殊名称“ yourapp.lock”,然后只计算有多少个文件其中有。

A harder way, would be to open up some inter-process communication, or sockets, so with the process list you could interrogate each process to see if it was your application. 一种更困难的方法是打开一些进程间通信或套接字,因此,使用进程列表,您可以查询每个进程以查看它是否是您的应用程序。

Enter a guid in your assembly data. 在装配数据中输入向导。 Add this guid to the registry. 将此GUID添加到注册表中。 Enter a reg key where the application read it's own name and add the name as value there. 在应用程序读取其自身名称的地方输入一个reg键,然后在其中将其添加为值。

The other task watcher read the reg key and knows the app name. 另一个任务观察程序读取reg键并知道应用程序名称。

you can simply use varialbles and one file to check for running your program. 您只需使用varialbles和一个文件来检查程序是否运行。 when open the file contain a value and when program closes changes this value to another one. 打开文件时包含一个值,程序关闭时将其更改为另一个值。

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

相关问题 使用Windows Service检查应用程序是否正在运行 - Checking if an application is running using Windows Service 检查ex中的特定文本字段。 带有正在运行的Windows应用程序的IE - Checking a specific text field in ex. IE with an running windows application Windows服务作为我的应用程序服务器正在运行的保证 - Windows service as insurance that my application server is running 在我的 C# windows 窗体应用程序中检查 Gmail 登录凭据? - Checking Gmail login credentails in My C# windows form Application? 我正在检查我的应用程序是否已经在运行,它说即使我停止了应用程序也在运行,为什么? - I'm checking if my application is already running or not and it's saying running even if i stopped the application why? 问题:在运行我的应用程序时使用Windows 7,未经授权的访问异常 - Question: Using Windows 7, Unauthorized Access Exception when running my application 在我的控制台应用程序仍在运行时运行Windows窗体 - Run a windows form while my console application still running 关闭后,我的 Windows 窗体应用程序仍作为任务运行 - My Windows Forms Application is still running as task after closing 有没有办法阻止我的应用程序在Windows 7机器上运行? - Is there any way to prevent my application from running on Windows 7 machines? Windows应用程序未与curl一起运行 - Windows application not running with curl
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM