Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This should be easy, right? Just set the link options to delay sign the assembly with an SNK file. There were two issues I ran into, which I’ll describe here.
Fixing Delay Signing in SP1
I used the /DELAYSIGN and /KEYFILE settings in the properties page for my C++/CLI project and everything compiled just fine. However, when I tried to use an object from this DLL, I got this message::
CS1577: Assembly generation failed … does not have a strong name
This certainly wasn’t what I expected. My first step was to double-check the signing on the assembly. I used the following command-line command to check:
sn -T AssemblyName.dll
When I ran this command, it reported “AssemblyName.dll does not represent a strongly named assembly". Obviously the properties I set in the project settings dialog weren’t working. After quite a bit of searching, I found a blog post by Amit Mohindra that explained the problem, which is a change in Visual Studio 2010 SP1.
The blog post had suggestions on how to fix the problem, but it seemed like quite a bit of work. I tried another approach, which worked just fine.
Signing via AssemblyInfo.cpp
I added an new file called AssemblyInfo.cpp to my project, which has the following contents:
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
[assembly:AssemblyKeyFile("myKey.snk")];
[assembly:AssemblyDelaySign(true)];
This took care of signing the assembly, which I verified using the sn command.
Dealing with C++/CLI vs C# Assemblies
One this was all working, we added a call from our C# EXE into the C++/CLI assembly, and got this run-time error:
Could not load file or assembly 'AssemblyName, Version=0.0.0.0, Culture=neutral, PublicKeyToken=…' or one of its dependencies. An attempt was made to load a program with an incorrect format.
Incorrect format? Huh?
With a little more searching, I found the problem, and now that I understand the problem, it makes perfect sense. First, the solution. You need to change the Platform from Any CPU to x86 for you main EXE (or x64 if you’re building a 64-bit version) to match the bitness of your C++/CLI assembly:
Here’s why we had to make this change. Our C++/CLI assembly is calling not a pure .NET assembly since it’s making calls to windows APIs. As such, the C++/CLI assembly needs to be either 32- or 64-bit. It can’t be both because of the native C++ code it contains. A .NET assembly that is built for Any CPU can run as either a 32- or 64-bit process, but you can’t load a 32-bit DLL into a 64-bit process, hence the error. Building a 32-bit .NET EXE that loads the 32-bit C++/CLI DLL fixes the problem.
Comments
- Anonymous
March 03, 2015
How did you resolve the System and System::Reflection references? I keep getting the error "Must be a namespace name".
