2014-07-25 20 views
0

我需要爲包含的第三方庫設置兩個環境變量(當我的應用程序運行時)。SetEnvironmentVariable不起作用

的問題是,「這樣」這是不是然而工作, 當我運行控制檯應用程序,設置這兩個變量,然後運行該應用程序,一切都還好...

如何配置這兩種變數正確嗎?

我使用的過程:

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:\程序文件(x86)\ Borland的\ Delphi7的\ LIB \ Magick \ magick \ ImageMagick.pas ', magick_wand in'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文件的開頭。

+0

SetEnvironmentVariable返回可通過GetLastError獲取的失敗的Windows錯誤代碼。你有什麼價值? –

+0

返回0返回 – John

+0

@John,聽起來像返回它的最佳時間,回報爲:-) – paxdiablo

回答

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,然後調用一個導出的函數。
  3. 使用單獨的啓動程序進程。啓動程序準備環境,然後啓動實際應用程序。

在我看來,這些選項中,第一個是迄今爲止最優選的。

+0

謝謝。我可以看到你的觀點。我假設我可以這樣做:設置變量,loadlibrary和調用方法。但我很好奇,爲什麼,當這些庫被調用,以便我不能更早地設置變量... – John

+0

您需要了解加載時間鏈接和運行時鏈接之間的區別。在MSDN上閱讀它。重點是加載時間鏈接DLL的DllMain函數在任何可執行代碼之前執行。 –

+1

@DavidHeffernan值得補充的是,任何使用Delphi 2010或更高版本閱讀的人都可以選擇將延遲關鍵字添加到dll API聲明中,該聲明會自動延遲dll負載,直到第一次dll API調用修復問題而沒有任何重大的返工。它顯然與當前海報無關,因爲我們可以看到Delphi 2007正在使用 – Kanitatlan

4

您可能在之後更改了環境變量,它們已被第三方庫讀取。

首先,你應該第一件事旅遊項目不設置環境變量。

即使這樣,它可能是第三方庫可以讀取初始化函數的信息,可能你的代碼,甚至開始運行之前。

如果是這樣的話,我覺得初始化的順序是確定的(見here),這取決於你的單位在dpr(項目文件)的順序。

如果您希望在第三方庫看到它們之前設置這些變量,您可以創建一個DoMeFirst單元並在該單元的init代碼中執行該單元。然後確保這是項目文件中的第一個。

如果這不起作用,另一種選擇可能是編寫一個程序,它改變環境,然後作爲孩子調用當前程序。

+0

在應用程序加載外部庫之前,是否可以在應用程序的某處運行代碼?我試圖在dpr項目開始後運行代碼,但沒有運氣 – John

+0

不幸的是,它不工作。我按你的建議做了。它在開始時設置了這兩個變量,但仍然存在該庫的問題:/ – John

+0

然後,您最好的選擇可能是聯繫這些庫的作者。順便說一句,你確定你在DPR文件中有正確的順序嗎? – paxdiablo