Wednesday, December 28, 2005 2:44 PM
As i toiled over this, I was sure there was some problem with the InfoPath Automation I was doing:
infoPathApplication =
new ApplicationClass();
oXDocumentCollection = infoPathApplication.XDocuments;
oXDocument = oXDocumentCollection.NewFromSolution(psrTemplateUrl);
The symptom: InfoPath just hangs right on this line. Now, to put some context around it...
I found a nifty way to save our accountants tons of hours through the year by prefilling parts of the form. The accountants select a lookup key from a dropdown, and the associated rules run some directives that do some stuff. Anyway, I could automate all that for all accountants just by pluggin in the value right into the Xml Document Object Model used by InfoPath (more on that later). This process is invoked from a web service call, hence it runs in the ASP.NET context. Additionally, to mock a Request-only message pattern (because this takes about an hour to run), I split off a worker thread so the main thread could return immediately.
The problem manifested when I deployed this solution to the dev server. First I got some security errors...Oh, I need to impersonate, so I do so in Web.config. Then, some more hanging. Oh! I need to login as my impersonated account and clear some of the IE warning dialogs. OK so far. This is when I split off a thread from the threadpool using the BeginInvoke pattern of the Delegate class. Again, more security errors occurred. After a quick Google search, I see that worker threads are now harnessed under the WindowsIdentity that harnessed them. So, one can use the WindowsImpersonationContext class to solve this (anywhere in code running under the ThreadPool thread):
WindowsIdentity winId = WindowsIdentity.GetCurrent();
WindowsImpersonationContext impersonationContext = winId.Impersonate();
Impersonation occurs until you undo it with:
impersonationContext.Undo();
At this point, more hair pulling because InfoPath continued to hang at the NewFromSolution() call. Finally, I thought to assign the thread the same principle as the WindowsPrincipal (which seemed to show up as the authenticated caller, not the impersonation context) - And voila, we're cooking with grease!
WindowsImpersonationContext impersonationContext = winId.Impersonate();
System.Security.Principal.WindowsPrincipal principal = new WindowsPrincipal(winId);
System.Threading.Thread.CurrentPrincipal= principal;
Oh, and for those of you still hangin' on for the InfoPath automation solution....
Remember that a control (named 'NameLookUp) had some rules on it. The rules will execute when you set the .text property through automation.
You will need to reference 2 assemblies
1) Microsoft Office InfoPath 1.0 Type Library. You can find this in the COM section of your add reference dialog
2) Microsoft.Office.Interop.InfoPath.Xml. To find this gem, browse to:C:\Program Files\Microsoft Office\OFFICE11\Microsoft.Office.Interop.InfoPath.Xml.dll
It is as simple as this (the setup code from above applies):
using
Microsoft.Office.Interop.InfoPath;
Microsoft.Office.Interop.InfoPath.Xml.IXMLDOMNode oProjectNumber;
oProjectNumber = oXDocument.DOM.selectSingleNode("//my:NameLookUp");
oProjectNumber.text = projectNumber;
oXDocument.SaveAs(savePath + fileName); //here i am just saving the prefilled form for the accountants.