Interop.Word not working on 64 bit Win 7
-
Tuesday, January 10, 2012 1:51 PM
After no response under General C# heading I have opened this thread here. Any help quickly would be appreciated as I have a customer in trouble.
I have a C# winform app developed on 32bit Win7 machine with Word 2007 installed, that uses interop.word to create Word documents using a .dot template ( so users with only Word 2003 can use it). For almost all customers this works fine, however for a very few that run 64bit Windows 7, an error is thrown when trying to create the Word doc. It is only if these users have Word 2003 or Word 2010 installed, but resolves if they install Word 2007 ( like mine).
As this is a rare, but serious problem, is there an easy fix I can do ( like installing a PIA on their machine )? From brief comments in other threads it appears to relate to the fact that I am 32 bit and have Word 2007, and they are 64 bi and don't. I have also seen it suggested that upgrading to VS 2010 & .NET 4 ( I use VS2008) would solve this because of the way interop is handled. This change is obviously expensive and a big opportunity for problems in my release schedule so I am very wary. Any suggestions?
All Replies
-
Tuesday, January 10, 2012 2:06 PMModeratorWithout knowing what the error message is and what code causes it, it's unlikely anyone can help you...
Cindy Meister, VSTO/Word MVP -
Tuesday, January 10, 2012 2:24 PM
I do not know the exact error message as it is exception handled by my software and I cannot get it to replicate on my development machine, but it appears to occur using :
Object oTemplatePath = (object)wordDocpath;
object templateFileFormat = WdOpenFormat.wdOpenFormatDocument;
myWordApp = new Microsoft.Office.Interop.Word.Application();
myWordDoc = myWordApp.Documents.Add(ref oTemplatePath, ref templateFileFormat, ref oMissing, ref oMissing);As it does not occur on the vast majority of users machines, but only on a few which seem to all be WIn7 64bit, it is difficult to see how to change my code to address this.
I see in this thread by you:
"Even better would be for you to upgrade to VS 2010. This supports embedding the parts of the object models you use into your project. Then it essentially doesn't matter which version of Office you use - the project becomes version-independent."
Is that my best option going forward given that I am not an advanced level programmer?
-
Tuesday, January 10, 2012 4:50 PMModerator
Hi CoppSoft
Mmm, I'd say Word 2007 is the "bad guy", here.
Assuming the code you've posted accurately reflects what you've distributed, take a very good look at the Documents.Add method in the Word API help. Four parameters is correct, but look at the data type of the second parameter, then compare what you're using.
In Word 2003, 2007 and 2010 the second parameter should be of type Boolean, you probably want False, as in object asTemplate = false; then ref asTemplate in the method.
Cindy Meister, VSTO/Word MVP- Marked As Answer by CoppSoft2011 Tuesday, January 10, 2012 5:53 PM
- Unmarked As Answer by CoppSoft2011 Tuesday, January 31, 2012 4:39 PM
-
Tuesday, January 10, 2012 5:12 PM
OK I see what you mean about the parameters for the Add method. Strangely though it worked in most cases. Do you think that could have been triggering this rare error? When you say "Word 2007" is the "bad guy" can you explain?
Thanks for your help Cindy -
Tuesday, January 10, 2012 5:23 PMModerator
Hi CoppSoft
By 2007 being "the bad guy" I mean that 2007 should have caught this error when you were testing. It's a mystery to me why it let that through, although it could have something to do with it being typed as an object. If 2007 had reacted with a "type mismatch" right from the start, you'd have caught it before distributing to n clients.
Do you have your code in try...catch blocks? If not, it would be a good idea to do so. Word could be causing any number of errors that you're not catching because they "fall between the cracks" propagating through the COM->.NET interface.
Cindy Meister, VSTO/Word MVP -
Tuesday, January 10, 2012 5:47 PM
Hi Cindy, Yes I do have it in try/catch blocks which is what threw up the error to my customer telling them that the Word doc couldn;t be created. Do you think that this issue you have identified could be the problem appearing for just a few customers, but works for most? So strange that it shows that behaviour and very difficult to pinpoint when problems are like that.
Stranger still, they first tried re-installing Word which didn;t help and then re-installed my software and that appears to have resolved it ( for now! ). Why would that work?
-
Tuesday, January 10, 2012 5:49 PMModerator
Hi CoppSoft
<<Stranger still, they first tried re-installing Word which didn;t help and then re-installed my software and that appears to have resolved it ( for now! ). Why would that work?>>
I haven't a clue...
Cindy Meister, VSTO/Word MVP -
Tuesday, January 10, 2012 5:53 PMThankyou for your help - will see if that resolves it in future!
-
Tuesday, January 31, 2012 4:53 PM
Well I adjusted the code as per your suggestion and released an update and it seems to have created more problems for people running Office 2010. I even have one customer with three copies of my software on different computers which all worked fine with the old version. They all run the same version of Windows, have Office 2010 installed and yet after updating my software on all three, just one is now having an exception fired when trying to create Word documents!! It is very strange and as I can't replicate it on my development machine, is very frustrating. My code for the offending Method is:
public static void MailMergeSingleWordDoc(string wordDocpath, string wordDocDestination, Dictionary<string, string> mailMergeData, bool visible, bool letterHead, List<string[]>[] tableContentsArray, int numBookings, int docType, bool save)
{
Object oMissing = System.Reflection.Missing.Value;
Object oTrue = true;
Object oFalse = false;
Microsoft.Office.Interop.Word._Application myWordApp = null;
Microsoft.Office.Interop.Word._Document myWordDoc = null;
//CREATING OBJECTS OF WORD AND DOCUMENT
try
{
Object oTemplatePath = (object)wordDocpath;
Object isTemplate = false;
myWordApp = new Microsoft.Office.Interop.Word.Application();
myWordDoc = myWordApp.Documents.Add(ref oTemplatePath, ref isTemplate, ref oMissing, ref oFalse);
//LOGO
if (!letterHead && Global.LogoFileName != "" && Global.LogoFileName != null)
{
try
{
string LogoPath = Global.UserFolderPath + @"\" + Global.LogoFileName;
//Calculate Logo sizes
Image myOriginalLogo = Image.FromFile(LogoPath);
Image myScaledImage = StaticMethods.SizeImageForContainer(myOriginalLogo, 150, 150);
Object linkToFile = Microsoft.Office.Core.MsoTriState.msoFalse;
Object saveWithDocument = Microsoft.Office.Core.MsoTriState.msoTrue;
Object imageWidth = myScaledImage.Width;
Object imageHeight = myScaledImage.Height;
Object left = 0;
Object top = 0;
myWordDoc.Shapes.AddPicture(LogoPath, ref linkToFile, ref saveWithDocument, ref left, ref top, ref imageWidth, ref imageHeight, ref oMissing);
}
catch (Exception) { }
}
//REMOVE UNUSED BOOKING TEXTBOXES
if (docType == 0 && numBookings > 1)
{
object zero = 0;
object chars = WdUnits.wdCharacter;
for (int i = 2; i > (numBookings - 2); i--)
{
myWordDoc.Frames[i].Range.Delete(ref chars, ref zero);
myWordDoc.Frames[i].Delete();
}
}
else if (docType == 1 && numBookings > 0)
{
object zero = 0;
object chars = WdUnits.wdCharacter;
for (int i = 3; i > (numBookings - 1); i--)
{
myWordDoc.Frames[i].Range.Delete(ref chars, ref zero);
myWordDoc.Frames[i].Delete();
}
}
//REPLACE MAILMERGE FIELDS
foreach (Field myMergeField in myWordDoc.Fields)
{
Microsoft.Office.Interop.Word.Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text;
// ONLY GETTING THE MAILMERGE FIELDS
if (fieldText.StartsWith(" MERGEFIELD"))
{
// THE TEXT COMES IN THE FORMAT OF MERGEFIELD MyFieldName \\* MERGEFORMAT
// THIS HAS TO BE EDITED TO GET ONLY THE FIELDNAME "MyFieldName"
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
// GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dot FILE
fieldName = fieldName.Trim();
// **** FIELD REPLACEMENT IMPLEMENTATION GOES HERE ****//
myMergeField.Select();
myWordApp.Selection.TypeText(" ");
foreach (KeyValuePair<string, string> fieldEntry in mailMergeData)
{
if (fieldEntry.Key == fieldName)
{
myWordApp.Selection.TypeText(fieldEntry.Value);
break;
}
}
}
}
//FILL TABLES
if (tableContentsArray != null)
{
int t = 1;
foreach (List<string[]> tableContent in tableContentsArray)
{
for (int i = 0; i < tableContent.Count(); i++)
{
if (i > 0)
myWordDoc.Tables[t].Rows.Add(ref oMissing);
for (int a = 0; a < tableContent[0].Count(); a++)
{
myWordDoc.Tables[t].Rows[i + 1].Cells[a + 1].Range.Text = tableContent[i][a].ToString();
}
}
t++;
}
}
//SAVE THE WORD DOC
if (wordDocDestination != "" && save)
{
Object oSaveAsFile = (object)wordDocDestination;
object fileFormat = WdSaveFormat.wdFormatDocument;
myWordDoc.SaveAs(ref oSaveAsFile, ref fileFormat, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);
}
//SHOW THE APP
if (visible)
myWordApp.Visible = true;
else
{
//CLOSING THE FILE
object saveChanges = WdSaveOptions.wdPromptToSaveChanges;
object originalFormat = WdOriginalFormat.wdWordDocument;
object routeDocument = false;
myWordDoc.Close(ref saveChanges, ref originalFormat, ref routeDocument);
//QUITTING THE APPLICATION
object noSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
myWordApp.Quit(ref noSaveChanges, ref originalFormat, ref routeDocument);
}
}
catch (Exception)
{
try
{
//CLOSING THE FILE
object saveChanges = WdSaveOptions.wdPromptToSaveChanges;
object originalFormat = WdOriginalFormat.wdWordDocument;
object routeDocument = false;
myWordDoc.Close(ref saveChanges, ref originalFormat, ref routeDocument);
//QUITTING THE APPLICATION
object noSaveChanges = WdSaveOptions.wdDoNotSaveChanges;
myWordApp.Quit(ref noSaveChanges, ref originalFormat, ref routeDocument);
}
catch (Exception) { }
throw;
}
}Thanks
-
Thursday, February 02, 2012 9:46 AMThat same customer with the issue on only one of their machines out of three reports that when they open up Word independently it brings up Document Recovery along the left hand side and shows the template ( rather than the new file) in recovery! I also have another customer running Word 2003 with problems too, so it appears that my original problem exists despite the suggested fix. Any suggestions please as I am stuck!!
- Edited by CoppSoft2011 Thursday, February 02, 2012 9:46 AM
-
Friday, May 11, 2012 10:23 AMany updates? I am also facing same issue on Windows Server 2008 64 Bit. Please post if got success
-
Friday, May 11, 2012 10:24 AMThis issue is with 64 Bit machines only.. tired on 32 bit, things are working fine.
-
Friday, May 11, 2012 10:42 AM
Solved my problem - I had to code it two different ways depending on Word version installed and played around with the parameters, trying to use the suggested ones in the MS documentation, and eventually ignoring those as they were causing problems. After trial and error the following works for me ( this is a method for mailmerging:
public static void MailMergeSingleWordDoc(string wordDocpath, string wordDocDestination, Dictionary<string, string> mailMergeData, bool visible, bool letterHead, List<string[]>[] tableContentsArray, int numBookings, int docType, bool save, bool logo)
{
Object oMissing = System.Reflection.Missing.Value;
Object oTrue = true;
Object oFalse = false;
Microsoft.Office.Interop.Word._Application myWordApp = null;
Microsoft.Office.Interop.Word._Document myWordDoc = null;
//CREATING OBJECTS OF WORD AND DOCUMENT
try
{
Object oTemplatePath = (object)wordDocpath;
Object isTemplate = false;
myWordApp = new Microsoft.Office.Interop.Word.Application();
if (Convert.ToDouble(myWordApp.Version) >= 12) //this is for Word 2010
{
myWordDoc = myWordApp.Documents.Add(ref oTemplatePath, ref isTemplate, ref oMissing, ref oFalse);
}
else //this is for Word 2007/2003
{
myWordDoc = myWordApp.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
}
//REMOVE UNUSED BOOKING TEXTBOXES
if (docType == 0 && numBookings > 1)
{
object zero = 0;
object chars = WdUnits.wdCharacter;
for (int i = 2; i > (numBookings - 2); i--)
{
myWordDoc.Frames[i].Range.Delete(ref chars, ref zero);
myWordDoc.Frames[i].Delete();
}
}
else if (docType == 1 && numBookings > 0)
{
object zero = 0;
object chars = WdUnits.wdCharacter;
for (int i = 3; i > (numBookings - 1); i--)
{
myWordDoc.Frames[i].Range.Delete(ref chars, ref zero);
myWordDoc.Frames[i].Delete();
}
}
//REPLACE MAILMERGE FIELDS
foreach (Field myMergeField in myWordDoc.Fields)
{
Microsoft.Office.Interop.Word.Range rngFieldCode = myMergeField.Code;
String fieldText = rngFieldCode.Text;
// ONLY GETTING THE MAILMERGE FIELDS
if (fieldText.StartsWith(" MERGEFIELD"))
{
// THE TEXT COMES IN THE FORMAT OF MERGEFIELD MyFieldName \\* MERGEFORMAT
// THIS HAS TO BE EDITED TO GET ONLY THE FIELDNAME "MyFieldName"
Int32 endMerge = fieldText.IndexOf("\\");
Int32 fieldNameLength = fieldText.Length - endMerge;
String fieldName = fieldText.Substring(11, endMerge - 11);
// GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dot FILE
fieldName = fieldName.Trim();
// **** FIELD REPLACEMENT IMPLEMENTATION GOES HERE ****//
myMergeField.Select();
myWordApp.Selection.TypeText(" ");
foreach (KeyValuePair<string, string> fieldEntry in mailMergeData)
{
if (fieldEntry.Key == fieldName)
{
myWordApp.Selection.TypeText(fieldEntry.Value);
break;
}
}
}
}
//FILL TABLES
if (tableContentsArray != null)
{
int t = 1;
foreach (List<string[]> tableContent in tableContentsArray)
{
for (int i = 0; i < tableContent.Count(); i++)
{
if (i > 0)
myWordDoc.Tables[t].Rows.Add(ref oMissing);
for (int a = 0; a < tableContent[0].Count(); a++)
{
myWordDoc.Tables[t].Rows[i + 1].Cells[a + 1].Range.Text = tableContent[i][a].ToString();
}
}
t++;
}
}
//SAVE THE WORD DOC
if (wordDocDestination != "" && save)
{
try
{
Object oSaveAsFile = (object)wordDocDestination;
Object fileFormat = WdSaveFormat.wdFormatDocument;
myWordDoc.SaveAs(ref oSaveAsFile, ref fileFormat, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing,
ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);
/*
//This is correct but doesn't give doc correct name
myWordDoc.SaveAs(ref oSaveAsFile, ref fileFormat, ref LockComments,
ref oMissing, ref AddToRecentFiles, ref oMissing,
ref ReadOnlyRecommended, ref EmbedTrueTypeFonts,
ref SaveNativePictureFormat, ref SaveFormsData,
ref SaveAsAOCELetter, ref Encoding, ref InsertLineBreaks,
ref AllowSubstitutions, ref LineEnding, ref AddBiDiMarks);
*/
}
catch (Exception)
{
throw;
}
}
//SHOW THE APP
if (visible)
myWordApp.Visible = true;
else
{
//CLOSING THE FILE
myWordDoc.Close(ref oFalse, ref oMissing, ref oMissing);
//QUITTING THE APPLICATION
myWordApp.Quit(ref oFalse, ref oMissing, ref oMissing);
}
}
catch (Exception)
{
try
{
//CLOSING THE FILE
myWordDoc.Close(ref oFalse, ref oMissing, ref oMissing);
//QUITTING THE APPLICATION
myWordApp.Quit(ref oFalse, ref oMissing, ref oMissing);
}
catch (Exception) { }
throw;
}
}
Hope this helps!!
- Proposed As Answer by coppsoft Friday, May 11, 2012 10:42 AM
- Marked As Answer by Cindy Meister MVPMVP, Moderator Friday, May 11, 2012 1:11 PM

