VSTO - .Net code throws 'System.AccessViolationException' error when automating the 'Find' object in Word (KB 292744 BUG: Automation client receives an error message or crashes when the client calls the Find object in Word)

Sometimes users are running versions of Office which are not fully up-to-date. This might be due to the fact that their local IT department has not tested the new patches and did not approve their company wide distribution, or because the machine is not connected tothe Internet and needs to be manually updated .. or some other reason. At the same time end-users are relying on COM add-ins and stand-alone COM automation programs to help with their daily work.

Later, the machine gets updated (let's suppose its user had Office 2007SP2 and he installs SP3 and the latest Cumulative Updates). Suddenly henotices that some of the programs automating Word will crash when performing certain tasks.

Let's assume the user is working with a WindowsForms application developed in a managed environment (VB.NET), which uses COM automation to open a document and perform a Find and Replace action in Word 2007:

  - everything worked as expected until he updated Office from SP2 to SP3;  - after this change, the code started to trigger a 'System.AccessViolationException' error when running this code:

Private Sub Test()   Dim wrd As Microsoft.Office.Interop.Word.Application        wrd = CreateObject("Word.Application")   wrd.Documents.Open(sFilename)   wrd.ActiveDocument.Selection.Find.ClearFormatting()

   With wrd.ActiveDocument.Selection.Find     .Text = "-"     .Replacement.Text = "-test-"     .Forward = True     .Wrap = Microsoft.Office.Interop.Word.WdFindWrap.wdFindContinue     .Format = True     .MatchCase = False     .MatchWholeWord = False     .MatchWildcards = False     .MatchSoundsLike = False     .MatchAllWordForms = False   End With  wrd.ActiveDocument.Selection.Find.Execute (Replace:=Microsoft.Office.Interop.Word.WdReplace.wdReplaceAll)End Sub

- even if we try to comment the "Selection.Find.ClearFormatting()" line, any instruction which gets executes inside the WITH block triggers a COM exception: 

Application: sampleApp.exeFramework Version: v4.0.30319Description: The process was terminated due to an unhandled exception.Exception Info: System.AccessViolationExceptionStack:   at Microsoft.Office.Interop.Word.Find.set_Style(System.Object      ByRef)   at Word2WikiPlus.Form1.ConvertHeading(Int64, System.String, System.String)   at Word2WikiPlus.Form1.Transform(System.String ByRef, Int32)   at Word2WikiPlus.Form1.Button_start_Click(System.Object, System.EventArgs)   at System.Windows.Forms.Control.OnClick(System.EventArgs)   at System.Windows.Forms.Button.OnClick(System.EventArgs)   at System.Windows.Forms.Button.OnMouseUp (System.Windows.Forms.MouseEventArgs)   at System.Windows.Forms.Control.WmMouseUp (System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)   at System.Windows.Forms.Control.WndProc(System.Windows.Forms. Message ByRef)   at System.Windows.Forms.ButtonBase.WndProc (System.Windows.Forms.Message ByRef)   at System.Windows.Forms.Button.WndProc(System.Windows.Forms. Message ByRef)   at System.Windows.Forms.Control+ControlNativeWindow.OnMessage( System.Windows.Forms.Message ByRef)   at System.Windows.Forms.Control+ControlNativeWindow.WndProc( System.Windows.Forms.Message ByRef)   at System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)   at System.Windows.Forms.Application+ComponentManager.System. Windows.Forms.UnsafeNativeMethods.IMsoComponentManager. FPushMessageLoop(IntPtr,Int32,Int32)   at System.Windows.Forms.Application+ThreadContext.RunMessageLoop Inner(Int32,System.Windows.Forms.ApplicationContext)   at System.Windows.Forms.Application+ThreadContext.RunMessageLoop (Int32,System.Windows.Forms.ApplicationContext)   at Microsoft.VisualBasic.ApplicationServices. WindowsFormsApplicationBase.OnRun()   at Microsoft.VisualBasic.ApplicationServices. WindowsFormsApplicationBase.DoApplicationModel()   at Microsoft.VisualBasic.ApplicationServices. WindowsFormsApplicationBase.Run(System.String[])   at Word2WikiPlus.My.MyApplication.Main(System.String[])

 

This entry appears in Computer Management                         > Event Viewer > Windows Logs > Application

The description for Event ID 1000 from source .NET Runtime 4.0 Error Reporting cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.

If the event originated on another computer, the display information had to be saved with the event.

The following information was included with the event:

   sampleApp.exe   0.3.3.0   4eca4fbc   oleaut32.dll   5.1.2600.5512   4802bdb7   0   0007c86c

- however, another machine that has also been updated to SP3 can successfully run the code;

 

Troubleshooting steps performed

  1. tried to eliminate the .Net layer by writing a small VBscript:

Set objDOCXSourceApp = CreateObject("Word.Application")

objDOCXSourceApp.Visible = falseobjDOCXSourceApp.DisplayAlerts = false

wscript.echo " Open Input file..."

Set objDOCXSourceDoc = objDOCXSourceApp.Documents.Open(<inputPath>)

If Err.Number <> 0 Then   objDOCXSourceApp.Application.Quit   Set objDOCXSourceDoc = Nothing   Set objDOCXSourceApp = Nothing wscript.QuitEnd If

wscript.echo " File opened OK."

Dim newDocWinSet newDocWin = objDOCXSourceDoc.ActiveWindow newDocWin.Selection.Find.ClearFormatting()newDocWin.Selection.Find.Replacement.ClearFormatting()

If Err.Number <> 0 Then wscript.QuitEnd If

wscript.echo " ClearFormatting .. OK."

With newDocWin.Selection.Find    .Text = "-"    .Replacement.Text = "-test-"    .Forward = True    .Wrap = 1 'Microsoft.Office.Interop.Word.WdFindWrap.wdFindContinue     .Format = True    .MatchCase = False    .MatchWholeWord = False    .MatchWildcards = False    .MatchSoundsLike = False    .MatchAllWordForms = FalseEnd With

'WdReplace.wdReplaceAll = 2

newDocWin.Selection.Find.Execute ,,,,,,,,,,2

wscript.echo " newDocWin.Selection.Find.Execute(Replace) .. OK."

objDOCXSourceDoc.Close (False)objDOCXSourceApp.Application.Quit

Set objDOCXSourceDoc = NothingSet objDOCXSourceApp = Nothing

     RESULT: the late binding code works;

  2. Analyzed Fusion logs and ProcMon activity trace; RESULT: the correct type libraries seem to be loaded; 

  3. Researched the Internet; RESULT: found this article: http://support.microsoft.com/kb/292744; The issues which are described are similar to what we experience when working with the Find object, but the error we receive is not listed there.

 

BUG: Automation client receives an error message or crashes when the client calls the Find object in Wordhttp://support.microsoft.com/kb/292744=======================================================================...SymptomsWhen you use an out-of-process client application that uses early binding to Automate Microsoft Word 97 or later versions of Word, the application may crash with an access violation or you may receive one of the following error messages:

 

From Microsoft Visual Basic:   > Run-time error '-2147023113 (800706f7)': The method '~' of object '~' failed > Run-time error '-2147023113 (800706f7)': Method 'Execute' of object 'Find' failed > Run-time error 430: Class does not support automation or does not support expected interface.

From Microsoft Visual C++:

  > HRESULT = 0x800706F7    RPC_X_BAD_STUB_DATA - The stub received bad data. Note In debug builds, you receive a corrupt stack warning message from an Assert dialog box, and the value of EAX is that listed above. In release builds, the stack corruption likely crashes the application soon after this point. However, the HRESULT value is likely to be similar to the above.

 

The problem occurs consistently on some computers, but may never occur on others. Installing a new application or a Microsoft Excel service pack can cause a computer that was working previously to experience the problem.

Cause

Several globally unique identifiers (GUIDs) that are used by Word for its interface identifiers were used by Excel 5.0 for an older object model that is now obsolete.

When the Excel 5.0 type library is reregistered on a system, the interface GUIDs in the registry that should point to the Word type library point to the Excel 5.0 library, and COM can mistakenly construct the wrong proxy v-table for an out-of-process client using early binding to Word. Calls that are made to this proxy return errors or crash because the proxy is configured for a dispinterface for Excel instead of for a dispinterface for the expected Word interface.

The following GUIDs are duplicated in the Excel 5.0 type library and the Word 8.0, 8.1, 10.0 and 11.0 type libraries.

The following GUIDs are affected:

  > Word.Replacement interface {000209B1-0000-0000-C000-000000000046}  > Word.Dictionary {000209AD-0000-0000-C000-000000000046}  > Word.ReadabilityStatistics {000209AE-0000-0000-C000-000000000046}  > Word.ReadabilityStatistic {000209AF-0000-0000-C000-000000000046}  > Word.Find {000209B0-0000-0000-C000-000000000046}

ResolutionTo resolve this problem, use one of the following methods.• Modify your code to use late binding when you call methods or properties on any of the above listed Word interfaces.• Reregister the Word type library on the system on which the problem occurs.The recommended solution is to use late binding. Because both type libraries describe interfaces that implement the IDispatch interface, calls to any of the IDispatch methods work regardless of which library was last registered on the system. This is the only way to be sure that your code does not encounter this error on systems that you do not administer.

 

For customers who use client applications that cannot be recompiled to use late binding, you can reregister the Word type library to resolve the problem in most cases. Because the problem returns if the Excel 5.0 library is reregistered again, this method is not an ideal resolution. However, the chances of the Excel 5.0 library being reregistered are low. Therefore, this method should work for most users.

 

To reregister the Word type library, find the appropriate type library for the version of Word that is installed on the system.

 

Version     Library name--------------------------------------Word 97     Msword8.olbWord 2000   Msword9.olbWord 2002   Msword.olbWord 2003   Msword.olb

 

Then, from the command line, use Regtlib.exe together with the full path to the type library to reregister the library for COM. Regtlib.exe calls the LoadTypeLib and RegisterTypeLib application program interfaces (APIs) on the type library (.tlb or .olb) file that is passed in. COM repairs the misconfigured registry keys. 

 How to solve this issue?

Since the user cannot modify the design of the application, he has to re-register the Word type library.

C:\Windows\Microsoft.NET\Framework\v4.0.30319\regtlibv12.exe "C:\Program Files\Microsoft Office\Office12\MSWORD.OLB"

Caution: ------------------------------------------------------------------------------* If the library registration goes wrong, you might receive the "SEHException was unhandled" message when automating the Find object.

* The .NET error message is a bit misleading ... in the managedenvironment, we didn't get any hint that the is something wrong the Find object ("Class does not support automation or does not support expected interface."). The only clue I could find is this KB: "Troubleshooting Exceptions: System.AccessViolationException"

An access violation that occurs in unsafe managed code can be expressedas either a NullReferenceException or a AccessViolationException, depending on the platform.Access violations in unmanaged code that bubble up to managed code are always wrapped in an AccessViolationException.

.. so it appears that if anything goes wrong in the unmanaged code, it will show up as a memory violation in the managed layer.* Sometimes, the error surfaces as corrupted memory exceptions: > "Attempted to read or write protected memory. This is often an indication that other memory is corrupt"; > "Es wurde versucht, im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist"------------------------------------------------------------------------------

Hopefully this blog entry will help you identify and solve the AccessViolationException error faster.

I would like to thank Mr. Domenico Zanferrari for his valuable insight and for helping me run my tests in an environment affected by the aforementioned issue.   

 

Thank you for reading my article! Bye :-)