Version Neutral APIs - Discussion

Add-in Express™ Support Service
That's what is more important than anything else

Version Neutral APIs - Discussion
 
Andrew Szczeszynski




Posts: 44
Joined: 2007-02-02
Hi All,

I have been working with the version neutral APIs, and I'm coming across some limitations. I'm starting to lean towards changing to the version specific APIs, but I would like to know more about advantages/disadvantages of the neutral APIs. I have been trying to find some information, but it's not what I want, so I though I would start a discussion on it.

Let me see if I got this right:

Version Neutral APIs
--------------------
This API exposes the lowest common denominator of functionality for all version of Office since 2000. If you want to use something more, you can use late binding. For instance, to set a member using late binding, you could use (in C++):

// Sets the value of a member of an instance using late binding.
bool setMember(System::Object ^ instance, String ^ memberName, Object ^ value)
{
try {
System::Type ^ classType = instance->GetType();
array <Object^>^ params = gcnew array <Object^> (1);
params[0] = value;
classType->InvokeMember(memberName,System::Reflection::BindingFlags::SetProperty,
Type::DefaultBinder, instance, params);
}
catch(...) { return false; }
return true;
}


Version Specific API
--------------------

I don't fully understand this one - is this the maximum functionality of all versions? Do you need a different Interop assembly for each version of Word? How does it know which version I'm targetting? What happens if you try to access some functionality that is not available for the current version of Office? (Does this simply generate an exception that can be caught and ignored?)

What I'm especially interested in is can I use these interop assemblies, and simply catch exceptions for those functionality that is not supported, then decide on alternate functionality.

I'm finding that the version neutral APIs are great if you are not going to be accessing many of the new features. However, if your application needs to access more on a regular basis, late binding just does not cut it. It may be better to just detect when functionality fails, and decide what to do based on the exception.


Finally, is it possible to include both APIs in your project?

Sincerely,
Andrew
Posted 07 Apr, 2008 00:04:16 Top
Sergey Grischenko


Add-in Express team


Posts: 7233
Joined: 2004-07-05
Hi Andrew.

Some exceptions may get the host application to work incorrectly regardless whether you have processed them in the try ... catch code or not. I would advise you to use version-neutral PIAs. And if you need to access some version-specific properties, you can use the late binding.
Or you can also import the target interfaces explicitly in the add-in code and use them in the dynamic_cast operator. Please use the Reflector tool to copy/past any interfaces defined in version-specific interop assemblies.
Posted 07 Apr, 2008 08:06:04 Top
Andrew Szczeszynski




Posts: 44
Joined: 2007-02-02
Hi Sergey,

sorry, I'm not too familiar with the reflector tool - what is it?

In the end - will this not be the same thing? Whether I use the version neutral APIs and try to run functionality using reflection, or use the version specific APIs and run the functionality normally, will this not achieve the same thing? Why will reflection not cause the same problems if the functionality is not available?

Cheers,
Andrew
Posted 07 Apr, 2008 09:47:33 Top
Sergey Grischenko


Add-in Express team


Posts: 7233
Joined: 2004-07-05
Andrew, you will not build the project if you use different versions of PIAs in the same code. But, if you import some interfaces and use the HostVersion property of the addinmodule, you will able to call version-specific features without reflection.
http://www.aisto.com/roeder/dotnet/
Posted 07 Apr, 2008 10:32:05 Top
Andrew Szczeszynski




Posts: 44
Joined: 2007-02-02
For those interested,

I tried converting my project from version neutral to version specific and did notice significant changes. On Word 2000, even some basic functionality could not be run (for instance, it complained that 'this can only be done in outline view'). This worked perfectly fine with version neutral interop.

For those who are interested in converting between one or the other, this is what I did:
- In Visual Studio, click on 'properties' on your project
- Under 'Common Properties':'References'
- For version neutral, make sure you have included Interop.Office, Interop.VBIDE, Interop.Word (these are found under the directory OfficePIAs in your project). If you can't find them, create a new project with version neutral PIAs
- For version specific, add Microsoft.Office.Interop.Word, Microsoft.Vbe.Interop, and Office (again, found in OfficePIAs)
- Refresh dependencies on the setup project.

Also note, there are some code changes. The ones I came across for C++:

- 'using namespace Microsoft::Office::Core' in version specific is 'using namespace Office' in version neutral
- In version specific, you access lists using the square bracket indexer (e.g. MyList[1]). In version neutral, you use '->Item(<index>)'
- Accessing '->Type' in version neutral is accomplished using '->default' in version specific

Finally, you need to use reflection to access certain advanced/version specific features. The biggest problem with this is accessing a variable whose type is not even defined/available, especially enums.

Cheers,
Andrew
Posted 14 Apr, 2008 15:12:23 Top
Andrew Szczeszynski




Posts: 44
Joined: 2007-02-02
Anyone know how to obtain the value of an enum that is not even defined?

My specific problem lies in setting

ActiveWindow->View->RevisionsView

in Word. RevisionsView is an enum that is not defined in the version neutral interop. What I don't know is how to obtain the enum using reflection.

In this case, it's rather easy. I can set the member to the integer 0 or 1 (0 for wdRevisionsViewFinal, 1 for wdRevisionsViewOriginal). However, in the future, how do I obtain the enum value for a specific enum string?

(Normally I would use System::Enum::Parse, but I can't get my hands on the enum type!)

Cheers,
Andrew
Posted 14 Apr, 2008 16:19:13 Top
Sergey Grischenko


Add-in Express team


Posts: 7233
Joined: 2004-07-05
Hi Andrew.

There is no need to obtain it. You can just import the enum in your code.
Posted 15 Apr, 2008 07:17:10 Top