c++ - Visual Studio 2015无法产生在Windows XP上成功注册的ATL Dll

标签 c++ dll visual-studio-2015 atl

我有一个要移植到Win 10的旧项目。我们需要保持与Windows XP的兼容性,但我无法使转换后的项目甚至在XP下注册也没有成功。为了了解什么是必要的(在搜索了Stack Overflow和MSDN几周之后),我尝试使用VS 2015从头开始创建基于ATL的Dll,但它不起作用。在继续之前,让我先解决一些问题:

1)是的,我已经安装了启用了XP的C++支持的VS 2015。
2)是,我已将平台工具集设置为XP
3)是的,我已经在XP目标上安装了VS 2015 x86可再发行组件包

如果我只是通过ATL项目向导并在添加任何COM接口(interface)之前停止,那么Dll将在XP上成功注册。如果添加没有任何方法的接口(interface),则regsvr32失败,返回码为0xc0000005。如果我向接口(interface)添加方法并提供实现,则该方法将继续以相同的方式失败。

如果您能提供缺少的那一部分,我将不胜感激。我生成最小Dll的过程大约需要5分钟的时间,这是我的步骤(选择设置以最接近我要移植的Dll):

所需环境:

您将需要一个Win 10系统,其中安装了启用了XP支持的Visual Studio 2015(如果在安装时未选中XP C++支持选项,则将出现构建错误;这不是默认选项),并且

安装了VS 2015 x86可再发行组件的Windows XP系统(在此处可用:https://www.microsoft.com/en-us/download/details.aspx?id=48145)

打开VS 2015,选择文件/新建/新建项目…

•在对话框左侧的“已安装/模板/ Visual C++ / Windows树”中,选择“ATL”作为项目类型过滤器,
•从对话框中心的模板列表中选择“ATL项目”作为项目类型。
•从对话框顶部的下拉列表中选择“.NET Framework 3.5”作为.NET Framework。
•将项目命名为“DllHoopt​​y”,
•选择对话框右下方的“创建解决方案目录”选项。
•单击确定以启动项目向导。

当出现项目向导时,当前项目设置应为“动态链接库”。

•单击“下一步”,而不是“完成”

在“应用程序设置”页面上:

•选择“允许合并代理/存根代码”,
•取消选择“安全开发生命周期(SDL)检查”。
•取消选中“支持MFC”和“支持COM + 1.0”。
•单击“完成”以创建项目和解决方案。

创建项目/解决方案后:

•选择“发布”作为配置,选择“x86”作为平台。
•右键单击DllHoopt​​y项目,然后选择“属性”。
•在属性对话框中,确保配置和平台分别为“Release”和“Win32”
•如果尚未选择,请转到“配置属性/常规”面板
•将“平台工具集”更改为“Visual Studio 2015-Windows XP(v140_xp)”
•单击确定保存更改并关闭属性面板。

如果您在此处停止并构建解决方案,则生成的dll将成功注册。

右键单击DllHoopt​​y项目,然后从弹出菜单中选择“添加/类...”以弹出“添加类”对话框。
•从树中选择“已安装/ Visual C++ / ATL”,然后从模板列表中选择“ATL简单对象”
•单击“添加”以启动ATL简单对象向导。

•在“欢迎使用ATL简单对象向导”页面上,为对象指定Hoopt​​y的“短名称”。这将导致其他所有字段都被填写。
• 点击下一步”。
•单击“文件类型处理程序选项”页面上的“下一步”

在“选项”页面上:
•选择“单一”作为线程模型,
•选择“否”作为“汇总”选项,
•选择“自定义”作为“接口(interface)”选项。
•取消选中“自定义”下的“自动化兼容”框。
•应取消选中所有“支持”框。
•单击“完成”

在这一点及以后,生成的任何dll都将无法向消息“DllHoopt​​y.dll中的DllRegisterServer失败”进行注册。返回码为0xc0000005”

打开文件“DllHoopt​​y.idl”,
•添加“HRESULT Wub();”到“接口(interface)IHoopt​​y”,例如更改为:

interface IHoopty : IUnknown{
    HRESULT Wub();
};

打开“Hoopt​​y.h”
•添加:
 STDMETHOD(Wub)();

对公众:CHoopt​​y类声明末尾的部分

打开“Hoopt​​y.cpp”
•添加:
STDMETHODIMP CHoopty::Wub()
{
    return S_OK;
}

生成项目(确保Release / x86是所选的配置和平台)

•在安装了C++可再发行组件的Win XP计算机上,将“DllHoopt​​y.dll”移动到本地硬盘驱动器(如果像我一样,将虚拟机与VirtualBox一起使用,则不要共享文件夹)。

在XP机器上:
•弹出命令提示符,
•导航到DllHoopt​​y.dll的位置,
•运行“regsvr32 DllHoopt​​y.dll”。

如果我的猜测是正确的,您将看到一个错误对话框:

“DllHoopt​​y.dll中的DllRegisterServer失败。返回码为:0xc0000005”

我尝试了很多事情:为WINVER 0x0501,_WIN32_WINNT 0x0501,_ATL_XP_TARGETING添加定义,以及其他很多我忘记的定义。什么都不会改变结果。

最佳答案

  • 静态链接CRT-在“配置属性” /“C / C++” /“代码生成” /“运行时库”中,选择非DLL多线程选项,例如发行版本中的/MT
  • 在配置属性/ C / C++ /命令行/其他选项下的编译器选项中添加/Zc:threadSafeInit-(n.b。尾随的-是开关的一部分)。

  • 解决方法#2来自https://connect.microsoft.com/VisualStudio/feedback/details/1907257处的打开案例。

    Windows Server 2003 and Windows XP have problems with dynamically loading a DLL (via LoadLibrary) that uses thread-local storage, which is what thread-safe statics use internally to provide efficient execution when the static local has already been initialized. As these systems are out of support, it is extremely unlikely for a patch to be created for those systems to add this support as is present in Vista and newer OSes, and we are reluctant to penalize the performance on in-support OSes to provide this functionality to the old out-of-support ones.

    To work around the issue you can use /Zc:threadSafeInit- to disable the thread-safe initialization code and this will avoid the thread-local variable. Of course by doing so the initialization code reverts back to the VS2013 mode and is not thread-safe, so this option is only viable if you don't rely on the thread-safety of local statics.

    关于c++ - Visual Studio 2015无法产生在Windows XP上成功注册的ATL Dll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34074204/

    相关文章:

    c++ - 自动将带有大量括号((()))的C++代码格式化为多行(更易于阅读)

    c++ - 用于从二进制文件中提取图标的 C/C++ 库

    c++ - 从weak_from_this()获取的weak_ptr无效

    delphi - DLL搜索路径仅部分搜索

    delphi - Robert Giesecke 的非托管导出和 Visual Studio 2015 构建错误

    asp.net - 使用 Asp.Net 5 实时重新加载

    c++ - 关于基类和派生类的构造函数调用

    c++ getter不返回值(NULL)

    .net - Dllimport 可在控制台应用程序中运行,但不能在 ASP.NET 网站中运行

    c++ - VB.NET 无法加载 DLL 找不到指定的模块。当dll导入时