Over-zealous off-topic police
I've noticed that on this forum in particular, moderators are over-zealous in describing posts as off-topic.
For example, my recent posthttp://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1657867&SiteID=1 asking about Thread.CurrentPrincipal in a VSTO 2005 application was moved by Ji Zhou to a forum "Off-topic posts" and he advised me to post again on a VBA forum (which is totally inappropriate as VBA experts are highly unlikely to know about how Culture is handled in managed code).
Please be more flexible and make more effort to answer questions rather than pushing them to a different forum.
Meanwhile I'll ask the question again here:
I have an Excel 2003 workbook with a VSTO 2005 customisation.
It exposes an object model to Excel VBA code using code similar to the following in ThisWorkbook.cs:
Code Snippet
private
void ThisWorkbook_Startup(object sender, System.EventArgs e){
Globals.ThisWorkbook.Open +=
new Microsoft.Office.Interop.Excel.WorkbookEvents_OpenEventHandler(ThisWorkbook_Open);}
void
ThisWorkbook_Open(){
ThisApplication.Run("Register", new MyApplicationObject(), lots of Type.Missing );
}
The VBA macro "Register" called by the above code simply saves the instance of MyApplicationObject in a module variable so that it is available to be called subsequently from VBA code.
The first time VBA calls a method of my .NET class (MyApplicationObject), I set Thread.CurrentPrincipal to a custom GenericPrincipal that is needed by my .NET code.
But each time control is returned to VBA, and VBA calls my .NET code again, Thread.CurrentPrincipal is reset to an unauthenticated GenericPrincipal.
Is there a way to set Thread.CurrentPrincipal to a GenericPrincipal and have it persist across calls from VBA? I thought about AppDomain.SetPrincipalPolicy, but that can only be used to set a WindowsPrincipal.
Hi Christin
I've read Joe's question through very carefully, and I don't think it's at all VBA-related. More a question of COM-Framework interop, but a very obscure one. Right off-hand, Andrew Whitechapel is a name that comes to mind who might have an idea what's going on :-)
But Joe, it couldn't hurt to try asking in the Framework.interop newsgroup. Those folks deal with the COM-.NET interface on a regular basis and someone who frequents that group might have an idea what's going on.
> It was our intention to suggest that a better answer might come from a VBA forum
I'm grateful for any suggestions of other places where I may get an answer, but less appreciative of having the post removed from the original forum.
Further to this, I have done the same test with my managed assembly called using standard COM Interop.
In this case, the Thread.CurrentPrincipal is preserved across calls from VBA.
I guess with standard COM Interop, the managed code is running in the default AppDomain.
I understand VSTO creates a separate AppDomain for VSTO managed code - and I guess the problem must be something specific about the transition between unmanaged and managed code in this scenario. I would have thought this could only be analyzed by someone who knows the internals of how VSTO integrates with unmanaged code in Office - and if no-one on the VSTO team can answer it (!!!) surely it's unlikely that VBA or even Interop experts will be able to help.
Still hoping someone will be able to help.
Hmm... this is interesting. I've had a look at the code in the VSTO runtime, and although I'm not completely sure of the code path that gets us to this situation, it does seem to be an appdomain boundary issue. Certainly, by default, when entering an appdomain, the CLR uses Principal and Identity objects that represent unauthenticated users, which is what you're seeing.
One question - can't you simply reattach your custom principal on each call? You can obviously do all the heavy lifting required to set up your principal once up front, and then cache it for later use.
Andrew,
Thanks for taking the time to look at this.
Reattaching the custom principal on each call is a daunting prospect. The managed class library exposes an ComVisible object model to VBA. Basically an instance of a managed Factory class is passed to a VBA module using Application.Run when the VSTO app starts up, and the VBA code can subsequently use this Factory class instance to access all of the object model.
The implication is that *every* ComVisible method or property potentially needs to have code to set the Principal. Including new methods and properties that may be added by a maintenance programmer in the future. Somewhere along the line, it's bound to be forgotten.
I think Interop between VBA and VSTO Managed code is an important area that hasn't to date received as much attention as it merits. I work in the financial sector where there is a large investment in VBA skills and legacy VBA code, and VSTO provides a great way to migrate some of this stuff to a more structured architecture. But unfortunately simple things like setting a Principal, which used to work in an earlier version of the library that used standard COM Interop rather than VSTO, are causing problems.
> Hmm... this is interesting
I hope it's interesting enough for you to want to spend more time on it 
Joe