Вопрос

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

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

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

Тестовый проект C++/CLI работает нормально, если добавить ссылку на 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

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

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

WPFViewModelInCPP\CPPViewModelTestInCS\bin\Debug содержит файлы CPPDemoViewModel и CPPViewModelTestInCS .dll и .pdb, но нет Резервное хранилище.Однако копирование BackingStore вручную в этот каталог не исправил ошибку.

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

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

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

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

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

Это было полезно?

Решение 2

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

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

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

Спасибо за ответы на это ТАК вопрос на тестовых конфигурациях, чтобы привести меня к ответу.

Другие советы

Находятся ли библиотеки DLL C и C++ в том же каталоге, что и исполняемая сборка C#?

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

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

После запуска приложения вы также можете попробовать Монитор процессов в коде, который вы выполняете, чтобы увидеть, на какие библиотеки DLL ссылаются и где они расположены.

Причина, по которой это происходит, заключается в том, что вы либо загружаете DLLMAIN из управляемого кода, прежде чем CRT получит возможность инициализироваться.У вас может не быть управляемого кода, он будет выполнен НАПРЯМУЮ или КОСВЕННО от эффекта уведомлений DllMain.(Видеть:Эксперт C++/CLI:.Net для программистов Visual C++, глава 11++).

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

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

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

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

Статическое связывание тоже не имеет к этому никакого отношения.Ты можешь НЕТ статически связать приложение C++/CLI в смешанном режиме.

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

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

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

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

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

Была такая же проблема при переходе на 64-битную Vista.Наше приложение вызывало библиотеки DLL Win32, что сбивало с толку целевую сборку приложения.Чтобы решить эту проблему, мы сделали следующее:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top