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>
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>