簡體   English   中英

檢查我的Windows應用程序是否正在運行

[英]Checking if my Windows application is running

如何檢查C#Windows應用程序是否正在運行?

我知道我可以檢查進程名稱,但是如果exe更改,則可以更改名稱。

有什么方法可以使用哈希鍵或其他使我的應用程序具有唯一性的方法嗎?

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

推薦的方法是使用Mutex。 您可以在此處簽出示例: http : //www.codeproject.com/KB/cs/singleinstance.aspx

具體代碼如下:


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

對於我的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();
    }
}

您需要一種方法來通過應用說“我正在跑步”,

1)打開WCF ping服務2)啟動時寫入注冊表/文件,關機時刪除3)創建Mutex

...我更喜歡WCF部分,因為您可能無法正確清理文件/注冊表,並且Mutex似乎有其自身的問題

Mutex和Semaphore在我的情況下不起作用(我按照建議嘗試了它們,但是在我開發的應用程序中卻沒有用)。 在我稍加修改后, abramlimpin提供的答案對我有用

這就是我最終使它工作的方式。 首先,我創建了一些輔助函數:

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

如果您第三次,第四次調用該應用程序,它將不再顯示警告,而是立即退出。

結帳: 在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();
        }
    }
}

我猜想我的方式非常簡單,對於每個正在運行的exe,您都可以在磁盤上的已知位置(c:\\ temp)上創建/打開一個文件,並使用特殊名稱“ yourapp.lock”,然后只計算有多少個文件其中有。

一種更困難的方法是打開一些進程間通信或套接字,因此,使用進程列表,您可以查詢每個進程以查看它是否是您的應用程序。

在裝配數據中輸入向導。 將此GUID添加到注冊表中。 在應用程序讀取其自身名稱的地方輸入一個reg鍵,然后在其中將其添加為值。

另一個任務觀察程序讀取reg鍵並知道應用程序名稱。

您只需使用varialbles和一個文件來檢查程序是否運行。 打開文件時包含一個值,程序關閉時將其更改為另一個值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM