2009-06-25 106 views
6

我正忙於編寫一個爲主機應用程序提供多種功能的DLL。 該應用程序動態調用dll,在每次函數調用後加載並釋放它。德爾福動態Dll - 全局變量

我無法控制主機應用程序。我只能在dll內工作。 有沒有辦法讓內存中的某些變量保留下來,以便我可以在每個函數中重用它們?很明顯,當主機應用程序卸載dll時,全局可變數據就會被清除。 保存DLL文件聽起來非常混亂!

任何人都可以提出一種方法來分配一個變量,我可以保持全球?

謝謝

+3

您的設計很糟糕,原因很多。你有沒有想過多個主機應用程序(快速用戶切換,在終端服務器下使用)或主機應用程序從多個線程調用DLL函數的可能性?不惜一切代價儘量避免全局/共享狀態。 – mghie 2009-06-25 09:45:47

回答

4

我認爲你在這裏有兩個主要選項。

  1. 報價2版本的功能,你現在有一個,加上另一個地方,他們在緩衝區(記錄,等等),你可以讀取以前的狀態,當然更新狀態爲通過。稱這是函數的高性能版本。他們會想要使用它。

  2. 保存喜歡你的狀態會一個cookie(那基本上它是什麼)在文件中的某個地方。

選項1將需要修改主機應用程序,但將是引人注目的主機應用程序開發人員採取的,選項2優點將不需要改變到主機應用程序,但不會像高性能的。

我不會親自傾向於開始擺弄引用計數,想必主機應用程序正在卸載是有原因的,如果我是主機應用開發,這將激怒了我。

+0

謝謝 - 我認爲這是最好的選擇。 我寧願保存到文件並採取性能比風險而不是擺弄dll引用。也許主機應用程序開發人員將繼續提供高性能版本 – Crudler 2009-06-26 12:30:27

1

最好的方法是使用包含「全局變量」的類。您實例化一個對象並將其作爲參數提供給dll函數。但這不會幫助你,因爲你無法更改調用應用程序。

如果你必須保持全局數據在DLL中,一個解決方案是將它們寫入文件。但這對性能造成嚴重影響。

0

如果我是你,我會的全局變量的值保存到一個文件時,該dll被釋放,當它被初始化加載它們。我沒有理由保存磁盤上的DLL的內存轉儲。

4

警告,骯髒的黑客:

您可以加載自己。

每次調用LoadLibrary遞增引用計數器,FreeLibrary遞減它。只有當計數器達到零時,DLL纔會被卸載。

因此,如果第一次你的DLL被加載時,你又把您的書架,從而增加引用計數器。如果調用應用程序調用FreeLibrary引用計數器遞減,但該DLL不會被卸載。

編輯:正如mghi指出,如果進程終止,DLL是否會被卸載,引用計數是否爲零。

+1

是的,但是這個方法再次增加了很多關於何時決定dll應該真正卸載的時間,因爲它不需要一直運行。該dll然後應該檢查主機應用是否仍然存在定期,我不太喜歡,但這只是我。 – zz1433 2009-06-25 09:17:43

+3

@Aldo:不正確 - 如果只有一個進程使用該DLL,那麼一旦該進程退出,引用計數是否已達到0,它將被卸載。 – mghie 2009-06-25 09:30:01

2

如果你有大量的全局數據要共享,另一個解決方案是創建一個windows服務來「緩存」狀態數據。您還需要實現某種跨越進程邊界的IPC,例如內存映射文件,郵箱,COM(本例爲單實例),TCP/IP等。您可能會發現這種開銷不僅僅是將狀態寫入文件,這就是爲什麼我只會在狀態數據量過多時才推薦這種方法,或者只會在每個請求的整個部分處理這些數據進入你的dll。

對於COM方法,除了請求(並保持)將用於維護狀態的com對象的實例之外,服務不必做太多的事情。由於它是一個單實例com對象,因此所有請求都將發送給同一個實例,從而允許您在請求之間保存狀態。對該對象的請求將被序列化,因此,如果您有多個客戶端同時在同一臺計算機上請求數據,則這可能是性能問題。

0

當DLL被釋放時將值寫入註冊表,並且在加載DLL時從註冊表讀取值。當讀取發現沒有設置密鑰時,不要忘記提供默認值。

-Al。

0

我同意之前關於全球狀態信息危險的評論,儘管我可以想象它可能是需要的。

我提出DR的骯髒的黑客更清潔的版本不具有作爲永久像skamradt的回答的缺點:

一個非常小的應用程序:

它沒有外觀無論如何,它讓自己從顯示在任務欄上。

任務#1:加載DLL

任務#2:把它的命令行,運行它,並等待它終止。

任務#3:卸載DLL

任務#4:退出。

安裝程序:

它找到快捷方式(多個)到主應用程序,並修改它們所以小應用程序運行時,原始位置的快捷指向變成第一參數。

結果:只有主應用程序正在運行,DLL纔會保留在內存中,但每次程序轉儲時它都不會被卸載。

0

這也可能是有益的

option 1: 創建握着你的頁面文件支持的變量共享內存區 - 如果你能打開共享內存區,你的DLL以前加載(假設「私人「共享內存名稱,可能名稱與process_id_yourdllname類似) - 如果您無法打開它,那麼您首次創建並初始化它。如果你創建了它,那麼你不用去刪除它 - 但是如果你打開它,你會在卸載時關閉它。我相信當應用程序關閉時該區域將被釋放,因爲沒有其他應用程序應該處理這個特定的「私有」共享內存區域。

option 2: 創建第二個。只存在用於管理全局變量的dll。你的DLL A可以加載該DLL B,而不是釋放它,放入DLL B無論你需要管理全局變量。當應用程序消失時它應該消失,我認爲你可能不需要關心(可能是無用的)引用計數(因爲你不會卸載dll B)。