Here is Microsoft’s workaround for the problem hang-ups during in-process debugging:
“The idea is that we want to wait for the type –registering threads to finish before we call addin.FinishInitialization.
What I did is to record the number of threads in the process before we activate add-in. After addin.Initialize (when the type-registering happens), I’ll track the thread number going up and down. When the thread number is exactly 1 + pre-addin-load number, I know the type registering is done. The workaround kicks in only during debugging. With the workaround, the problem goes away as I tried (note some time you may need to wait a while, as long as several seconds, for the break point to hit.)…”
private IEntryPoint LoadAddIn(string addInPath, string startUpClass, AddInProcess addInProcess)
{
try
{
//Start Workaround for AddIn_Startup debug hanging problem
// Used to keep track the type registering threads.
int threadCountBeforeLoadingAddIn = Process.GetCurrentProcess().Threads.Count;
// End Workaround
// Search for the AddIn at the given location and make sure that it has
// the same Startup class. Also make sure that we can load this Addin
// using the default VSTA pipeline. This function will return a token
// to the AddIn which can be later on used to actually load the AddIn.
Collection<AddInToken> addInToken = AddInStore.FindAddIn(typeof(IEntryPoint), AddInStoreExtensions.DefaultPipelinePath, addInPath, startUpClass);
// Assert the AddIn is valid.
System.Diagnostics.Debug.Assert(addInToken.Count >= 1);
// If the AddIn is not valid then return false.
if (addInToken.Count == 0)
return null;
IEntryPoint addIn = null;
// Using the Token returned above, load the AddIn. This will create an
// instance of AddIn EntryPoint class to activate the AddIn.
if (addInProcess == null)
{
// Load the AddIn in the same process as the host.
addIn = addInToken[0].Activate<IEntryPoint>(AddInSecurityLevel.FullTrust);
}
else
{
// Load the AddIn in external process.
addIn = addInToken[0].Activate<IEntryPoint>(addInProcess, AddInSecurityLevel.FullTrust);
}
// Initialize AddIn by calling into functions of the AddIn EntryPoint instance.
addIn.Initialize(this.serviceProvider);
//Start Workaround for AddIn_Startup debug hanging problem
// Make sure the type-registering thread is started.
int timesToTry = 50; // 5 seconds;
bool typeRegisteringThreadStarted = false;
while ((timesToTry--) > 0 && System.Diagnostics.Debugger.IsAttached)
{
int count = Process.GetCurrentProcess().Threads.Count;
if (count >= threadCountBeforeLoadingAddIn + 2)
{
typeRegisteringThreadStarted = true;
Debug.WriteLine("typeRegisteringThreadStartedt: true");
break;
}
Thread.Sleep(100);
}
//End Workaround
addIn.InitializeDataBindings();
//Start Workaround for AddIn_Startup debug hanging problem
timesToTry = 50;
while ((timesToTry--) > 0 && System.Diagnostics.Debugger.IsAttached)
{
// assume the addin startup does not create new threads.
int count = Process.GetCurrentProcess().Threads.Count;
if (count == threadCountBeforeLoadingAddIn + 1 && typeRegisteringThreadStarted)
{
break;
}
else if (count > threadCountBeforeLoadingAddIn + 1)
{
typeRegisteringThreadStarted = true;
}
Debug.WriteLine("thread count: " + count);
Thread.Sleep(100);
}
// End Workaround
addIn.FinishInitialization();
// Return the loaded AddIn.
return addIn;
}
catch (Exception ex)
{
// Do not let error of this AddIn affect others
System.Diagnostics.Trace.WriteLine(ex.ToString());
System.Diagnostics.Debug.Assert(false);
return null;
}
}
Posted
Jun 22 2009, 01:48 PM
by
BillL