正確使用DllGetVersion

2021-06-07 16:27:35 字數 3328 閱讀 1064

《關於notifyicondata的一些新特性》中,我提到了使用

[cpp:nogutter]view plain

copy

print?

hresult callback dllgetversion(dllversioninfo *pdvi);  

這一函式獲取shell32.dll的版本號,但這一函式不是api,而是shell32.dll中的乙個匯出函式。我們需要使用loadlibrary與getprocaddress 來獲取這個函式的指標,並呼叫它,才能實現版本的獲取。 下面,簡單介紹下如何實現這一過程。

首先,dllgetversion並不是每乙個版本的shell32.dl的匯出函式,若函式getprocaddress在shell32.dll中找不到此匯出函式,返回值為0 ,這時,我們可以確定shell32.dll為4.7.1之前的版本(4.7.1開始有此匯出函式)。

其次,使用 loadlibrary 載入dll時,錯誤的操作會有安全風險,我們必須確保dll路徑有效並且正確。

再次,函式dllgetversion的唯一引數是乙個指向dllversioninfo結構的指標,該結構用於接收dll的版本資訊(major and minor version numbers, the build number, and a platform id),在呼叫之前,我們必須初始化該結構中的cbsize。下面給出的是該結構定義。

[cpp:nogutter]view plain

copy

print?

typedef

struct _dllversioninfo  dllversioninfo;  

另外,在windows 2000及之後的版本,系統返回的可能是dllversioninfo2結構,為了保持相容性,該結構的第乙個成員是dllversioninfo結構。在返回dllversioninfo2結構時,可以使用巨集makedllverull將 versions, build numbers, and service pack releases等資訊與該結構中的成員 ullversion 進行比較。下面給出的是該結構的定義。

[cpp:nogutter]view plain

copy

print?

typedef

struct _dllversioninfo2  dllversioninfo2;  

最後,該函式的返回值為s_ok則表示成功獲取。

下面給出的是msdn中的乙個例子,用於獲取指定路徑dll的版本資訊,版本資訊中的major,minor資訊組合成dword形式返回,若指定dll不存在,返回0。

[cpp:nogutter]view plain

copy

print?

#include "stdafx.h"

#include "windows.h"

#include "windef.h"

#include "winbase.h"

#include "shlwapi.h"

#define packversion(major,minor) makelong(minor,major)

dword getversion(lpctstr lpszdllname)  

}  freelibrary(hinstdll);  

}  return dwversion;  

}  

呼叫例子,判斷shell32.dll版本是否大於6.0

[cpp:nogutter]view plain

copy

print?

lpctstr lpszdllname = l"c://windows//system32";  

dword dwver = getversion(lpszdllname);  

dword dwtarget = packversion(6,0);  

if(dwver >= dwtarget)  

else  

該例子存在一些問題,函式getversion定義了dvi為dllversioninfo型變數,卻引用了不存在的成員info1,應該去掉通過該成員的呼叫,或者直接定義為dllversioninfo2型的資料。

info1實際上為dllversioninfo2型別的成員,我們可以定義該結構變數,並初始化info1中的cbsize為dllversioninfo2大小,再傳遞dvi.info1至getdllversion,這個函式原意可能是想表明如何使用dllversioninfo2型別的結構,再使用ullversion成員進行判斷。

下面介紹使用dllversioninfo2結構進行版本判斷,巨集makedllverull引數為

[cpp:nogutter]view plain

copy

print?

ulonglong makedllverull(  

word wmajorversion,  

word wminorversion,  

word wbuild,  

word wqfe  

);  

呼叫如下:

[cpp:nogutter]view plain

copy

print?

dllversioninfo2 dvi2;     

hresult hr;     

zeromemory(&dvi2, sizeof(dvi2));     

dvi2.info1.cbsize = sizeof(dvi2);     

hr = (*pdllgetversion)(&dvi2.info1);     

if(dvi2.ullversion >= makedllverull(4, 71, 0,0))    

經測試,在win7 64bit與xp下ullversion都可以接收到正確的版本號資訊。

最後補充一點,關於shell32.dll版本,在msdn中給出6.0.6版本以上均為vista及以上作業系統,而xp則是6.0版本的。

勸各位先檢視下自己硬碟/windows/system32/shell32.dll的屬性中版本資訊,再選擇具體的判斷依據。

在我的電腦上,其中在xpsp3下的版本為6.0.2900.5512,win7 64bit下為6.1.7600.16644。

我不知道6.0.6與6.0.2900哪個版本高,但若是利用ullversion直接判斷,那麼6.0.6 < 6.0.2900。

vista正確的版本號是6.0.6000.***x,寫程式時不要忽略了這點。

正確使用記憶體

對於初學者來說,記憶體是個神秘的空間。程式的絕大部分錯誤,也是在於記憶體的使用不當造成的,而且這些錯誤有些都是隱藏很深的。所以,如何掌握記憶體的使用,通曉系統對記憶體的管理手段,將是軟體成功的乙個非常關鍵的因素。首先我們要了解記憶體的分配方式。一般來說,記憶體的分配方式有三種 1 從靜態儲存區域分配...

Calendar 正確使用

public static void main string args calendar cal calendar.getinstance cal.settime new date 當前年 int year cal.get calendar.year 當前月 int month cal.get ca...

正確使用記憶體

對於初學者來說,記憶體是個神秘的空間。程式的絕大部分錯誤,也是在於記憶體的使用不當造成的,而且這些錯誤有些都是隱藏很深的。所以,如何掌握記憶體的使用,通曉系統對記憶體的管理手段,將是軟體成功的乙個非常關鍵的因素。首先我們要了解記憶體的分配方式。一般來說,記憶體的分配方式有三種 1 從靜態儲存區域分配...