2009-03-15 3 views
7

Я получаю System.IO.FileNotFoundException: The specified module could not be found при запуске C# код, который вызывает сборку C++/CLI, который в свою очередь, вызывает чистый C DLL. Это происходит, как только создается экземпляр объекта, который вызывает функции чистого C DLL.C# для C++/CLI для C DLL System.IO.FileNotFoundException

BackingStore is pure C. CPPDemoViewModel - это C++/CLI, вызывающий BackingStore, он имеет ссылку на BackingStore.

Я пробовал самый простой случай - добавьте новый тестовый проект на C#, который просто пытается создать объект, определенный в CPPDemoViewModel. Я добавил ссылку из проекта C# в CPPDemoViewModel.

Проект тестирования на C++/CLI отлично работает с добавленным ref в CPPDemoViewModel, поэтому это что-то вроде перехода между языками.

Я использую Visual Studio 2008 SP1 с .Net 3.5 SP1. Я основываюсь на Vista x64, но старался убедиться, что для моей платформы задано значение x86.

Это похоже на что-то глупое и очевидное, что мне не хватает, но мне было бы еще глупее тратить время на то, чтобы решить это наедине, так что я здесь смущаю себя!

Это тест для проекта, переносящего огромное количество унаследованного кода C, который я храню в DLL, с ViewModel, реализованным в C++/CLI.

Редактировать После проверки каталогов я могу подтвердить, что BackingStore.dll не был скопирован.

У меня есть стандартные уникальные папки проектов, созданные с типичным многопроектным решением.

 
WPFViewModelInCPP 
    BackingStore 
    CPPViewModel 
    CPPViewModelTestInCS 
    bin 
     Debug 
    Debug 

Чем выше уровень отладки, как представляется, общая папка используется проектами C и C++/CLI, к моему удивлению.

WPFViewModelInCPP \ Debug содержит BackingStore.dll, CPPDemoViewModel.dll, CPPViewModelTest.dll и их ассоциированных .ilk и .pdb файлы

WPFViewModelInCPP \ CPPViewModelTestInCS \ Bin \ Debug содержит CPPDemoViewModel и CPPViewModelTestInCS .dll и PDB-файлы, но не BackingStore. Однако вручную копирование BackingStore в этот каталог не исправило ошибку.

CPPDemoViewModel имеет свойство Copy Local набор, который я предполагаю, отвечает за копирование его DLL, когда, если есть ссылка. Я не могу добавить ссылку из проекта C# в чистую C DLL - он просто говорит Ссылка на хранилище не может быть добавлена.

Я не уверен, что у меня есть только одна проблема.

Я могу использовать старомодный шаг копирования, чтобы скопировать файл BackingStore.dll в любые каталоги проекта C#, хотя я надеялся, что новая модель .net этого не потребует.

DependencyWalker сообщает мне, что отсутствующим файлом является файл GPSVC.dll, который has been suggested указывает на проблемы с настройкой безопасности. Я подозреваю, что это красная селедка.

edit2 С ручной копии BackingStore.dll быть рядом с исполняемым файлом, графический интерфейс теперь работает отлично. У тестируемого проекта C# все еще есть проблемы, которые, как я подозреваю, обусловлены средой выполнения тестового проекта, но я могу жить без этого на данный момент.

ответ

4

Ответ для графического интерфейса пользователя, кроме изменения параметров вывода, было добавление предварительной сборки Шаг

copy $(ProjectDir)..\Debug\BackingStore.* $(TargetDir) 

Ответ на тестовых проектов, чтобы добавить недостающие DLL на вкладку Развертывание testrunconfig. Вы можете сделать это, непосредственно отредактировав по умолчанию LocalTestRun.testrunconfig (отображается в разделе Решение в разделе «Решения») или щелкните правой кнопкой мыши «Решение» и добавьте новую конфигурацию тестового прогона, которая затем появится в главном меню «Тест».

Спасибо за ответы на this SO question на тестовых конфигурациях, чтобы привести меня к ответу.

+0

Да, я знаю, что дерзко отметить свой собственный ответ, но никто не приблизился к реальному ответу на те тесты, на которые ушел хороший час рытья. Я все еще ошеломлен, мне нужно использовать такую ​​старомодную технику для копирования DLL! –

+0

Энди, вы все равно должны проверить, что я поднял точку, у меня такое ощущение, что вам повезло с порядком/временем инициализации, и в будущем вам может не повезти без твердой хватки на этом. – RandomNickName42

11

Являются ли библиотеки C и C++ в том же каталоге, что и сборка C#?

Возможно, вам придется изменить настройки вывода проекта, чтобы сборка C# и другие DLL-файлы попадали в одну и ту же папку.

Я часто использовал Dependency Walker в таких случаях; это проверка работоспособности, которая показывает, что все зависимости действительно могут быть найдены.

Как только приложение будет запущено, вы также можете попробовать Process Monitor на код, в котором вы работаете, чтобы увидеть, какие DLL ссылки и где они находятся.

+0

+1 для зависимостей Walker; отличный инструмент – Randolpho

+0

Я не думал использовать старый добрый файл depend.exe .Net (я старая школьная Win32/MFC и другой парень на C++). Хорошая точка зрения. Он подтвердил недостающую DLL. –

+0

@ Энди: Хорошо, это хорошо;] Depends.exe ftw! –

1

Это интересная дилемма. Я никогда не слышал о проблеме загрузки native .DLLs из C++/CLI после вызова из него с C# раньше. Я могу только предположить, что проблема заключается в том, что @Daniel L предложил, и что ваш .DLL просто не находится в пути, который может найти загрузчик сборок.

Если предложение Daniel не работает, я предлагаю вам попробовать статически связать собственный C-код с программой C++/CLI, если сможете. Это, безусловно, решит проблему, так как .DLL будет полностью поглощен C++/CLI .DLL.

+0

статическая ссылка - хорошая идея, но это невозможно - код должен оставаться в чистой C DLL по соображениям безопасности и потому, что это древний K & R C, который нельзя преобразовать в ANSI (неприятные математические функции) –

+0

А, ну. Хорошо, что Даниэль был прав, а? – Randolpho

1

Убедитесь, что целевая система имеет правильную рабочую среду MS Visual C и что вы случайно не создаете C dll с отладочной средой выполнения.

+0

+1 хорошая точка, материал отладки CRT получил меня раньше ... –

+0

Является ли это утверждение, что родная C++ DLL не должна быть построена с целью отладки? В чем именно «я уверен»? У меня очень похожая ситуация (C#, вызывающий C++/CLI DLL, вызывающий родную C++ DLL, чтобы включить устаревший код), и я хотел бы избежать того, что здесь идентифицируется ловушка. –

+0

@richp: IIRC, зависимость находится на msvcrtd.dll. Depends.exe должен подтвердить. – leppie

4

Причина, по которой это происходит, заключается в том, что вы либо загружаете DLLMAIN из управляемого кода, прежде чем CRT имеет возможность инициализации. У вас может не быть управляемого кода, который должен быть выполнен DIRECTLY или INDERECTLY из-за эффекта уведомлений DllMain. (См.: Expert C++/CLI: .Net для программистов на Visual C++, глава 11 ++).

Или у вас нет родной точки входа, определенной wahtsoever, но вы связаны с MSVCRT. CLR автоматически инициализируется для вас с/clr, эта деталь вызывает много путаницы и должна быть принята во внимание. DLL с смешанным режимом на самом деле задерживает нагрузку CLR с помощью горячего исправления всех управляемых точек входа vtables в ваших классах.

Ряд вопросов инициализации класса окружают эту тему, блокировка загрузчика и задержка загрузки CLR иногда немного сложны. Попробуйте объявить статику global и не использовать #pragma управляемый/неуправляемый, изолируйте свой код с/clr для каждого файла.

Если вы не можете изолировать свой код от управляемого кода и возникают проблемы (после принятия некоторых из этих шагов), вы также можете посмотреть на размещение CLR самостоятельно и, возможно, выполнить усилия по созданию менеджера домена , что обеспечит ваш «полный цикл» событий во время выполнения и загрузку.

Это точно, почему у него нет todo с вашим путем поиска или инициализацией. К сожалению, средство просмотра журнала Fusion не очень помогает (это обычное место для поиска проблем привязки .NET CLR, не связанных с ходом зависимостей).

Связывание статически не имеет ничего общего с этим. Вы можете NOT статически связывать приложение C++/CLI, смешанное.

  1. Поместите функцию DLLMAIN в файл самостоятельно.
  2. Убедитесь, что этот файл делает НЕ имеют /CLR набор в параметрах сборки (файл вариантов сборки)
  3. Убедитесь, что ваша связь с/MD или/MDD, и все ваши зависимостей, которые вы связываете использование точно такой же CRT.
  4. Оцените настройки вашего компоновщика для/DEFAULTLIB и/INCLUDE, чтобы определить возможные возможные проблемы с ссылкой, вы можете объявить прототип в своем коде и использовать/INCLUDE для переопределения разрешения библиотеки по умолчанию.

Удачи, также проверьте, что книга очень хорошая.

+0

спасибо за поднятие этих проблем - они были восприняты всерьез и добавлены к нашим задачам для анализа кода –

+0

Пункт 2 об отсутствии настроек/CLR помог мне. Благодарю. – Patel

0

Если бы такая же проблема перешла на 64-разрядную Vista. Наше приложение вызывало библиотеки DLL Win32, которые сбивали с толку целевую сборку для приложения. Для его решения мы сделали следующее:

  1. Перейти к объекту проекта;
  2. Выберите вкладку «Сборка»;
  3. Изменить параметр «Платформа цели:» на x86;
  4. Восстановить приложение.

Когда я перезапустил приложение, он сработал.

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