4

I have a VSTO-addin, which uses CustomTaskPanes. My code compiles and works fine, but problem comes from code analizers, like Resharper and Code contracts for .net.

This code provokes error messages from both analizers:

CustomTaskPane taskPane = CustomTaskPanes.Add(new UserControl(), "Title");
taskPane.DockPosition = MsoCTPDockPosition.msoCTPDockPositionFloating;

Cannot convert source type 'Microsoft.Office.Core.MsoCTPDockPosition [office, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c]' to target type 'Microsoft.Office.Core.MsoCTPDockPosition [Microsoft.Office.Tools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]'

That is weird, because public type Microsoft.Office.Core.MsoCTPDockPosition exists only in office.dll. Anyway, I tried to resolve it using aliases and named Microsoft.Office.Tools.Common as Tools_Common:

extern alias Tools_Common;
using System;
using System.Windows.Forms;
using Microsoft.Office.Core;
using Tools_Common::Microsoft.Office.Tools;
using CustomTaskPane = Tools_Common::Microsoft.Office.Tools.CustomTaskPane;

But it didn't help at all. What is the cause of the message? How can I solve it (especially for code contracts)?

Also, I found another strange artifact - Resharper's autocomplete shows MsoCTPDockPosition like it exists in Microsoft.Office.Tools.Common.dll, but then I try to do autocomplete, it uses office.dll version: enter image description here

Alex Butenko
  • 3,664
  • 3
  • 35
  • 54
  • Have you used Reflector or ILSpy to verify that the type does not exist in Microsoft.Office.Tools.Common.Dll? If the type exists in both dll's in the same namespace than you need to kill one of the references. – Ryan Mann Jan 30 '16 at 03:46
  • They both do. But I cannot kill any of them, because i'm using them. And seriously, do I need to to kill it in order to make code analyzers happy? It is usual thing, this is why aliases invented, but here it doesn't help. Compiler works well even without aliases. – Alex Butenko Jan 30 '16 at 03:58
  • Just be like me and don't use Resharper! Lol It sounds like a bug in Resharper or Code Contracts. One or the other is actually trying to load the types and the one it grabbed conflicts with the one in the first referenced dll with the type it grabbed or something along those lines. Honestly I don't use either of those tools, I've found Visual Studio 2015 to be good enough for me not to need Resharper anymore. – Ryan Mann Jan 30 '16 at 04:01
  • Can't you create a rule for Resharper to stop this check for this file? – T.S. Jan 30 '16 at 05:26
  • @T.S. I can, but what about Code contracts for .NET? – Alex Butenko Jan 30 '16 at 05:34
  • Never worked with contracts, so can't tell. – T.S. Jan 30 '16 at 05:35
  • I think the problem is that your taskPane object is from the "Tools" library, but the position Enum is not. Try either casting taskPane explicitly to an Office.Taskpane object or using the .InnerObject property. – Cindy Meister Jan 31 '16 at 16:33
  • @CindyMeister I'm sorry, but I'm not aware what is Office.Taskpane and where to get .InnerObject. I would be definitely happy to learn. – Alex Butenko Feb 01 '16 at 10:30
  • The VSTO objects always derive from native Office objects. The VSTO objects are in the "Tools" namespace; the native Office objects in the "Interop" namespace. Right now, you're using a Tools.Taskpane, but that is built on the Office.Taskpane. Every VSTO object that derives from an Interop object has the InnerObject property. Just type "." and you should get it in Intellisense. InnerObject accesses the native object that's "wrapped up" in the VSTO object. Give it a try :-)? – Cindy Meister Feb 02 '16 at 17:46

2 Answers2

2

You should use Microsoft Office 15.0 Object Library from the COM tab in VS instead of that office.dll

0

So, I tried a few different ways and found solutions. I found that if I change the Office.dll assembly to another version from

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Visual Studio Tools for Office\PIA\Office15\Office.dll, 15.0.4420.1017

to

C:\Windows\assembly\GAC_MSIL\office, 15.0.4787.1001

then Resharper works fine. But Code Contracts still give me the same error. So I fooled it using the dynamic word

((dynamic) taskPane).DockPosition = MsoCTPDockPosition.msoCTPDockPositionFloating;

I'm not really happy about using dynamic. But Code Contracts are pretty important to me, so I can tolerate a little dirtiness for that.

If someone can explain, why Resharper started to work well after I changed version or find better, cleaner solution for Code Contracts - I will reaccept the answer.

Edit:

((dynamic) taskPane).DockPosition shows TargetExceptions and says that the property doesn't exist in the object. So I changed it to use reflection

typeof(CustomTaskPane)
    .InvokeMember("DockPosition", BindingFlags.SetProperty, null, taskPane, new object[] { MsoCTPDockPosition.msoCTPDockPositionFloating }, null);
Alex Butenko
  • 3,664
  • 3
  • 35
  • 54
  • 1
    FWIW, I blew a bunch of time going through the whole same exercise. I have a big via steel project that's got tons of these errors. In the end, I just manually set each error to be ignored and R# and got on with my life, which is annoying but at least he got the job done. I would be keen to know a real solution. The substitution you mentioned above doesn't work. The dynamic trick does work. I've also tried doing explicit casts which makes the compiler happy, but not R#. – Wade Hatler Mar 19 '16 at 18:28