hey all

 I just thought I would share with everyone something I that I wrote that I
find saves me lot of time. If you are developing a customer .NET
bootstrapper you periodically need to attach and debug your
BootstrapperApplication.

 One can easily solve this by having a line

System.Diagnostics.Debugger.Launch();

somewhere in your BootstrapperApplication::Run

This will usually provide you with a dialog and you can pick a option to
debug your bootstrapper.

This can get very tiring soon :).Typically my workflow involves having my
Visual Studio 2010 open with my installers solution. Let's call it
CoreInstallers.sln. I always want this devenv process to be
the preferred debugger.

You can solve this by incorporating the attached code and simply add these
two lines

string message = AutoDebugAttacher.Attach();
Engine.Log(LogLevel.Verbose, "Debugger Message " + message);

somewhere in your BootstrapperApplication::Run.

Basically it finds a devenv process first that has a window title of your
solution.  Then it uses COM/Visual Studio Automation model to automatically
attach devenv to your bootstrapper process.  There is an additional guard
that happens only when you have a specific environment variable set.
Everything is done using .NET 4 DLR so you don't add any unneeded
references to your bootstrapper project.

Hope your find it useful.
Thanks
raj




Implementation of AutoDebugAttacher.Attach()
___________________________________________________________________
    public static class AutoDebugAttacher
    {
        //We don't attempt an debugger attach unless
        //ENV_VARIABLE_NAME environment variable is set to
        //EXPECTED_ENV_VARIABLE_VALUE
        const string ENV_VARIABLE_NAME = "WIXAUTOATTACH";
        const string EXPECTED_ENV_VARIABLE_VALUE = "1";

        //We always attach to the devenv that has this solution open
        const string EXPECT_DEVENV_SOLUTION = "CoreInstallers";

        [DllImport("ole32.dll")]
        private static extern int CreateBindCtx(uint reserved, out IBindCtx
ppbc);

        public static string Attach()
        {
            //If enviroment variable doesn't have an expected value we
don't attach
            var currentValue =
Environment.GetEnvironmentVariable(ENV_VARIABLE_NAME);
            if (!string.IsNullOrWhiteSpace(currentValue) && currentValue ==
EXPECTED_ENV_VARIABLE_VALUE)
            {
                return AttachInner();
            }

            return ENV_VARIABLE_NAME + "not declared";
        }

        static string AttachInner()
        {
            string returnMessage = string.Empty;
            try
            {
                var devEnvProcesses = Process.GetProcessesByName("devenv");
                Process interestingProcess = null;
                foreach (var process in devEnvProcesses)
                {
                    var mainWindowTitle = process.MainWindowTitle;
                    if (mainWindowTitle.StartsWith(EXPECT_DEVENV_SOLUTION))
                    {
                        interestingProcess = process;
                        break;
                    }
                }

                if (interestingProcess == null)
                    return "Devenv process not located";

                dynamic dte = GetDTE(interestingProcess);
                if (dte == null)
                    return "EnvDTE could not be found";

                //Once EnvDTE.DTE is located attempt to attach
                dynamic debugger = dte.Debugger;
                var processes = debugger.LocalProcesses;
                int currentProcessId = Process.GetCurrentProcess().Id;
                foreach (dynamic p in processes)
                {
                    if (p.ProcessID == currentProcessId)
                    {
                        p.Attach();
                        break;
                    }
                }

            }
            catch (Exception ex)
            {
                returnMessage = ex.Message;
            }

            return returnMessage;
        }

        /// <summary>
        /// Given a Process Id of devenv process returns the corresponding
EnvDTE.DTE object
        /// </summary>
        private static object GetDTE(Process devenvProcess)
        {
            IBindCtx bindCtx = null;
            IRunningObjectTable rot = null;
            IEnumMoniker enumMonikers = null;
            object runningObject = null;
            try
            {
                int processId = devenvProcess.Id;
                //Change to 10.0 when we upgrade visual studio 2008 to 2010
                string progId = "!VisualStudio.DTE.10.0:" +
processId.ToString();

                Marshal.ThrowExceptionForHR(CreateBindCtx(0, out bindCtx));
                bindCtx.GetRunningObjectTable(out rot);
                rot.EnumRunning(out enumMonikers);

                IMoniker[] moniker = new IMoniker[1];
                IntPtr numberFetched = IntPtr.Zero;
                while (enumMonikers.Next(1, moniker, numberFetched) == 0)
                {
                    IMoniker runningObjectMoniker = moniker[0];

                    string name = null;

                    try
                    {
                        if (runningObjectMoniker != null)
                        {
                            runningObjectMoniker.GetDisplayName(bindCtx,
null, out name);
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                    }

                    if (!string.IsNullOrEmpty(name) && string.Equals(name,
progId, StringComparison.Ordinal))
                    {

Marshal.ThrowExceptionForHR(rot.GetObject(runningObjectMoniker, out
runningObject));
                        break;
                    }
                }

            }
            finally
            {
                if (enumMonikers != null)
                {
                    Marshal.ReleaseComObject(enumMonikers);
                }

                if (rot != null)
                {
                    Marshal.ReleaseComObject(rot);
                }

                if (bindCtx != null)
                {
                    Marshal.ReleaseComObject(bindCtx);
                }
            }

            return runningObject;
        }
    }
}
------------------------------------------------------------------------------
Free Next-Gen Firewall Hardware Offer
Buy your Sophos next-gen firewall before the end March 2013 
and get the hardware for free! Learn more.
http://p.sf.net/sfu/sophos-d2d-feb
_______________________________________________
WiX-devs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/wix-devs

Reply via email to