Несколько доменов приложений в одном приложении winform процесса - PullRequest
1 голос
/ 24 февраля 2012

Я создаю домен приложения в моем приложении winform, используя этот код в файле program.cs

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

Работает нормально, создает другой домен приложения в том же процессе, который уже запущен, когда я пытаюсь открыть свое приложение.

Мой первый вопрос - могу ли я создать домен приложения изтот же процесс уже запущен от другого пользователя, например

Джон работает над этим приложением и имеет два домена приложения и один процесс.И Стив вошел в систему на той же машине и попытался открыть это приложение, и приложение не должно создавать процесс, и оно должно добавить новый домен приложения в уже запущенный процесс Джоном.

Я обнаружил процесс, запущенный у другого пользователя, по префиксуимя мьютекса с "Глобальным \".как уже упоминалось здесь

и второй вопрос здесь, когда я редактирую следующий код в 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 , почему я должен отправлять сообщение в форму и делать то же самое в методе WndProc

1 Ответ

1 голос
/ 24 февраля 2012

Я отвечу на ваш второй вопрос.

Домены приложений - это изолированные среды внутри процесса.Здесь у вас есть два процесса, и оба имеют свои собственные домены приложений.Вы должны отправить сообщение от одного процесса другому, если вы хотите дать команду другому процессу создать новый домен приложения.Вот почему вы должны отправить сообщение.

Я также подозреваю, что код работает не так, как вы планировали.ExecuteAssembly () запускается в том же потоке, что и основной пользовательский интерфейс.Если выполненная сборка начинает новый цикл сообщений, ваш стек вызовов будет расти после каждого сообщения WM_SHOWME, и вы в конечном итоге получите исключение переполнения стека.

В этом случае ваш стек вызовов будет выглядеть примерно так:*

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