《關於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 從靜態儲存區域分配...