【问题标题】:MS VS 2010 Entry Point Procedure cannot be located after changing Procedure name更改程序名称后无法定位 MS VS 2010 入口点程序
【发布时间】:2014-05-02 17:36:24
【问题描述】:

这是一个我找不到答案的谜题(在 SO 或其他网站上)。我是 SO 的新手,但我正在努力快速学习。

我需要更改我的 dll 入口点过程的名称

int subCreatePipe()

int subCreateNewPipe()

但是当我这样做时,启动程序就会死掉。

具体错误是:

“过程入口点 subCreateNewPipe 不能位于动态链接库 myPipe.dll 中”

我正在运行的设置是:

  • Windows 7
  • MS Visual Studio 2010
  • C++ Win32
  • 非托管(无 CLI)
  • MBCS

    • 我创建了一个“myPipe.dll”(使用上述设置)来测试我创建 dll 和打开管道的能力。
    • 我创建了一个“TestPipe.cpp”(使用上述设置,但使用 Win32 控制台),因此我可以运行一个链接到 dll 的程序并为我显示一些结果。
    • (我还有另一个程序可以向管道发送一些东西。)

现在是关键:

  1. 我用一个名为int subCreatePipe() 的过程创建了dll。
  2. 我编译成功了。
  3. 我将发布文件移动到我的TestPipe 项目“Lib”子文件夹。
  4. 在 TestPipe.cpp 中,我有一行要调用该过程:

    x = subCreatePipe();
    
  5. 我编译了 TestPipe.cpp 并运行了“TestPipe.exe”版本,它运行良好。 它找到 subCreatePipe 的入口点。

但我需要将 DLL 过程重命名为 subCreateNewPipe 以遵守我无法控制的命名约定。

  1. 我将 myPipe.dll 中的过程重命名为 int subCreateNewPipe()
  2. 我编译成功了。
  3. 我将发布文件移动到我的 TestPipe 项目“Lib”子文件夹中。 (删除旧文件)
  4. 在 TestPipe.cpp 中,我将对过程的调用更改为:

    x = subCreateNewPipe();
    
  5. 我编译了 TestPipe.cpp 并运行了“TestPipe.exe”版本,它死了(上面给出了错误)。

如果我返回并将 DLL 过程名称更改为 subCreatePipe,它将再次运行。如果我回去把它改成subCreateNewPipe,它又会死掉。我唯一不同的是更改入口点过程名称。

所以我的问题是:

  1. 有没有办法在 VS 2010 中重命名入口点程序?
  2. 我是否应该使用DLLMain(),即使我只是将其留空? (这看起来很糟糕。)
  3. 是不是我遗漏了一些隐藏的开关?
  4. 链接器到底发生了什么?
  5. 是否正在进行名称修改?
  6. 或者第一次编译项目后还有什么不能改的?

我尝试了其他一些方法(仍然给出“第一种方式有效”但“第二种方式失败”的相同结果):

  • 我尝试使用__stdcall

    int __stdcall subCreatePipe() // works 
    int __stdcall subCreateNewPipe() // doesn't work
    
  • 我尝试使用__declspec(dllexport)

    ifdef X_EXPORT_FLAG  
    #define DLL_IMPORT_EXPORT __declspec(dllexport)  
    else  
    #define DLL_IMPORT_EXPORT __declspec(dllimport)  
    endif
    
    X_EXPORT_FLAG int __stdcall subCreatePipe() // works
    X_EXPORT_FLAG int __stdcall subCreateNewPipe() // doesn't work
    
  • 我还尝试使用 .DEF 文件为链接器定义过程名称。

    int subCreatePipe() // works 
    int subCreateNewPipe() // doesn't work
    

(在所有示例中,我更改了 TestPipe.cpp 代码以调用正确的过程名称。)

如果你说不出来,我有点强迫症想弄清楚如何让它发挥作用。

我现在要创建一个新的 Win32 控制台应用程序来调用 dll(我应该在 24 小时前完成的事情。)但是,我仍然很好奇为什么我不能更改入口点过程名称.任何关于为什么无法完成、更好的编码技术或如何解决此链接器问题的见解都将受到欢迎。

【问题讨论】:

  • 如果我理解您的问题,您不应为此使用术语“dll 入口点程序”。 DLL 入口点是加载器在加载 DLL 时调用的东西,是一个相当高级的设置,很少需要弄乱。您似乎在谈论的是从应用程序调用的 DLL 导出。
  • 听起来应用程序正在定位旧的 DLL 构建。确保更新的 DLL 位于应用程序将从中加载它的位置。
  • 嗨迈克尔 :) 感谢您的回复。我收到的错误消息是“...procedure Entry Point...”,这就是我在描述中使用它的原因。我没有触摸 dll 入口点的 Configuration->Linker->Advanced 选项。该设置保持空白。另外...我同意这听起来像是一个旧的 DLL 可能是问题所在。但事实并非如此。我每次都清除我的 dll libray 文件夹并复制新的 dll Release 文件。当我编译了原始过程名称时......它可以工作。当我尝试更改原始过程名称时,它不起作用。 ...我知道...这也让我感到困惑。
  • 在“入口点”术语上足够公平。您能否尝试以下操作并将结果粘贴到您的问题中:link /dump /exports myPipe.dll | grep subCreatelink /dump /imports application.exe | grep subCreate(在适当的情况下替换正确的文件名)。
  • 谢谢 Michael :) 那些查看 dll 详细信息的工具非常有帮助。非常有帮助,他们帮助我解决了我的问题。我将编辑我上面的帖子,详细说明我错过解决方案的原因。再次感谢您对我的耐心和分享这些工具!

标签: c++ dll unmanaged visual-c++-2010 entry-point


【解决方案1】:

解决方案:

非托管 C++ 中,DLL 不会像在托管 C++ 中那样从“Release”文件夹中清除。每次更改 DLL 时,都必须将新 DLL 物理移动到应用程序的“Release”文件夹中。

我学会了如何在 Managed C++ 中更新 DLL,您所要做的(在您的应用程序文件夹中)就是清除旧的 DLL 库子文件夹并复制到新版本的将 DLL 更改为那个空的库子文件夹。当您“清理并重建”调用这些 DLL 的应用程序时,Managed VS2010 C++ 将从“Release”文件夹中删除旧 DLL,并将新 DLL 从库子文件夹复制到应用程序中“释放”文件夹。它可以很好地使您的 DLL 保持最新。

非托管 C++ 中,“清理并重建”不会从应用程序的“Release”文件夹中删除您的旧 DLL。而且它不会从您的库子文件夹中复制新的 DLL。因此,即使我认为我将我的新 DLL 放在我的程序可以找到它们的文件夹中,它们并没有像在托管 C++ 下那样被复制。

当 Michael Burr 给我link /dump /exports myPipe.dll 工具时,我能够看到 DLL 的时间戳和可用的过程。 (在我的例子中,它是第一个只有一个过程的 DLL 构建。)很明显,它是一个旧的 DLL,而不是当前的。

这解释了为什么应用程序总是使用旧的过程名称运行。但是,当使用新的过程名称编译时,它给出了一个过程入口点错误,因为应用程序只能找到旧的 DLL(其中不存在新的过程名称)。

再次感谢! :)

【讨论】:

    猜你喜欢
    • 2014-12-21
    • 2016-01-20
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多