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

C# 检查我的Windows应用程序是否正在运行,c#,winforms,C#,Winforms,如何检查我的C#Windows应用程序是否正在运行 我知道我可以检查进程名称,但如果exe更改,名称可以更改 有没有办法使用散列键或其他东西使我的应用程序唯一?签出: 我想,对于正在运行的每个exe,您都可以在磁盘上的已知位置(c:\temp)创建/打开一个名为“yourapp.lock”的文件,然后计算其中有多少个文件 更困难的方法是打开一些进程间通信或套接字,这样您就可以使用进程列表查询每个进程,看看它是否是您的应用程序。在程序集数据中输入guid。 将此guid添加到注册表。 输入一个注册

如何检查我的C#Windows应用程序是否正在运行

我知道我可以检查进程名称,但如果exe更改,名称可以更改

有没有办法使用散列键或其他东西使我的应用程序唯一?

签出:


我想,对于正在运行的每个exe,您都可以在磁盘上的已知位置(c:\temp)创建/打开一个名为“yourapp.lock”的文件,然后计算其中有多少个文件


更困难的方法是打开一些进程间通信或套接字,这样您就可以使用进程列表查询每个进程,看看它是否是您的应用程序。

在程序集数据中输入guid。 将此guid添加到注册表。 输入一个注册表项,应用程序在其中读取自己的名称,并将该名称作为值添加到其中


另一个任务观察者读取注册表项并知道应用程序名称。

建议使用互斥锁。您可以在此处查看示例:

具体而言,守则:


        /// 
        /// 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;
        }

你需要一种从应用程序中说出“我在跑步”的方式

1) 打开WCF ping服务 2) 启动时写入注册表/文件,关闭时删除 3) 创建互斥锁


。。。我更喜欢WCF部分,因为您可能无法正确清理文件/注册表,并且互斥似乎有自己的问题

对于我的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();
    }
}

您可以简单地使用变量和一个文件来检查程序的运行情况。
当打开文件时,包含一个值,当程序关闭时,将该值更改为另一个值

互斥和信号量在我的例子中不起作用(我按照建议尝试了它们,但在我开发的应用程序中没有起作用)。在我稍作修改后,提供的答案对我有效

这就是我最终让它工作的方式。 首先,我创建了一些助手函数:

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);
    }
}
然后,我将以下内容添加到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;
    };
}

如果您在第三、第四次调用应用程序。。。时间,它不再显示警告,而是立即退出。

如果您只想查看一个实例,请查看互斥:以这种方式使用互斥存在问题,而且有时我需要使用应用程序重新启动我的应用程序。重新启动会与互斥模式冲突。因此,基本上,您的问题是:“如何在不实际创建互斥体的情况下获得所有互斥体功能"? 为什么不问问如何解决你在使用互斥体时遇到的任何问题?@Cody:我想你是对的,我应该试着解决与互斥体的冲突。谢谢-1:正如OP所说,他知道他可以检查进程名,他想知道如果应用程序名为changed@djeeg字体我们读过同样的问题吗?你能指出op所说的,他想知道如果应用程序名称被更改该怎么办吗?第2行:“我知道我可以检查进程名称,但如果exe被更改,名称可以更改。”这是不可接受的,因为我认为我不应该请求访问直接写入磁盘,这会带来很多麻烦,但是感谢如果检查应用程序与正在运行的应用程序相同,这将起作用。如果您使用GUID而不是
sExeName
,则它将适用于任何应用程序。这应该放在我的C应用程序的哪个函数中?这是脆弱的:
IsProcessOpen(“application.exe的名称”)
。从编写源代码到在用户机器上运行,可执行文件可能已经更改了名称。互斥不存在此问题,也不假设应用程序是如何运行的。如果另一个应用程序实例正在运行,是否有任何方法可以“切换到”或“将进程置于前面”?枚举进程的窗口并找到前景窗口:EnumWindows。然后将此窗口移到前面。@AbramImpin应用程序无法派生密封型应用程序应用程序崩溃后,重新启动不会从“重复实例”消息中保存您。不要使用注册表,当您忘记删除此值时,请小心不干净的退出。使用注册表是一个选项,与您在文件系统的某处编写.pid文件时所做的相同。如果应用程序崩溃,你需要清理这个烂摊子。与注册表相同,代码需要处理此问题。
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);
    }
}
[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;
    };
}