青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

如何獲取某個動態(tài)鏈接庫的版本信息

我如何獲得安裝在我的系統(tǒng)上的某個特定的 DLL 的版本信息?我嘗試著確定系統(tǒng)安裝了哪個版本的 comctl32.dll。我見過有些代碼調(diào)用 GetProcAddress 來獲取各種函數(shù),如 InitCommonControlsEx,以確定基于不同版本的函數(shù)調(diào)用。對于我來說,這是一個坎兒,到底用什么方法獲得版本號?

  有兩種方法:容易的和難的。容易的方法是調(diào)用一個專門用于此目的的函數(shù) DllGetVersion。問題是雖然 comctl32.dll 支持該函數(shù),但并不是所有的 DLLs 都具備它。如果不具備 DllGetVersion,那么就得用難的方法——使用 FileVersion API,這可能是你要遭遇到的最為曖昧的 API 之一。我寫了一個類 CModuleVersion 來封裝兩種方法,同時還寫了一個Demo程序 VersionDlg 來示范 CModuleVersion 的使用方法。程序畫面如 Figure 1 所示。你可以在編輯框中敲入任何系統(tǒng)模塊的名字,VersionDlg 將用 DllGetVersion (如果具備這個函數(shù)的話)和 FileVersion API 兩種方法顯示版本信息。源代碼參見 Figure 2。

  Figure 1 運行中的 VersionDlg 程序

  讓我們先看容易的方法。DllGetVersion 用 DLL 版本信息填寫一個 DLLVERSIONINFO 結(jié)構。該結(jié)構定義在 Win32 SDK 的 showapi.h 頭文件中。許多人可能都沒有安裝 Platform SDK,那么就得自己定義這個結(jié)構了(譯者注:實際上,早期的 Developer Studio 不包含這個頭文件。后來的 Visual Studio 6.0 安裝已經(jīng)包含該頭文件,路經(jīng)參見:Driver:Program FilesMicrosoft Visual StudioVC98Include),就像我在 VersionDlg 所做的那樣。

typedef struct _DllVersionInfo {
DWORD cbSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformID;
} DLLVERSIONINFO;

  這個結(jié)構中的字段基本不用怎么說明就知道是什么意思:dwPlatformID 為 DLLVER_PLATFORM_WINDOWS (value = 1)指 Windows 9x,而 DLLVER_PLATFORM_NT (value = 2)用于 Windows NT。一旦定義了 DLLVERSIONINFO 結(jié)構,就可以調(diào)用 DllGetVersion 了,該函數(shù)的署名如下:

HRESULT DllGetVersion(DLLVERSIONINFO*);

  因為并不是任何給定的 Dll 都輸出 DllGetVersion 函數(shù),你得按照標準套路來調(diào)用它,即調(diào)用 GetProcAddress 并判斷返回值是否為 NULL。我編寫的類 CModuleVersion 中含有一個 DllGetVersion 函數(shù),它把所有細節(jié)都進行了封裝(參見 Figure 2 中的 ModulVer.cpp。)CModuleVersion 類的使用方法如下:

DLLVERSIONINFO dvi;
if (CModuleVersion::DllGetVersion("comctl32.dll", dvi))
{
  // now info is in dvi
}

  DllGetVersion 是一個比較新的函數(shù)(譯者注:在1998年是這樣。)對于 comctl32 很好使,因為它實現(xiàn)并輸出 DllGetVersion——但是對于那些不輸出 DllGetVersion 的 DLLs 來說怎么辦呢?例如:shell32.dll 就沒有實現(xiàn) DllGetVersion,如 Figure 3 所示。這時你就得用可怕以及奇怪的 GetFileVersionInfo 和 VerQueryValue 函數(shù),它們在 winver.h 中定義。

  Figure 3 No DllGetVersion Info

  大多數(shù)可執(zhí)行程序和 DLLs 都具備 VS_VERSION_INFO 資源,在模塊的 RC 文件中定義。Figure 4 是 VersionDlg 的 RC 文件中的版本信息。你可以用文本編輯器或者 Visual Studio 直接編輯資源文件中的這段信息。你可以指定文件版本,產(chǎn)品版本等等,以及任何你想要編輯的字段,如:CompanyName、InternalName。文件版本信息與 Exe 或 DLL 文件在資源管理器“屬性”頁“版本”標簽中顯示的信息相同(參見 Figure 5)。

  Figure 5 Version Tab

等一會兒你就會發(fā)現(xiàn),這些版本 APIs 十分曖昧,很容易把人搞暈菜,但 CModuleVersion 使一切都變得簡單明了。這個類派生于 VS_FIXEDFILEINFO(參見 Figure 6),此結(jié)構包含“固定的”版本信息,其中有主版本號和次版本號,還有一些 DLLVERSIONINFO 里的東西。使用 CModuleVersion 時,只要像下面這樣寫即可:CModuleVersion ver;
if (ver.GetFileVersionInfo(_T("comctl32.dll"))
{
  WORD major = HIWORD(ver.dwFileVersionMS);
  WORD minor = LOWORD(ver.dwFileVersionMS);
  ...
}

  為了存取 CompanyName 這樣的可變信息以及內(nèi)涵的模塊創(chuàng)建信息,你可以用另外一個函數(shù) CModuleVersion:: GetValue,例如,下面代碼段執(zhí)行之后,sCompanyName 的值將類似“XYZ”或“Acme Corporation”這樣的公司名稱:

CString sCompanyName =
ver.GetValue(_T("CompanyName"));

  CModuleVersion 隱藏了獲取信息所要做的所有邋遢細節(jié)——相信我,都是些邋遢細節(jié)!如果你只是想使用 CModuleVersion,那么看到這里就可以打住了;如果你想要了解 CModuleVersion 的工作原理,那就繼續(xù)往下看。

  假設 CModuleVersion::GetFileVersionInfo 能加載模塊并獲取 HINSTANCE,它調(diào)用 ::GetFileVersionInfoSize 來獲取版本信息的大小,然后分配一個緩沖并調(diào)用 GetFileVersionInfo 來填充該緩沖。原始緩沖(CModuleVersion::m_pVersionInfo)是一個數(shù)據(jù)塊,它包含固定的信息和可變信息。VerQueryValue 將一個指針指向你感興趣的特定信息的起始位置。例如,為了得到固定的信息(VS_FIXEDFILEINFO),你得這樣寫

LPVOID lpvi;
UINT iLen;
VerQueryValue(buf, _T("\"), &lpvi, &iLen);

  此處 buf 是從 GetFileVersionInfo 返回的完整信息。字符串“”(在 C 中用“\”),你如果把它看作是一個目錄,那它就是根信息(有一點像注冊表)。VerQueryValue 將 lpvi 置到 VS_FIXEDFILEINFO 的起始處,iLen 為其長度。

  以上是獲取固定信息的方法,可變信息獲取更奇怪,因為你必須首先知道語言 ID 和代碼頁是什么。在 Winidows 里,代碼頁指定了一個字符集,它是字符文字與表示它們的 1 或 2 字節(jié)值之間映射。標準的 ANSI 代碼頁是 1252;Unicode 是 1200。Figure 7 是語言ID和代碼頁的清單。Figure 4 中文件信息里的 Translation 鍵指定模塊的語言ID和代碼頁。在 CModuleVersion 中,我使用自己的 Translation 結(jié)構來獲取這個信息。

// in CModuleVersion
struct TRANSLATION {
WORD langID // language ID
WORD charset; // code page
} m_translation;

  為了獲取語言信息,CModuleVersion 用 VerQueryValue 函數(shù)以 VarFileInfoTranslation 作為鍵。

if (VerQueryValue(m_pVersionInfo,"\VarFileInfo\Translation", &lpvi, &iLen) && iLen >= 4)
{
  m_translation = *(TRANSLATION*)lpvi;
}

  一旦你知道了語言ID和代碼頁,你就可以得到 CompanyName 和 InternalName 這樣的可變信息。實現(xiàn)方法是構造一個如下形式的查詢:

StringFileInfo<langID><codepage><keyname>

  這里 <langID> 是十六進制 ASCI 形式的語言ID(中文是 0804;US English 是 0409),<codepage> 是代碼頁,格式為(1252 即 ANSI 的代碼頁是04e4),<keyname> 是你想要的鍵,如:CompanyName。為了構造這個查詢,你得用 sprintf 或者 CString::Format 來構造字符串:

\StringFileInfo\040904e4\CompanyName

  然后將這個字符串傳給 VerQueryValue。如果你對這些繁瑣的細節(jié)感到暈菜,不用擔心——很幸運,CModuleVersion::GetValue 對所有邋遢細節(jié)都進行了封裝,所以你只要像下面這樣寫即可:

CString s = ver.GetValue(_T("CompanyName"));

  實現(xiàn)了 CModuleVersion,VersionDlg 就簡單多了。 它實際上就是一個對話框,這個對話框帶有一個編輯框,用于輸入模塊名稱,每當用戶在編輯框中敲入模塊名稱時,MFC 便調(diào)用 ON_EN_CHANGE 消息處理例程 CVersionDialog::OnChangedModule。OnChangedModule 例程通過 CModuleVersion 對象及其 GetFileVersionInfo 和 GetDllVersion 函數(shù)來獲得版本信息,然后將信息顯示在對話框的兩個靜態(tài)文本控件中。這個過程很簡單。

  最后還有個技巧我得提一下。GetFileVersionInfo,VerQueryValue 以及其它有關文件版本函數(shù)在一個叫做 version.lib 的庫中,你必須將它鏈接到你程序中。從而避免鏈接時出現(xiàn)煩人的“undefined symbol”(未定義符號)錯誤,ModuleVer.h 使用了一個鮮為人知但特別有用的 #pragma comment 語法,即使你忘記在 Project|Settings 的 Link 屬性頁中添加 Input ==〉Libraries 也沒關系,#pragma comment 會告訴鏈接器與 version.lib 鏈接。

// 告訴鏈接器與 version.lib 進行鏈接
#pragma comment(linker,
"/defaultlib:version.lib")

  現(xiàn)在,有人可能會問,為什么這些東西如此重要?以及誰會需要這些東西呢?一般來說,如果你編寫的是顯示文件屬性之類的工具程序,那你只是需要獲取諸如 CompanyName 和 LegalCopyright 之類的變量。但你也許發(fā)現(xiàn)用 CModuleVersion 從自己的應用程序中吸取文件信息很有用,例如,為了在“關于”對話框和啟動屏幕中顯示版本信息。如果你使用 CModuleVersion,你只需修改資源文件中相應位置的版本信息即可,“關于”對話框和啟動屏幕會自動顯示當前最新版本信息。

 

  版本信息另一個重要的用途是確定某個DLL是針對哪種語言編寫的,這樣你代碼能與之對應。隨著當今基于 Windows 的編程技術迅猛發(fā)展,DLLs 的新版本也隨之日新月異,你很快就會發(fā)現(xiàn)下面這樣的代碼越來越多:

if (version <= 470)
// do one thing
else if (version==471)
// do something else
else if (version==472)
// do a third thing
else
// scream

  這是一件很郁悶的事情,我敢說這也是微軟的大佬們引入 DllGetVersion 來快速獲取版本號的一個原因,從而避免了面對讓人恐懼的 GetFileVersionInfo 函數(shù),只用它來獲取語言 IDs 和代碼頁(僅在需要獲取諸如 CompanyName 這樣的信息時使用)。

  comctl32.dll 的與眾不同也沒有什么意外的,這個模塊版本問題已經(jīng)程序員最大的禍害之一,我可憐的郵箱曾被讀者關于 comctl32.dll 這個模塊的問題撐爆,很多問題都是客戶下載了微軟最新版本的 comctl32.dll 到機器上之后,應用程序就無法運行了。我會在以后的文章中解釋 comctl32.dll 的版本問題,以及新的 toolbar 特性,如何解決 MFC 中 CToolBar 的 bug。現(xiàn)在,由于篇幅所限,我只能點到為止,目前 comctl32.dll 最新的版本為 6.00(隨 IE 一起發(fā)布)。

  最后,感謝上帝,微軟已經(jīng)出臺關于可以隨你的應用程序一起分發(fā) comctl32.dll!但不是單獨分發(fā) comctl32.dll,而是可以隨你程序的更新包及其它文件一起分發(fā)。詳情參見:http://msdn.microsoft.com/developer/downloads/files/40comupd.htm,請在你的新版本出爐之前仔細閱讀。

posted on 2008-05-25 15:49 wrh 閱讀(630) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導航

<2008年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

統(tǒng)計

常用鏈接

留言簿(19)

隨筆檔案

文章檔案

收藏夾

搜索

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久免费少妇高潮久久精品99| 亚洲国产精品精华液2区45| 亚洲伊人久久综合| 日韩视频一区二区| 一本色道久久综合亚洲精品不| 日韩视频免费在线观看| 日韩亚洲精品在线| 中文亚洲视频在线| 午夜精品www| 久久综合网络一区二区| 欧美极品一区二区三区| 国产精品女人网站| 136国产福利精品导航网址| 99re6热只有精品免费观看| 亚洲欧美日韩在线一区| 另类av一区二区| 日韩亚洲精品在线| 久久偷看各类wc女厕嘘嘘偷窃| 欧美国产专区| 国产午夜精品久久久久久久| 亚洲经典自拍| 欧美日韩精品在线播放| 欧美日韩在线免费| 黄色在线一区| 午夜在线一区二区| 亚洲人www| 亚洲欧美国产高清va在线播| 美乳少妇欧美精品| 国产亚洲欧美另类中文| 宅男精品导航| 亚洲国产91色在线| 久久国产婷婷国产香蕉| 国产精品国产福利国产秒拍| 亚洲日本va午夜在线电影 | 欧美午夜精品一区| 黑丝一区二区| 香蕉久久a毛片| 99国产精品| 欧美成人久久| 亚洲黄页一区| 欧美sm视频| 久久久久久久999| 国产亚洲精品一区二区| 亚洲欧美日韩国产另类专区| 亚洲电影专区| 久久先锋影音av| 国产真实乱偷精品视频免| 亚洲女性裸体视频| 一本久久精品一区二区| 欧美精品色网| 一本色道久久88综合日韩精品| 欧美国产一区二区在线观看| 久久人人97超碰精品888| 一区二区亚洲欧洲国产日韩| 久久久噜噜噜久久久| 性欧美办公室18xxxxhd| 国产亚洲在线观看| 久久频这里精品99香蕉| 久久蜜桃精品| 亚洲久久一区| 一区二区久久| 国产乱子伦一区二区三区国色天香| 午夜精品福利在线观看| 亚洲影院在线| 国产日韩欧美中文| 久久综合五月天婷婷伊人| 久久久xxx| 亚洲精品午夜精品| av不卡在线看| 国产区亚洲区欧美区| 久久久国产成人精品| 久久久久久久999精品视频| 亚洲国产免费| 夜夜嗨av一区二区三区免费区| 国产精品理论片| 久久综合一区二区| 欧美日本二区| 久久久久一区二区三区四区| 欧美高清免费| 久久se精品一区精品二区| 亚洲成人中文| 欧美巨乳波霸| 欧美在线不卡视频| 鲁大师影院一区二区三区| 亚洲深夜激情| 欧美在线三级| 一本色道久久| 久久久久99| 亚洲视频二区| 久久久久久久综合| 亚洲永久网站| 久久天堂av综合合色| 亚洲永久在线观看| 美日韩在线观看| 欧美在线精品免播放器视频| 欧美超级免费视 在线| 欧美一区二区精美| 欧美精品国产精品| 久热精品视频在线免费观看| 欧美偷拍另类| 欧美国产精品日韩| 国产午夜精品全部视频播放| 91久久极品少妇xxxxⅹ软件| 国产性做久久久久久| 99国产精品国产精品久久| 亚洲黄色影院| 久久视频一区| 久久青草欧美一区二区三区| 国产精品视频自拍| 99视频有精品| 日韩视频一区二区在线观看| 久久精品一级爱片| 欧美一区二区三区视频| 国产精品啊v在线| 亚洲日本视频| 亚洲精品国产精品久久清纯直播| 久久久精品久久久久| 久久精品国产精品亚洲| 欧美日韩一区三区四区| 亚洲区一区二区三区| 亚洲人成啪啪网站| 久久综合伊人77777尤物| 久久久www免费人成黑人精品| 国产精品久久久久久久久久久久久 | 欧美视频一区二区三区四区| 鲁大师影院一区二区三区| 国产欧美日韩精品丝袜高跟鞋| 夜夜爽www精品| 中文精品在线| 欧美三区美女| 亚洲伦理在线免费看| 99视频一区二区三区| 欧美日韩第一区| 99精品久久免费看蜜臀剧情介绍| 日韩视频二区| 欧美日韩亚洲三区| 亚洲网站在线播放| 欧美在线视频二区| 国内精品久久久久久| 久久精品水蜜桃av综合天堂| 免费成人你懂的| 亚洲精品美女久久久久| 欧美人成网站| 亚洲深夜福利视频| 久久精品国产亚洲a| 国产综合18久久久久久| 久久久亚洲综合| 亚洲免费观看在线观看| 欧美三级免费| 欧美亚洲视频在线观看| 久久精品国产欧美亚洲人人爽| 一区在线视频| 欧美激情网友自拍| 亚洲一区国产精品| 另类综合日韩欧美亚洲| 999亚洲国产精| 国产欧美日韩精品在线| 久久综合狠狠综合久久综青草 | 亚洲免费在线观看| 国模一区二区三区| 久久综合伊人77777麻豆| 亚洲日本电影| 久久激情视频久久| 最新高清无码专区| 国产精品老牛| 麻豆精品在线视频| 一本色道久久综合亚洲精品不卡| 欧美在线看片| 在线视频中文亚洲| 国产一区日韩一区| 欧美日韩国产成人在线免费| 午夜欧美精品久久久久久久| 亚洲第一级黄色片| 欧美一区二区在线视频| 亚洲欧洲在线一区| 国产欧美日韩在线| 欧美日韩国产一区| 久久九九有精品国产23| 一区二区三区高清在线| 欧美黄色免费| 久久久久久尹人网香蕉| 亚洲小说区图片区| 亚洲区欧美区| 亚洲第一精品电影| 国产一区二区三区免费不卡| 国产精品高清免费在线观看| 欧美电影免费| 久久精品盗摄| 午夜精品福利在线观看| 在线性视频日韩欧美| 欧美ab在线视频| 久久青草福利网站| 欧美自拍偷拍午夜视频| 亚洲一区三区电影在线观看| 亚洲国产日日夜夜| 激情六月婷婷综合| 国模大胆一区二区三区| 国产欧美高清| 国产精品亚洲综合一区在线观看 | 久久综合久久久久88|