简体   繁体   English

如何运行ac#WinForm应用程序的一个实例?

[英]How to run one instance of a c# WinForm application?

I've a C# application that displays a login form when launched and displays the main form after users are authenticated. 我有一个C#应用程序,它在启动时显示登录表单,并在用户通过身份验证后显示主表单。 I used Mutex to restrict that only one instance of my application runs. 我使用Mutex限制只运行我的应用程序的一个实例。 And, this works fine for only the Login form. 而且,这只适用于登录表单。 Once the main form is displayed, it doesn't restrict users from reopening the Login form. 显示主窗体后,它不会限制用户重新打开登录表单。 I was looking for a solution by which the Login screen couldn't be displayed once the main form is already opened. 我正在寻找一种解决方案,一旦主窗体已经打开,登录屏幕就无法显示。

Here is my Program.cs 这是我的Program.cs

 [STAThread]
    static void Main()
    {
        bool mutexCreated=true;

        using (Mutex mutex = new Mutex(true, "eCS", out mutexCreated))
        {
            if (mutexCreated)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Login());
            }
            else
            {
                Process current = Process.GetCurrentProcess();
                foreach (Process process in Process.GetProcessesByName(current.ProcessName))
                {
                    if (process.Id != current.Id)
                    {
                        XtraMessageBox.Show("Another instance of eCS is already running.", "eCS already running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        SetForegroundWindow(process.MainWindowHandle);
                        break;
                    }
                }
            }
        }
    }

I've made some small changes: 我做了一些小改动:


namespace CSMutex
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            bool mutexCreated=true;
            using(Mutex mutex = new Mutex(true, "eCS", out mutexCreated))
            {
                if (mutexCreated)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Login loging = new Login();
                    Application.Run(loging);
                    Application.Run(new Main() { UserName = loging.UserName });
                }
                else
                {
                    Process current = Process.GetCurrentProcess();
                    foreach (Process process in Process.GetProcessesByName(current.ProcessName))
                    {
                        if (process.Id != current.Id)
                        {
                            MessageBox.Show("Another instance of eCS is already running.", "eCS already running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                            //SetForegroundWindow(process.MainWindowHandle);
                            break;
                        }
                    }
                }
            }
        }
    }
}

That works as expected - ie even when Login form is closed (and the main application form is started) it doesn't let user run the application once again. 这按预期工作 - 即使关闭了Login表单(并且主应用程序表单已启动),它也不允许用户再次运行该应用程序。 I've decided not to create Main from within Login (this is I believe how you application works) and instead I am passing parameter to Main . 我决定不在Login创建Main (这是我相信你的应用程序是如何工作的)而是我将参数传递给Main I have also made some small change to Login so it has UserName propert (same as Main ). 我还对Login进行了一些小改动,因此它具有UserName属性(与Main相同)。

If you are ok with a reference to Microsoft.VisualBasic, you can use its SingleInstance processing. 如果您对Microsoft.VisualBasic的引用没有问题,则可以使用其SingleInstance处理。

    [STAThread]
    static void Main(string[] args)
    {
        using (System.Threading.Mutex mutex = new System.Threading.Mutex(true, "MyApp.SingleInstance.Mutex", out createdNew))
        {
            MainForm = new MainDlg();
            SingleInstanceApplication.Run(MainForm, StartupNextInstanceEventHandler);
        }
    }

    public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e)
    {
        MainForm.Activate();
    }

public class SingleInstanceApplication : WindowsFormsApplicationBase
{
    private SingleInstanceApplication()
    {
        base.IsSingleInstance = true;
    }

    public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
    {
        SingleInstanceApplication app = new SingleInstanceApplication();
        app.MainForm = f;
        app.StartupNextInstance += startupHandler;
        app.Run(Environment.GetCommandLineArgs());
    }
}

if you want limit to only one instance for a Form , you can do something like this: 如果您只想限制一个Form一个实例,您可以这样做:

public static class LoginForm 
{
    private static Form _loginForm = new Form();


    public static bool ShowLoginForm(){

        if(_loginForm.Visible)
             return false;

        _loginForm.Show();
        return true;
    }
}

So if more then one clients will call this method, which is only possible method to show login form, in case when its already visible, it will not be executed. 因此,如果多于一个客户端将调用此方法,这只是显示登录表单的可能方法,如果它已经可见,则不会执行。

private bool IsSingleInstance()
    {
        string szCurrentProcessName = this.ProductName;
        Process[] processlist = Process.GetProcesses();
        foreach(Process theprocess in processlist)
        {
            string szProcessName = theprocess.MainModule.ModuleName.ToString();
            if (szProcessName.Contains(szCurrentProcessName))
                return false;
        }
        return true;
    }

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

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