2014-02-03 3 views
2

У меня возникла проблема при компиляции управляемого DLL-проекта. Решение состоит из двух проектов: первая - это .NET DLL, написанная на C#, а другая - управляемая C++ DLL, которая напрямую ссылается на проект C#.null PublicKeyToken для сборки x86

Оба проекта/библиотеки DLL сильно названы файлом snk на диске. C# dll имеет целевую структуру "AnyCPU", а проект Manage C++ скомпилирован дважды, один для целевой x86, а другой для x64.

Моя проблема заключается в том, что когда я компилирую проект Managed C++ для таргетинга на платформу x86, DLL результатов имеет PublicKeyToken = null, как сообщается ILSpy. При компиляции для целевой платформы x64 в DLL есть правильный PublicKeyToken. Я проверил свойства проекта, файл snk правильно ссылается для обеих целевых платформ под Configuration Properties -> Linker->Advanced->Key File без фиксации задержки; опция Target Machine также установлена ​​правильно на основе желаемой цели компиляции.

Вот информация, показанная ILSpy при загрузке моей DLL.

Для x64 DLL:

// MyDll.x64, Version=1.1.1000.1, Culture=neutral, PublicKeyToken=XXXXXXXXX 

// Architecture: x64 
// This assembly contains unmanaged code. 
// Runtime: .NET 2.0 

Для x86 DLL:

// MyDll.x86, Version=1.1.1000.1, Culture=neutral, PublicKeyToken=null 

// Architecture: AnyCPU (64-bit preferred) 
// This assembly contains unmanaged code. 
// Runtime: .NET 2.0 

Что касается меня, это описание архитектуры для сборки x86: AnyCPU (64-bit preferred)

Я не знаю, почему его использование конфигурации AnyCPU и то, что означает 64-битная предпочтительная аннотация?

Я также хотел бы упомянуть, что мой проект построен против .NET Framwork 2.0 для проекта C#, а проект Managed C++ построен против набора инструментов V90 Platform Toolset. Я использую Visual Studio 2010, работающую на 64-разрядной машине Windows 7.

Может кто-нибудь сказать мне, почему это происходит и как я могу решить эту проблему?

+0

Попробуйте включить ведение журнала MSBuild, а затем вы можете узнать об этом. –

ответ

2

Это просто следствие того, как заголовок COR в сборке может указывать на желательность архитектуры процессора. Вы можете увидеть объявления в файле заголовка CorHdr.h SDK, вы найдете его в своем каталоге Windows SDK на вашем компьютере. Вы можете использовать утилиту CorFlags.exe для отображения значений.

только Доступный флаг COMIMAGE_FLAGS_32BITREQUIRED. Когда установлено, оно указывает CLR, что вы хотите запустить программу в 32-битном режиме, даже в 64-разрядной операционной системе. Дополнительный флаг добавлен в .NET 4.5, COMIMAGE_FLAGS_32BITPREFERRED, он устраняет двусмысленность в ядрах ARM. Слишком много сборок, где 32BITREQUIRED на самом деле означает «x86 требуется» вместо «требуется 32-бит».

Таким образом, нет ничего похожего на флаг «64 бит», сборка может указывать только «32-бит» или «не имеет значения». С джиттером, обеспечивающим «неважно» клей, он генерирует зависимый от архитектуры машинный код во время выполнения. Поскольку параметр 32BITREQUIRED не включен в вашей сборке, дизассемблер не может отображать ничего, кроме AnyCPU.

Следующая информация - это поле IMAGE_FILE_HEADER.Machine в заголовке PE исполняемого файла, оно указывает, на какой машине может работать исполняемый файл. Это слабый сигнал для сборщиков .NET, поскольку они обычно не содержат исполняемого кода, а просто MSIL. И он легко игнорируется загрузчиком Windows. В сборках .NET обычно установлено это поле IMAGE_FILE_MACHINE_I386 для указания x86.Вы по-прежнему получаете 64-битный процесс из такой сборки EXE, некоторые довольно героические структуры структуры загрузчика возникают, когда такой EXE загружается. Работа mscoree.dll, «прокладка погрузчика». Подробнее об этом в this post.

Поскольку вы нацелились на x64 в своем проекте C++/CLI, IMAGE_FILE_HEADER.Machine был установлен IMAGE_FILE_MACHINE_AMD64 компоновщиком. Дисассемблер увидел это, создав таким образом «64-битную предпочтительную» аннотацию.

Не обманывайтесь словом «предпочтительный» здесь. Дисассемблер выглядел недостаточно глубоко, чтобы увидеть, что ваша сборка содержит машинный код, созданный компилятором C++/CLI. Им не нравится, нет никакого дизассемблера, который декомпилирует машинный код обратно в исходный код C++/CLI. Сборка никогда не будет запускаться в 32-разрядной операционной системе. Kaboom на 32-битной ОС, программа выходит из строя с ошибкой 11, ERROR_BAD_FORMAT, «Была сделана попытка загрузить программу с неправильным форматом».

Это отвечает на ваш вопрос, это не имеет ничего общего с сильным именем.

+0

Спасибо за подробный ответ, однако это касается только моей озабоченности по поводу (64-битной предпочтительной) аннотации. Моя фактическая проблема связана с 'PublicKeyToken = null', так как я полагаюсь на нее, чтобы загрузить сборку из моего клиентского приложения. –

+0

Да, я был счастлив, что вы на самом деле не задали этот вопрос. Конечно, я понятия не имею, вы не описали * точные * шаги, которые вы предприняли, чтобы подписать сборку, поэтому я не могу сказать, где это произошло. Знать, где * не * искать проблему, составляет 50% битвы. Продолжайте пытаться. –

Смежные вопросы