【问题标题】:Using Microsoft.VisualBasic.ApplicationServices to manage an application's single instance使用 Microsoft.VisualBasic.ApplicationServices 管理应用程序的单个实例
【发布时间】:2011-04-27 13:33:02
【问题描述】:

我已经设法从 StackOverflow 中找到以下代码:

using Microsoft.VisualBasic.ApplicationServices;
using System.Windows.Forms;

namespace ExciteEngine2.MainApplication {

    public class SingleInstanceController: WindowsFormsApplicationBase {

        public delegate Form CreateMainForm();
        public delegate void StartNextInstanceDelegate(Form mainWindow);
        private readonly CreateMainForm formCreation;
        private readonly StartNextInstanceDelegate onStartNextInstance;

        public SingleInstanceController() {

        }
        public SingleInstanceController(AuthenticationMode authenticationMode)
            : base(authenticationMode) {

        }

        public SingleInstanceController(CreateMainForm formCreation, StartNextInstanceDelegate onStartNextInstance) {
            // Set whether the application is single instance
            this.formCreation = formCreation;
            this.onStartNextInstance = onStartNextInstance;
            IsSingleInstance = true;

            StartupNextInstance += this_StartupNextInstance;
        }

        private void this_StartupNextInstance(object sender, StartupNextInstanceEventArgs e) {
            if (onStartNextInstance != null) {
                onStartNextInstance(MainForm); 
                // This code will be executed when the user tries to start the running program again,
                // for example, by clicking on the exe file.
                // This code can determine how to re-activate the existing main window of the running application.
            }
        }

        protected override void OnCreateMainForm() {
            // Instantiate your main application form
            MainForm = formCreation();
        }

        //public void Run() {
        //  string[] commandLine = new string[0];
        //  base.Run(commandLine);
        //}

        protected override void OnRun() {
            base.OnRun();
        }

    }

}

我的Program.cs 中有这个:

    private static Form CreateForm() {
        return new AppMDIRibbon();
    }

    private static void OnStartNextInstance(Form mainWindow)            
    {
        // When the user tries to restart the application again, the main window is activated again.
        mainWindow.WindowState = FormWindowState.Maximized;
    }

    [STAThread]
    static void Main(string[] args) {

        SingleInstanceController ApplicationSingleInstanceController = new SingleInstanceController(CreateForm, OnStartNextInstance);           
        ApplicationSingleInstanceController.Run(args);   

        #region Application Logic
        #endregion
    }

现在,在 Run() 之前,我需要很多应用程序逻辑:

        #region Application Logic
        //Uninstall
        foreach (string arg in args) {
            if (arg.Split('=')[0] == "/u") {
                ApplicationLogger.Info("Uninstallation command received.");
                Process.Start(new ProcessStartInfo(Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\msiexec.exe", "/x " + arg.Split('=')[1]));
                return;
            }
        }

        SetupXPO();
        SetupLogging();

        Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
        Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.ThreadException += Application_ThreadException;

        try {
            ApplicationLogger.Info("Setting Telerik Theme: " + ConfigurationManager.AppSettings["ThemeToUse"]);
            ThemeResolutionService.ApplicationThemeName = ConfigurationManager.AppSettings["ThemeToUse"];

        }
        catch (Exception ex) {
            ApplicationLogger.Error("Exception while setting Telerik Theme.", ex);
            ThemeResolutionService.ApplicationThemeName = "ControlDefault";

        }

        DevExpress.UserSkins.OfficeSkins.Register();
        DevExpress.UserSkins.BonusSkins.Register();
        DevExpress.Skins.SkinManager.EnableFormSkins();
        DevExpress.Skins.SkinManager.EnableMdiFormSkins();

        if (args.Contains("/dx")) {
            Application.Run(new AppMDIRibbonDX());
            ApplicationLogger.Info("Application (DX) started.");

        }
        else {
            Application.Run(new AppMDIRibbon());
            ApplicationLogger.Info("Application started.");

        }
        #endregion

如何设置此逻辑?我正在使用命令行参数来实际启动替代表单。我正在使用命令行参数来导致卸载,并调用一些方法来设置数据库和日志记录。同样,我也在设置文化和主题。所有这些都在实际应用程序运行之前。有人可以推荐吗?

【问题讨论】:

    标签: c# .net winforms single-instance


    【解决方案1】:

    如果您简化您链接的 Visual Basic 派生类,您只需替换当前对 Application.Run() 的调用。这确实取决于您希望如何处理后续实例。

    使用以下版本,只需将您的调用更改为:Application.Run(myForm) 为 SingleInstanceApplication.Run(myForm);

    public sealed class SingleInstanceApplication : WindowsFormsApplicationBase
    {
        private static SingleInstanceApplication _application;
    
        private SingleInstanceApplication()
        {
            base.IsSingleInstance = true;
        }
    
        public static void Run(Form form)
        {
            _application = new SingleInstanceApplication {MainForm = form};
    
            _application.StartupNextInstance += NextInstanceHandler;
            _application.Run(Environment.GetCommandLineArgs());
        }
    
        static void NextInstanceHandler(object sender, StartupNextInstanceEventArgs e)
        {
            // Do whatever you want to do when the user launches subsequent instances
            // like when the user tries to restart the application again, the main window is activated again.
            _application.MainWindow.WindowState = FormWindowState.Maximized;
        }
    }
    

    然后您的 Main() 方法包含您的“应用程序逻辑”

       [STAThread]
        static void Main(string[] args) {
    
            #region Application Logic
            //Uninstall
            foreach (string arg in args) {
                if (arg.Split('=')[0] == "/u") {
                    ApplicationLogger.Info("Uninstallation command received.");
                    Process.Start(new ProcessStartInfo(Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\msiexec.exe", "/x " + arg.Split('=')[1]));
                    return;
                }
            }
    
            SetupXPO();
            SetupLogging();
    
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
    
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
    
            Application.ThreadException += Application_ThreadException;
    
            try {
                ApplicationLogger.Info("Setting Telerik Theme: " + ConfigurationManager.AppSettings["ThemeToUse"]);
                ThemeResolutionService.ApplicationThemeName = ConfigurationManager.AppSettings["ThemeToUse"];
    
            }
            catch (Exception ex) {
                ApplicationLogger.Error("Exception while setting Telerik Theme.", ex);
                ThemeResolutionService.ApplicationThemeName = "ControlDefault";
    
            }
    
            DevExpress.UserSkins.OfficeSkins.Register();
            DevExpress.UserSkins.BonusSkins.Register();
            DevExpress.Skins.SkinManager.EnableFormSkins();
            DevExpress.Skins.SkinManager.EnableMdiFormSkins();
    
            if (args.Contains("/dx")) {
                SingleInstanceApplication.Run(new AppMDIRibbonDX());
                ApplicationLogger.Info("Application (DX) started.");
    
            }
            else {
                SingleInstanceApplication.Run(new AppMDIRibbon());
                ApplicationLogger.Info("Application started.");
    
            }
            #endregion
        }
    

    【讨论】:

    • 好的,但是我在哪里放置我的应用程序逻辑代码(我的问题中的第三段代码)?
    • 您调用的应用程序逻辑代码看起来像您原来的 Main() 函数。保持这种方式。只需摆脱您添加的 SingleInstance 逻辑即可。
    • Err... 我实际上是根据命令行参数使用不同的主要形式启动的。您是否建议 main 函数不会在第二个实例上重新执行?我称为Application Logic 的代码块包含两行:Application.Run(new AppMDIRibbonDX());Application.Run(new AppMDIRibbon()); 我不想在SingleInstanceApplication(在我的原始案例中为SingleInstanceController)类中使用我的Application Logic 代码。
    • 好的,再试一次。也许我理解错了,但我不这么认为。我更新了帖子以在主要方法中包含您的整个“应用程序逻辑”。正如我所说的那样替换 App.Run。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    相关资源
    最近更新 更多