Word 2003 Crashes When Viewing Custom Properties Updated by DSOFile.DLL
One of the neat things we take advantage of in QualTrax is Microsoft’s DSOFile.dll. That DLL allows programs to view and/or update the properties of Office documents without requiring Office on the server or requiring the bulky overhead of Word Automation (which Microsoft does not recommend on a web server).
This ability may not sound that exciting until you realize Office provides a Custom tab in the Properties window to let you record your own unique information. QualTrax takes advantage of this to embed (and subsequently display!) specifics about the document and its lifecycle in the document itself– stuff like Revision Number, Publication/Effective Date, Editor, Expiration Date and even the Signature Manifestation for FDA 21 CFR Part 11 approvals.
Migrating this feature over to .NET 2.0 and C#, I ran into some peculiar behavior.
The process worked beautifully when I was filling in “TODO” for every field. As I started to flesh out the Document objects, I plugged in real live information. That’s where I ran into problems. Everything would run smoothly with no errors to hint something was wrong.
After the code executed I went to open my Word document and it would open normally. All seemed well. However anytime I went to Word’s File->Properties menu, Word 2003 would crash:
Clicking on What data does this error report contain? provided little assistance:
Once I reopened Word– if I went to Insert->Field; selected DocProperty as my Field Name, I could see my custom variables listed in the Field properties list box and I could insert most of them into my document without crashing. Saving after inserting those fields was another matter altogether. ;)
When I went to the file through Windows Explorer and right clicked on the Word file and selected Properties, the normal Word Properties window would come up. Alas, when I clicked on the Custom tab, my fields were not displayed:
So I went through a fun troubleshooting experience. First I thought DSOFile was not completely writing my file, but that wasn’t it and because I was using System.Runtime.InteropServices.Marshal.ReleaseComObject I knew the object was no longer interfering. I thought maybe the approval record data was too long, but that wasn’t it.
After opening and crashing the same document a few times in a row, Word takes the liberty of repairing the document for you and removing the what it thinks is bad. That’s where I got a good strong lead– I could see it added all my fields until it got to a date field that would have been blank.
“Eureka!” I thought, “It must not like that crazy 1/1/0002 12:00:00 AM date.”
But my heart sank a bit when I ran to the code and saw that I had already accounted for that (Blast that foresight of mine!). If the date was null or the system default, I replaced it with an empty string. But for kicks, I changed that function to replace those bad dates with my second favorite test string, “TODO” (Side note– my favorite test string is “ISUCK” or variations such as email@example.com).
I ran it again and after a series of crashing and reopening, Word repaired the document. This time it got past all the blank dates… but it stopped right before a text field that would have been set to an empty string. So I intercepted those blank fields and changed them to “N/A”.
Ran it again and great success! No crashes and all variables were accounted for. Times were good.
At that point I was unenthused about having to account for the different languages our application runs over. I was just thinking “What’s N/A in Portugeuse?” when Mark Duncan asked, “Can you use a space?”
I changed my “TODO”s and my “N/A”s to a space– ran it through and Word 2003 liked that. So there you go. A blank space is perfect– no need for translations there!
If you are using a DSOFile.OleDocumentPropertiesClass object and calls such as dsoDoc.CustomProperties[index].set_Value(ref myValue); through C# and you started getting similiar Word 2003 crashes— be on the lookout for empty strings in your field values. A quick little check may be all you need:
if (myValue.ToString() == “”)
myValue = ” “;