Как отложить загрузку .dll в приложении C ++ - CLI (.net)? - PullRequest
5 голосов
/ 21 января 2011

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

Я попытался добавитьуказывает на MyProject-> Properties-> ConfigurationProperties-> Linker-> Input-> Delay Loaded DLLS ... но это просто дает мне предупреждение, что он не ссылается на них:

5> LINK: warningLNK4199: /DELAYLOAD:Util.dll игнорируется;импорт не найден из Util.dll

Если я удаляю .dll и запускаю приложение, оно вылетает и хочет отправить в Microsoft информацию об отсутствующем .dll, так что похоже, что он все еще пытается загрузить всемодули при запуске и в результате имеют подгонку.

К вашему сведению, мой запуск приложения выглядит примерно так:

using namespace System;
using namespace System::Collections::ObjectModel;
using namespace Microsoft::Win32;

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    try
    {
        // Enabling Windows XP visual effects before any controls are created
        Application::EnableVisualStyles();
        Application::SetCompatibleTextRenderingDefault(false); 

        // First make sure we have all the .dlls we need
        ArrayList^ missingDlls = gcnew ArrayList();
        Assembly^ assembly = Assembly::GetEntryAssembly();
        array<System::Reflection::AssemblyName^>^ referencedAssemblies = assembly->GetReferencedAssemblies();
        for each(System::Reflection::AssemblyName^ referencedAssemblyName in referencedAssemblies)
        {
            try
            {
                Assembly^ a = assembly->Load(referencedAssemblyName);
                if( a == nullptr )
                {
                    missingDlls->Add(referencedAssemblyName->Name);
                }
            }
            catch(System::Exception^ e)
            {
                MessageBox::Show("Error loading "+referencedAssemblyName->Name);
            }
        }

        ...

1 Ответ

8 голосов
/ 21 января 2011

Опция компоновщика / delayload работает только для библиотек DLL, которые содержат функции, скомпилированные с собственным машинным кодом. Линкер уже сказал вам, что у вас его нет.

Вероятный сценарий здесь состоит в том, что ваша DLL фактически содержит IL, а не машинный код. Это произойдет, когда вы скомпилируете исходный код с использованием / clr и не используете #pragma, чтобы отключить генерацию IL. Код IL должен быть преобразован в машинный код с помощью джиттера.

Ваша DLL будет загружаться динамически, так же, как / delayload, как только джиттеру потребуется информация о типе из метаданных сборки для генерации машинного кода. Чтобы избежать зависимости от DLL, вы должны тщательно обработать свой код, чтобы джиттеру никогда не приходилось загружать типы из вашей сборки. Это отличная проблема от выполнения загруженной с задержкой функции. Трассировка стека исключения InnerException должна дать вам четкий совет, как это произошло.

...