簡體   English   中英

單個進程winform應用程序上的多個應用程序域

[英]Multiple app domains on a single process winform application

我正在使用program.cs文件中的代碼在winform應用程序中創建應用程序域

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    ///

    [STAThread]
    static void Main(string[] args)
    {
        string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();

        // unique id for global mutex - Global prefix means it is global to the machine
        string mutexId = string.Format("Global\\{{{0}}}", appGuid);

        using (var mutex = new Mutex(false, mutexId))
        {
            var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
            var securitySettings = new MutexSecurity();
            securitySettings.AddAccessRule(allowEveryoneRule);
            mutex.SetAccessControl(securitySettings);


            if (mutex.WaitOne(TimeSpan.Zero, true) || (args.Length > 0 && string.Compare(args[0], "secondary", true) == 0))
            {
                ErrorHandler errorHandler = new ErrorHandler();
                DffEnvironment.Default.AppErrorHandler = errorHandler;
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(errorHandler.Application_ErrorHandler);
                MainForm mainForm = new MainForm();
                DffEnvironment.Default.MainForm = mainForm;
                if (args.Length > 0)
                {
                    MessageBox.Show(" CurrentDomain" + AppDomain.CurrentDomain.FriendlyName);
                }
                Application.Run(mainForm);
            }
            else
            {
                // send our Win32 message to make the currently running instance
                // Add new app domain
                NativeMethods.PostMessage(
                    (IntPtr)NativeMethods.HWND_BROADCAST,
                    NativeMethods.WM_SHOWME,
                    IntPtr.Zero,
                    IntPtr.Zero);
            }
        }
    }
}

在我的MainForm(窗體)中,我重寫了代碼WndProc方法並編寫了此代碼

static int procNumber=0;
protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == NativeMethods.WM_SHOWME)
            {
                try
                    {
                        procNumber++;
                        AppDomain appDomain = AppDomain.CreateDomain("MyAppDomainApplication" + procNumber.ToString(), null, setupInfo);
                        string[] arguments = { "secondary" };
                        appDomain.ExecuteAssembly("MyAppDomainApplication.exe", null, arguments);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString());
                    }
                }
            }
            base.WndProc(ref m);
        }

它運行良好,它在我嘗試打開應用程序時已經在運行的同一過程中創建了另一個應用程序域。

我的第一個問題是,是否可以在已經從其他用戶運行的情況下創建相同進程的應用程序域?

John正在開發此應用程序,並且具有兩個應用程序域和一個進程。 然后Steve在同一台計算機上登錄並嘗試打開此應用程序,並且該應用程序不應創建進程,而應由John在已經運​​行的進程中添加新的應用程序域。

我通過在互斥量名稱前加上“ Global \\”作為前綴來檢測在另一個用戶中運行的進程。 這里提到的

當我在program.cs中編輯以下代碼時, 第二個問題就在這里

NativeMethods.PostMessage(
                        (IntPtr)NativeMethods.HWND_BROADCAST,
                        NativeMethods.WM_SHOWME,
                        IntPtr.Zero,
                        IntPtr.Zero);

try
{
    procNumber++;
    AppDomain appDomain = AppDomain.CreateDomain("MyAppDomainApplication" + procNumber.ToString(), null, setupInfo);
    string[] arguments = { "secondary" };
    appDomain.ExecuteAssembly("MyAppDomainApplication.exe", null, arguments);
 }
 catch (Exception ex)
 {
    MessageBox.Show(ex.ToString());
 }

它創建了另一個進程,為什么它不能在Program.cs文件中工作,為什么我必須將消息發送到Form並在WndProc方法中執行相同的操作

我會回答你的第二個問題。

應用程序域是流程內部的隔離環境。 在這里,您有兩個進程,它們都有自己的應用程序域。 如果要命令另一個進程創建新的應用程序域,則必須將消息從一個進程發送到另一個進程。 這就是為什么您必須發送消息。

我還懷疑該代碼無法按照您預期的方式工作。 ExecuteAssembly()在與主用戶界面相同的線程中運行。 如果執行的程序集開始一個新的消息循環,則在每條WM_SHOWME消息之后,您的調用堆棧都會增長,最終您將獲得堆棧溢出異常。

在這種情況下,您的調用堆棧將大致如下所示:

at Application.Run()
at Main()
at AppDomain.ExecuteAssembly()
...
at Application.Run()
at Main()
at AppDomain.ExecuteAssembly()
at Application.Run()
at Main()

暫無
暫無

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

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