views:

622

answers:

2

After moving a project from .NET 1.1 to .NET 2.0, MsBuild emits lots of warnings for some COM objects.

Sample code for test (actual code doesn't matter, just used to create the warnings):

using System;
using System.DirectoryServices;
using ActiveDs;
namespace Test
{
    public class Class1
    {
        public static void Main(string[] args)
        {
            string adsPath = String.Format("WinNT://{0}/{1}", args[0], args[1]);
            DirectoryEntry localuser = new DirectoryEntry(adsPath);
            IADsUser pUser = (IADsUser) localuser.NativeObject;
            Console.WriteLine("User = {0}", pUser.ADsPath);
        }
    }
}

Warning messages look like

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets : warning : At least one of the arguments for 'ITypeLib.RemoteGetLibAttr' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.

Observations:

  • Happens for ActiveDs (11 warnings) and MSXML2 (54 warnings).
  • Not seen for our own COM objects.
  • <Reference> entry in .csproj file contains attribute WrapperTool = "tlbimp"
  • Despite of all warnings, no problems have been observed in the running system.

Any idea how to get rid of the warnings?

A: 

You can stop the warnings with:

    #pragma warning disable warning-list
    #pragma warning restore warning-list

where warning list is a comma seperated list of warning numbers.

The warning means that the typelib you are importing contains something untranslatable into managed code but could be dealt with using pointer operations, in an unsafe code block. The code was untranslatable in .Net 1.1 as well, but the compiler wasn't smart enough to warn you about the trap you might walk into if you use one of the methods it's warning you about.

Joe Caffeine
Disabling the warnings via #pragma does not work because the warning message contains no warning number!The warning is not created by the compiler. Probably it's created by TlbImp.
gyrolf
+2  A: 

According to a comment in the MDSN article about TLBIMP for 2.0, you can't fix this problem w/o running TLBIMP yourself.

It was easy to reproduce your problem using VS. I also reproduced it running TLBIMP manually from a VS comment prompt:

   tlbimp c:\WINNT\system32\activeds.tlb /out:interop.activeds.dll

The fix was to use the /silent switch

   tlbimp c:\WINNT\system32\activeds.tlb /silent /out:interop.activeds.dll

As pointed out in the comment in the MSDN article, the COM reference becomes a .net assembly reference to the interop assembly you built yourself.

I'm not a VS expert, but I made this work by adding a prebuild to project of:

    "$(DevEnvDir)\..\..\SDK\v2.0\bin\tlbimp" c:\WINNT\system32\activeds.tlb
            /namespace:ActiveDs /silent /out:"$(ProjectDir)interop.activeds.dll"

Built it once so I'd have a dll to add a reference with the browse tab. Added a reference to the interop.activeds.dll in my project root and then built again. You may want to do this some other way, like with an external make file via a C++ project. This is more of a POC.

Note a funny difference in MSBUILD vs VS, $(DevEnvDir) has a trailing backslash but MSBUILD does not.

Tony Lee