SetEnvironmentVariable无法正常工作

时间:2014-07-25 07:34:48

标签: delphi delphi-7

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

然而,问题在于“那种方式”不起作用 当我运行控制台应用程序时,设置这两个变量,然后运行应用程序,一切正常......

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

我使用的程序:

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;

返回0

也许事情是,我在应用程序启动时加载了库。 当我的应用程序明星我设置变量,我做得太晚了??


更多信息

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

ImageMagick在'C:\ Program Files(x86)\ Borland \ Delphi7 \ Lib \ Magick \ magick \ ImageMagick.pas'中, magick_wand在'C:\ Program Files(x86)\ Borland \ Delphi7 \ Lib \ 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.

此单元位于dpr文件的开头。

2 个答案:

答案 0 :(得分:4)

在第三方库读取之后,您可能正在更改环境变量

首先,你应该将环境变量设置为旅行计划的第一件事。

即便如此,可能是第三方库可能正在初始化函数中读取该信息,可能在您的代码开始运行之前。

如果是这种情况,我认为初始化顺序是确定性的(参见here),具体取决于dpr(项目文件)中单位的顺序

如果您希望在第三方库之前设置这些变量,则可以创建DoMeFirst单元并在该单元的init代码中执行。然后确保它是项目文件中的第一个。

如果这不起作用,另一种选择可能是编写一个改变环境的程序,然后然后将您当前的程序称为孩子。

答案 1 :(得分:4)

从我的更新中可以看出,第三方库是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. 使用单独的启动程序进程。启动程序进程准备环境,然后启动实际应用程序。
  4. 在我看来,在这些选项中,第一个是最优选的。