【问题标题】:Get DLL caller info in Delphi在 Delphi 中获取 DLL 调用者信息
【发布时间】:2014-12-15 20:59:27
【问题描述】:

在一个Delphi DLL中需要建立调用者——可能是一个简单的“.exe”或者一个DBMS运行时模块——这意味着它必须获取进程中运行的命令。

我知道 CmdLine 不起作用,并且可能是 ParamStr(0),并且不能使用基于“主窗口”的技术,因为调用者有时没有窗口.我怀疑 GetModuleHandle 是起点,但需要帮助才能从那里到达正在执行的命令。

【问题讨论】:

  • 为什么你不能让你的调用者在一个参数中告诉你你需要知道的信息?
  • 您必须以更精确的方式定义“调用者”。

标签: windows delphi dll


【解决方案1】:

我创建了一个测试 dll:

library Project2;

uses
  System.SysUtils, System.Classes, Vcl.Forms, Vcl.Dialogs, Winapi.Windows;

{$R *.res}

procedure DoStuff; stdcall;
begin
    ShowMessage(
            'ParamStr(0): '+ParamStr(0)+#13#10+
            'GetCommandLine: : '+GetCommandLine);
end;

exports
    DoStuff;
begin
end.

然后从测试应用程序中调用它:

procedure TForm1.Button1Click(Sender: TObject);
var
    module: HMODULE;
    doStuff: procedure; stdcall;
begin
    module := LoadLibrary('D:\Temp\Win32\Debug\Project2.dll');
    if module = 0 then
        RaiseLastOSError;
    try
        doStuff := GetProcAddress(module, 'DoStuff');

        if @doStuff = nil then
            raise Exception.Create('Could not find export "DoStuff"');

        DoStuff;
    finally
        FreeLibrary(module);
    end;
end;

它看到命令行,同时使用:

  • ParamStr(0)
  • GetCommandLine

GetCommandLine 显然显示了整个命令行,而ParamStr(0)(根据定义)只是进程可执行路径。

【讨论】:

    【解决方案2】:

    事实上ParamStr(0) 可以正常工作。在 Windows 上,它是通过调用 API 函数 GetModuleFileName 来实现的,将 0 的值作为模块句柄传递。这将检索与主可执行模块关联的文件名。无论调用是从 DLL 还是主可执行文件进行,这都一样。

    如果我们相信 Delphi 文档,我们真的不需要深入研究实现。诚然,这有时可能是一项有风险的业务! ParamStr 的文档说:

    ParamStr(0) 返回执行程序的路径和文件名(例如,C:\TEST\MYPROG.EXE)。

    如果您需要知道传递给可执行进程的参数,您可以使用ParamStr 传递大于零的索引。或者您可以调用GetCommandLine 并自己解析命令行。

    请注意GetCommandLine 并不总是提供与GetModuleFileName 相同的可执行文件名。 documentation 说:

    操作系统提供给进程的命令行中可执行文件的名称不一定与调用进程提供给 CreateProcess 函数的命令行中的名称相同。操作系统可能会在没有完全限定路径的情况下为可执行文件名添加一个完全限定路径。

    虽然这一切都感觉有点脏。从 DLL 导出初始化函数并要求调用者传递您需要的任何信息可能会更简洁。

    【讨论】:

    • 大卫,这是一个“信任 Delphi 文档”问题引发了这个问题。那些文档说全局“CmdLine”变量在 DLL 中无效——这让我相信“GetModuleFileName”不可用(即,它需要一些其他系列的神秘 WinAPI 调用才能获得所需的信息)。顺便说一句,我不能要求调用者识别自己的原因是调用将来自可以重新编译的代码,以适应更改,以及超过十年的代码不再可修改(而 DLL API 是替代对于不需要知道的前任)。
    • 如有疑问,可以随时查阅源代码。我做到了。所以现在你可以信任 ParamStr(0)。
    • ... 除非您是使用所谓“Starter”版的初学者,在这种情况下您别无选择,只能依赖文档(或询问其他人)。只是说。 ;)
    • @BruceWeinel 你还卡住了吗?
    猜你喜欢
    • 2012-08-01
    • 2010-10-25
    • 1970-01-01
    • 2023-03-22
    • 2021-05-25
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    相关资源
    最近更新 更多