DLL не загружается, если удален неиспользуемый класс ref - PullRequest
1 голос
/ 02 июля 2019

Я сталкиваюсь с очень странной проблемой, пытаясь скомпилировать и использовать компонент среды выполнения Windows в приложении UWP (сообщество VS2017 15.9.13 с NetCore.UniversalWindowsPlatform 6.2.8, скомпилированное без / clr, но с /ZW).

Это в основном что-то вроде Оттенки серого . Компонент времени выполнения фактически работает, как и ожидалось, теперь я хотел удалить неиспользуемый код. Однако, как только я удаляю его из определенного файла и перекомпилирую, он действительно компилирует ссылки, но DLL больше не загружается.

Вот пример кода, который я должен вставить:

ref class DummyU sealed
{
public:
    DummyU() {}
};

DummyU^ CreateDummyU()
{
    return ref new DummyU();
}

Код только заставляет его работать, хотя на него а) вообще не ссылаются и б) ничего полезного не делает.

Результат удаления:

Exception thrown at 0x0EFF322F (vccorlib140d_app.dll) in TestAppUWP.exe: 0xC0000005: Access violation reading location 0x00000000.

в

STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _Deref_out_ IActivationFactory** ppFactory)
{
    return Platform::Details::GetActivationFactory(Microsoft::WRL::Details::ModuleBase::module_, activatibleClassId, ppFactory);
}

функция в dllexports.cpp, которая является частью VS. module_ становится NULL.

У кого-нибудь есть идея, если есть какие-либо известные ошибки, связанные с тем, что среда выполнения Windows не инициализируется / не используется должным образом, если в файле нет явного создания экземпляра класса ref?

РЕДАКТИРОВАТЬ 1:

Вот ссылка на полный исходный код:

Ответы [ 2 ]

1 голос
/ 03 июля 2019

Здесь происходит то, что вы немного смешиваете режимы.Поскольку вы скомпилировали свой код C ++ с флагом / CX, вы сказали компилятору включить расширения winrt для создания библиотеки WinRT DLL.На практике, однако, ни один из вашего кода на самом деле не использует расширения CX для реализации классов.Вы используете WRL и стандарты C ++.Компилятор просматривает библиотеку DLL, не находит классов WinRT в стиле CX и, соответственно, не устанавливает модуль.

Это в основном непроверенный и неподдерживаемый случай, поскольку вы решили сказать, что хотите предоставить классы ref, выбрав тип проекта библиотеки компонентов UWP, но затем фактически не предоставили никаких классов ref.Бывает, что под капотом / CX эффективно использует WRL, поэтому вы можете подтолкнуть его и инициализировать состояние для правильной работы, но вы вроде как взламываете детали реализации системы.

Есть два вариантаЯ бы порекомендовал, либо работает: просто сделайте проект не-CX Win32 DLL и запустите модуль, как описано выше.Или, что еще лучше, переключитесь на C ++ / WinRT , который обеспечит вам лучшую поддержку типов WinRT, чем / CX, и позволит вам более легко смешивать классические типы COM в вашей реализации.Вы можете начать, просто отключив флаг / CX в переключателях компилятора, а затем начните соответственно обновлять код.

Ben

1 голос
/ 02 июля 2019

Возможно, у вас неправильный файл .winmd для вашего компонента.Компоненты WinRT, сделанные в C ++, выдают два вывода: dll и winmd.Оба должны совпадать.Возможно, они у вас из разных сборок.

Другая возможная причина - ошибка в манифесте.Манифест приложения должен включать в себя все упомянутые компоненты среды выполнения.

Кстати, для собственных DLL, написанных на классическом C ++ и предоставляющих C API, развертывание проще, вы включаете DLL в пакет иони просто работают, с [DllImport], если вы используете их из C #.

Обновление: Вы можете заменить ref class на следующий код, который работает на моем ПК.

struct ModuleStaticInitialize
{
    ModuleStaticInitialize()
    {
        Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
    }
};
static ModuleStaticInitialize s_moduleInit;

Возможно, ошибка где-то во время выполнения Microsoft.

...