Zaksh
Zaksh

Reputation: 963

Multiple app domains on a single process winform application

I am creating app domain in my winform application using this code in program.cs file

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

and in my MainForm (Form) I override the code WndProc method and wrote this

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

It is working fine, it creates another app domain in the same process already running when I try to open my application.

My first question is can I create app domain of the same process in already running from other user, for example

John is working on this app and having two app domains and one process. And Steve logged in on the same machine and tried to open this application and application should not create process and it should add new app domain in already running process by John.

I detected the process running in another user by prefixing the name of the mutex with "Global\". as mentioned here

and second question is here when I edit the following code in program.cs

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

to

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

It creates another process why it is not working in Program.cs file, why should I have to send message to my Form and do the same thing in WndProc method

Upvotes: 1

Views: 4245

Answers (1)

mgronber
mgronber

Reputation: 3419

I'll answer to your second question.

Application domains are isolated environments inside process. Here you have two processes and they both have their own application domains. You must send a message from one process to another if you want to command the other process to create a new application domain. That is why you have to send the message.

I also suspect that the code does not work in the way you have intended. The ExecuteAssembly() is run in the same thread as the main user interface. If the executed assembly begins a new message loop, your call stack will grow after every WM_SHOWME message and you will eventually get stack overflow exception.

In that case your call stack will look more or less like this:

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

Upvotes: 1

Related Questions