SetEnvironmentVariable 不起作用

Joh*_*ohn 1 delphi delphi-7

我需要为包含的 3rd 方库设置两个环境变量(当我的应用程序运行时)。

问题是“那样”它不起作用,但是当我运行控制台应用程序时,设置这两个变量然后运行应用程序,一切正常......

如何正确配置这两个变量?

我使用的程序:

function SetEnvVarValue(const VarName,
  VarValue: string): Integer;
begin
  // Simply call API function
  if SetEnvironmentVariable(PChar(VarName),
    PChar(VarValue)) then
    Result := 0
  else
    Result := GetLastError;
end;
Run Code Online (Sandbox Code Playgroud)

它返回 0

也许问题是,我在应用程序启动时加载了库。当我的应用程序启动时,我设置了变量,但我这样做太晚了......?


更多信息

我在 dpr 中包含了两个单元:

'C:\Program Files (x86)\Borland\Delphi7\Lib\Magick\magick\ImageMagick.pas' 中的 ImageMagick,'C:\Program Files (x86)\Borland\Delphi7\Lib\Magick\wand\magick_wand 中的 magick_wand .pas';

和单位:

unit DoItFirst;

interface

uses
  Windows, Sysutils;

var
  s: string;
  error: Integer;

function _putenv_s(const lpName, lpValue: PChar): BOOL; cdecl; external 'msvcrt.dll';

implementation

function GetEnvVarValue(const VarName: string): string;
var
  BufSize: Integer;  // buffer size required for value
begin
  // Get required buffer size (inc. terminal #0)
  BufSize := GetEnvironmentVariable(PChar(VarName), nil, 0);
  if BufSize > 0 then
  begin
    // Read env var value into result string
    SetLength(Result, BufSize - 1);
    GetEnvironmentVariable(PChar(VarName),
      PChar(Result), BufSize);
  end
  else
    // No such environment variable
    Result := '';
end;  

initialization

_putenv_s(PChar('DYLD_LIBRARY_PATH'), PChar('g:\_projekty\ZBar Test\'));
_putenv_s(PChar('MAGICK_CODER_MODULE_PATH'), PChar('g:\_projekty\ZBar Test\modules\coders\'));

s := GetEnvVarValue('DYLD_LIBRARY_PATH');
s := GetEnvVarValue('MAGICK_CODER_MODULE_PATH');

end.
Run Code Online (Sandbox Code Playgroud)

该单位位于 dpr 文件的开头。

Dav*_*nan 5

从我从您的更新中可以看出,有问题的第三方库是 ImageMagick。并且该库的 .pas 包装器使用加载时链接到 ImageMagick DLL。

当您从命令解释器修改环境变量,然后启动您的进程时,ImageMagick DLL 可以看到这些环境变量。当您在进程启动代码中修改环境变量时,ImageMagick DLL 无法看到这些环境变量。大概是因为它在您的代码修改它们之前已经读取了变量。

我从上面得出的结论是 ImageMagick DLL 在其初始化时正在读取环境变量。

因为您使用的是加载时链接,所以 DLL 初始化发生在您有机会执行您的代码之前。我可以想到以下方法来解决这个问题:

  1. 将 ImageMagick DLL 从加载时链接切换到运行时链接。这将要求您修改您使用的 ImageMagick 包装器。如果您不熟悉如何执行此操作,那么您可以参考 JEDI 源代码以获取灵感。请注意,如果您使用的是现代 Delphi,那么您可以简单地修改包装 DLL 以延迟加载 ImageMagick DLL。将delayed指令添加到函数声明中。这会导致运行时链接。
  2. 将您的一些代码移动到 DLL 中,以便您可以使用运行时链接加载它。我想象您将使用 ImageMagick 包装器的任何代码移动到 DLL 中。这将允许您继续使用相同的包装器,但仍然在进程运行时而不是进程加载时加载 ImageMagick DLL。您甚至可以将整个代码移动到一个 DLL 中,然后有一个可执行文件,该可执行文件只加载该 DLL,然后调用单个导出main函数。
  3. 使用单独的启动程序。启动器进程准备好环境,然后启动真正的应用程序。

在我看来,在这些选项中,第一个是迄今为止最可取的。