如果删除未使用的引用 class,则 DLL 无法加载
DLL fails to load if unused ref class is removed
我 运行 遇到了一个非常奇怪的问题,试图在 UWP 应用程序中编译和使用 windows 运行时组件(VS2017 社区 15.9.13 和 NetCore.UniversalWindowsPlatform 6.2.8 , 编译时没有 /clr 但有 /ZW).
它基本上类似于 Grayscaletransform。运行时组件实际上按预期工作,现在我想删除一些未使用的代码。但是,一旦我将它从特定文件中删除并重新编译,它确实可以编译、链接,但 DLL 不再加载。
这是我必须放入的一些示例代码:
ref class DummyU sealed
{
public:
DummyU() {}
};
DummyU^ CreateDummyU()
{
return ref new DummyU();
}
代码只是让它工作,尽管它 a) 根本没有被引用并且 b) 没有做任何有用的事情。
删除结果:
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
。
如果没有明确实例化 ref class,是否有人知道是否存在关于 windows 运行时未正确 initialized/used 的任何已知错误文件?
编辑 1:
这里是 link 完整的源代码:
您的组件的 .winmd 文件可能有误。用 C++ 制作的 WinRT 组件产生两个输出,dll 和 winmd。两者必须匹配。您可能从不同的版本中获得它们。
另一个可能的原因是清单错误。应用的清单 must include 所有引用的运行时组件。
顺便说一句,对于用经典 C++ 编写并公开 C API 的本机 DLL,部署更简单,您在包中包含一个 DLL,它们就可以工作,如果您正在使用 [DllImport]
他们来自 C#。
更新: 您可以用以下代码替换 ref class
,在我的电脑上有效。
struct ModuleStaticInitialize
{
ModuleStaticInitialize()
{
Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
}
};
static ModuleStaticInitialize s_moduleInit;
可能是 Microsoft 运行时某处的错误。
这里发生的是你有点混合模式。由于您已使用 /CX 标志编译 C++ 代码,因此您已告知编译器启用 winrt 扩展以生成 WinRT DLL。但实际上,您的代码 none 实际上是使用 CX 扩展来实现 类。您正在使用 WRL 和标准 C++。编译器查看 DLL,未找到 CX-style WinRT 类,因此不会设置模块。
这基本上是一个未经测试和不受支持的案例,因为您选择说要通过选择 UWP 组件库项目类型来公开 ref 类,但实际上并没有提供任何 ref 类。碰巧在引擎盖下,/CX 有效地使用了 WRL,因此您可以推动它并初始化状态以使其正常工作,但您有点破解了系统的实现细节。
我会推荐两个选项,两者都有效:只需将项目设为 non-CX Win32 DLL 并如上所述初始化模块。或者,更好的是,转到 C++ /WinRT,这将为你提供比 /CX 更好的 WinRT 类型支持,并允许你更轻松地在你的实现中混合经典 COM 类型。您只需关闭编译器开关中的 /CX 标志即可开始,然后相应地开始更新代码。
本
我 运行 遇到了一个非常奇怪的问题,试图在 UWP 应用程序中编译和使用 windows 运行时组件(VS2017 社区 15.9.13 和 NetCore.UniversalWindowsPlatform 6.2.8 , 编译时没有 /clr 但有 /ZW).
它基本上类似于 Grayscaletransform。运行时组件实际上按预期工作,现在我想删除一些未使用的代码。但是,一旦我将它从特定文件中删除并重新编译,它确实可以编译、链接,但 DLL 不再加载。
这是我必须放入的一些示例代码:
ref class DummyU sealed
{
public:
DummyU() {}
};
DummyU^ CreateDummyU()
{
return ref new DummyU();
}
代码只是让它工作,尽管它 a) 根本没有被引用并且 b) 没有做任何有用的事情。
删除结果:
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
。
如果没有明确实例化 ref class,是否有人知道是否存在关于 windows 运行时未正确 initialized/used 的任何已知错误文件?
编辑 1:
这里是 link 完整的源代码:
您的组件的 .winmd 文件可能有误。用 C++ 制作的 WinRT 组件产生两个输出,dll 和 winmd。两者必须匹配。您可能从不同的版本中获得它们。
另一个可能的原因是清单错误。应用的清单 must include 所有引用的运行时组件。
顺便说一句,对于用经典 C++ 编写并公开 C API 的本机 DLL,部署更简单,您在包中包含一个 DLL,它们就可以工作,如果您正在使用 [DllImport]
他们来自 C#。
更新: 您可以用以下代码替换 ref class
,在我的电脑上有效。
struct ModuleStaticInitialize
{
ModuleStaticInitialize()
{
Microsoft::WRL::Module<Microsoft::WRL::InProc>::GetModule();
}
};
static ModuleStaticInitialize s_moduleInit;
可能是 Microsoft 运行时某处的错误。
这里发生的是你有点混合模式。由于您已使用 /CX 标志编译 C++ 代码,因此您已告知编译器启用 winrt 扩展以生成 WinRT DLL。但实际上,您的代码 none 实际上是使用 CX 扩展来实现 类。您正在使用 WRL 和标准 C++。编译器查看 DLL,未找到 CX-style WinRT 类,因此不会设置模块。
这基本上是一个未经测试和不受支持的案例,因为您选择说要通过选择 UWP 组件库项目类型来公开 ref 类,但实际上并没有提供任何 ref 类。碰巧在引擎盖下,/CX 有效地使用了 WRL,因此您可以推动它并初始化状态以使其正常工作,但您有点破解了系统的实现细节。
我会推荐两个选项,两者都有效:只需将项目设为 non-CX Win32 DLL 并如上所述初始化模块。或者,更好的是,转到 C++ /WinRT,这将为你提供比 /CX 更好的 WinRT 类型支持,并允许你更轻松地在你的实现中混合经典 COM 类型。您只需关闭编译器开关中的 /CX 标志即可开始,然后相应地开始更新代码。
本