Ticket #37597

WordBasic object access yields casting error

Open Date: 2017-10-23 11:50 Last Update: 2017-10-25 12:11

Reporter:
Type:
Status:
Closed
Component:
(None)
MileStone:
(None)
Priority:
5 - Medium
Severity:
5 - Medium
Resolution:
None
File:
None

Details

I have to programmatically open a Word template that has Auto macros in it and I need to prevent those auto macros from firing. Normally this is done using the WordBasic.DisableAutoMacros(1) call.

With other Office API wrappers you can do this:

object[] argValues = { 1 }; Application.WordBasic.GetType().InvokeMember("DisableAutoMacros", BindingFlags.InvokeMethod, null, Application.WordBasic, argValues, null, null, null);

but in NetOffice when you try to do anything with the WordBasic object you get an exception thrown:

System.InvalidCastException: 'Specified cast is not valid.'

Ticket History (3/4 Histories)

2017-10-23 11:50 Updated by: chadknudson
  • New Ticket "WordBasic object access yields casting error" created
2017-10-23 16:38 Updated by: sebastiandotnet
  • Resolution Update from None to Accepted
Comment

i'm on it.

2017-10-23 17:56 Updated by: sebastiandotnet
Comment

Seems to be the anonymous WordBasic object does not implement the IDispatch interface.

Moreover, my test with the interop assemblies (12.0)

object[] argValues = { 1 }; Application.WordBasic.GetType().InvokeMember("DisableAutoMacros", BindingFlags.InvokeMethod, null, Application.WordBasic, argValues, null, null, null);

failed with a TargetInvocationException(DISP_E_MEMBERNOTFOUND)

what kind of office wrapper works for you here? (+office version and any special)

thanks for informations *Sebastian

2017-10-25 12:11 Updated by: chadknudson
  • Resolution Update from Accepted to None
  • Status Update from Open to Closed
  • Ticket Close date is changed to 2017-10-25 12:11
Comment

I was attempting to invoke the function by name, my bad. I wrote a little helper wrapper around WordBasic to illustrate how to do it correctly. Lots of help on the internet from places like: https://bytes.com/topic/c-sharp/answers/244327-idispatch-getidsfromnames to get me pointed in the right direction. I found a number of other users out there who had struggled with calling WordBasic functions so I thought I better do my part and share the implementation that worked for me. I wrapped it up in a WordBasicHelper class so that it looked very similar to Word Basic in use :-)

using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using Word = Microsoft.Office.Interop.Word;

[Guid("00020400-0000-0000-c000-000000000046")] InterfaceType(ComInterfaceType.InterfaceIsIUnknown) public interface IDispatch {

PreserveSig int GetTypeInfoCount(); ITypeInfo GetTypeInfo( MarshalAs(UnmanagedType.U4) int iTInfo, MarshalAs(UnmanagedType.U4) int lcid);
PreserveSig int GetIDsOfNames( ref Guid riid, ArraySubType = UnmanagedType.LPWStr) string[] rgsNames, int cNames, int lcid, MarshalAs(UnmanagedType.LPArray) int[] rgDispId);
PreserveSig int Invoke( int dispIdMember, ref Guid riid, MarshalAs(UnmanagedType.U4) int lcid, MarshalAs(UnmanagedType.U4) int dwFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, MarshalAs(UnmanagedType.LPArray)Out object[] pVarResult, ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo, MarshalAs(UnmanagedType.LPArray)Out IntPtr[] pArgErr);

}

namespace WordBasicInvokeRepro {

public class WordBasicHelper {
public Word.Application WordApp { get; set; } public IDispatch IDispatchWordBasic { get; set; } public Dictionary<string, int> DispIdsOfWordBasicFunctions = new Dictionary<string, int>(); private Guid dummy = Guid.Empty;
public WordBasicHelper(Word.Application app) {
WordApp = app; IDispatchWordBasic = app.WordBasic;
}
public void DisableAutoMacros(int disableMode) {
if ((disableMode < 0) || (disableMode > 1))
throw new ArgumentException("DisableAutoMacros can only be called with a parameter of 0 or 1");
// First time we call DisableAutoMacros we will need to look up the dispIdMember for the function if (DispIdsOfWordBasicFunctions.ContainsKey("DisableAutoMacros"))
DispIdsOfWordBasicFunctionsDisableAutoMacros = GetWordBasicFunctionId("DisableAutoMacros");
object[] argValues = { disableMode }; System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo = new System.Runtime.InteropServices.ComTypes.EXCEPINFO(); System.Runtime.InteropServices.ComTypes.DISPPARAMS dispParams = new System.Runtime.InteropServices.ComTypes.DISPPARAMS(); object[] varResult = new object1; IntPtr[] argErr = new IntPtr1;
IDispatchWordBasic.Invoke(DispIdsOfWordBasicFunctionsDisableAutoMacros, ref dummy, 0x800, (int)BindingFlags.InvokeMethod, ref dispParams, varResult, ref exceptionInfo, argErr);
}
public int GetWordBasicFunctionId(string functionName) {
string[] rgsNames = new string1; int[] rgDispId = new int1; rgsNames0 = functionName; IDispatchWordBasic.GetIDsOfNames(ref dummy, rgsNames, 1, 0x800, rgDispId); return rgDispId0;
}
}

}

This issue can be closed and marked as not reproducible. This was totally user error on my part.

Attachment File List

No attachments

Edit

You are not logged in. I you are not logged in, your comment will be treated as an anonymous post. » Login