3

I have a VS2012 solution with a C++/CLI Class Library project targeting .NET 3.5 and using the the Windows7.1SDK as Platform Toolset, which according to MSDN is the correct way to target previous versions of the framework without installing the corresponding version of the toolset (i.e. Visual Studio 2008):

You can use the Windows7.1SDK platform toolset to target the .NET Framework 2.0, 3.0, 3.5, and 4, and the x86, Itanium, and x64 platforms.

The CLI/C++ project has Common Language Runtime Support (/clr) enabled.

I would like to use a class declared in the C++ project in C#, so I create a C# project targeting .NET 3.5 and add a reference to the CLI project. However, when building the C# that uses the type declared in the C++ project, I get: The type or namespace name 'Class1' could not be found (are you missing a using directive or an assembly reference?)

The strange thing is that the IDE does seem to be able to find the type (green color) and IntelliSense shows the methods available for the type.

Solution Structure

Solution Test1
|
| ClassLibrary1 (C++)
|    Class1.h
|    Class1.cpp
|
| Test1 (C#)
|    TestClass1.cs

ClassLibrary1.h

public ref class Class1
{
public:
    Class1(unsigned short int initValue);
    ~Class1(void);

    void Init(unsigned short int init);
    void Input(unsigned char data);
    unsigned short int Getalue(void);

private:
    unsigned short int _value;
};

TestClass1.cs

static void Main(string[] args)
{
    var t = new Class1(0xFFFF); //also tried with global::Class1, no cigar
}

Even more strangely, VS identifies the reference to the C++/CLI project as targeting v4.0.30319.

It also gives warnings like

Warning 5 The primary reference "D:\Test1\Debug\ClassLibrary1.dll" could not be resolved because it has an indirect dependency on the .NET Framework assembly "System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" which has a higher version "4.0.0.0" than the version "2.0.0.0" in the current target framework. Test1

I can't figure out where it's getting the idea that this has anything to do with .NET 4. I found ClassLibrary1.dll.metagen in the Debug folder, which is the only place I can think of it would be getting these references to v4 of the assemblies:

ImageRuntimeVersion: v4.0.30319
Assembly ClassLibrary1, Version=1.0.*, Culture=Invariant Language (Invariant Country): 
    hash=SHA1, flags=PublicKey
Assembly mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089: 
    hash=None, flags=None
Assembly System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089: 
    hash=None, flags=None
Assembly System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089: 
    hash=None, flags=None
Assembly System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089: 
    hash=None, flags=None
Assembly Microsoft.VisualC, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a: 
    hash=None, flags=None
Assembly mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089: 
    hash=None, flags=None
Assembly System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089: 
    hash=None, flags=None
Assembly Microsoft.VisualC, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a: 
    hash=None, flags=None
Class Class1: AutoLayout, AnsiClass, Class, Public, BeforeFieldInit
    Void .ctor(UInt16): PrivateScope, Public, HideBySig, SpecialName, RTSpecialName
  Interfaces:
    System.IDisposable
  Methods:
    Init(UInt16): PrivateScope, Public, HideBySig
    Input(Byte): PrivateScope, Public, HideBySig
    GetValue(): PrivateScope, Public, HideBySig
    Dispose(): PrivateScope, Public, Final, Virtual, HideBySig

I've tried editing the file with no success. I've also tried switching the toolset to Visual Studio 2012 (v110) in the C++ project without success. Any help would be appreciated.

It seems like someone already had the exact same issue over on the VS Forums site, but eventually gave up trying to resolve it.

Related questions:

How to build with v90 platform toolset in VS2012 without VS2008, using Windows SDK?

ClassLibrary1.vcxproj

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{B2C66274-DF38-473F-B759-C7E2E7A1E8A3}</ProjectGuid>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <Keyword>ManagedCProj</Keyword>
    <RootNamespace>ClassLibrary1</RootNamespace>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>Windows7.1SDK</PlatformToolset>
    <CLRSupport>true</CLRSupport>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>Windows7.1SDK</PlatformToolset>
    <CLRSupport>true</CLRSupport>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PrecompiledHeader>Use</PrecompiledHeader>
    </ClCompile>
    <Link>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <AdditionalDependencies />
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <PrecompiledHeader>Use</PrecompiledHeader>
    </ClCompile>
    <Link>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <AdditionalDependencies />
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClInclude Include="Class1.h" />
    <ClInclude Include="resource.h" />
    <ClInclude Include="Stdafx.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="AssemblyInfo.cpp" />
    <ClCompile Include="Class1.cpp" />
    <ClCompile Include="Stdafx.cpp">
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="app.rc" />
  </ItemGroup>
  <ItemGroup>
    <Image Include="app.ico" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

Test1.csproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{160BE075-BAF3-48CE-8CB3-E607D5F91A50}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Test1</RootNamespace>
    <AssemblyName>Test1</AssemblyName>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="TestClass1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.vcxproj">
      <Project>{b2c66274-df38-473f-b759-c7e2e7a1e8a3}</Project>
      <Name>ClassLibrary1</Name>
    </ProjectReference>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>
Community
  • 1
  • 1
user5877732
  • 371
  • 3
  • 19
  • Actually your C++/CLI project is not targeting 3.5 but 4.0. Follow this [article on MSDN](https://msdn.microsoft.com/en-us/library/ff770576.aspx) to change targeted framework version on C++/CLI projects. – Adriano Repetti May 17 '16 at 13:49
  • It is indeed targeting 3.5. I selected 3.5 in the Add New Project wizard and the line `v3.5` is already in the project file and the project's property pages read: Targeted framework: .NETFramework, Version=v3.5 – user5877732 May 17 '16 at 13:56
  • I don't know how you created that project but in Reference Properties (screenshot you included) you can read that Runtime Version is 4.0.30319 then IT IS targeting version 4.0. Also from other data you posted you should ALSO check its dependencies... – Adriano Repetti May 17 '16 at 14:07
  • Thanks for your response. I know it's strange; that's exactly why I prefaced the image with "Even more strangely" :) That's the reason I'm asking the question: there's clearly a version mismatch happening somewhere. In case it helps, the project was created by right-clicking the solution node in the Solution Explorer -> Add -> New Project, then selecting .NET Framework 3.5 on the dropdown & choosing Other Languages -> Visual C++ -> CLR -> Class Library as the project template. Not sure what your last sentence means. There are no other dependencies (even removing all but the CLI project fails) – user5877732 May 17 '16 at 14:15
  • I can't reproduce your issue here but I'd try to remove all dependencies from C++/CLI project then edit (manually) vcprojx to be sure it's targeting 3.5 (see linked article) and then reload it to readd dependencies. – Adriano Repetti May 17 '16 at 14:19
  • Already did. No change. – user5877732 May 17 '16 at 14:20
  • Can you post here your vcprojx file instead of .metagen? It shouldn't be too big. – Adriano Repetti May 17 '16 at 14:21
  • Thanks Adriano, I've included the project file contents in the question. – user5877732 May 17 '16 at 14:32
  • Can you check to what $(VcTargetPaths) resolves to? – Adriano Repetti May 17 '16 at 14:39
  • Thanks again! $(VCTargetsPath) has the value 'C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\' – user5877732 May 17 '16 at 14:47
  • You cannot target 3.5 if you have only VS2012. The runtime library support for a C++/CLI assembly targets .NET 4. This support hooks into AppDomain so the native CRT gets properly initialized when the assembly is loaded and your unmanaged code can work. You must have VS2008 and VS2010 installed on your machine so you can change the project's Platform target to use v9.0. If you don't have them installed then you can obtain them with an MSDN subscription. – Hans Passant May 17 '16 at 15:17
  • @HansPassant absolutely to the point, I didn't even noted _"...without installing the corresponding version..."_ – Adriano Repetti May 17 '16 at 15:22
  • @HansPassant O_o thanks for your response. I guess I have two questions in that case: 1) you mention unmanaged code. I was going for a *managed* dll. Does that make any difference? 2) I was under the impression that the W7.1SDK was precisely there to circumvent the need for the older toolset. If not, what's the effect of building with the v110 toolset in VS2012 and targeting 3.5? If it's just not possible at all to build for 3.5 with VS, is there a way to do it with MSBuild or TFS? I'm at a loss as to why MS would give the option to create a project in a way that is not supported/doesn't work – user5877732 May 18 '16 at 07:27
  • @HansPassant btw, feel free to write respond in an answer so that I can mark it accordingly – user5877732 May 18 '16 at 09:11

1 Answers1

2

So after finding the link to VS2010 Express in this answer (it's no longer available on the VS website) and installing it, I found that it's also not possible to build against 3.5 with VS2010; you need to have 2008 installed! This was an absolute nightmare, but the workaround in this answer finally allowed me to build on VS2012 targeting .NET 3.5.

<rant>Judging by how time-consuming it was to get this to work (and even then, with a workaround), one can only conclude there's clearly no money to be made by Microsoft if developers are not targeting the latest and greatest. Why you would tightly couple the tooling version with the framework is beyond me.</rant>

Community
  • 1
  • 1
user5877732
  • 371
  • 3
  • 19