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