日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Windows核心编程 第四章 进程(上)

發(fā)布時(shí)間:2025/6/17 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows核心编程 第四章 进程(上) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第4章 進(jìn) 程

? ? 本章介紹系統(tǒng)如何管理所有正在運(yùn)行的應(yīng)用程序。首先講述什么是進(jìn)程,以及系統(tǒng)如何創(chuàng)建進(jìn)程內(nèi)核對(duì)象,以便管理每個(gè)進(jìn)程。然后將說明如何使用相關(guān)的內(nèi)核對(duì)象來對(duì)進(jìn)程進(jìn)行操作。接著,要介紹進(jìn)程的各種不同的屬性,以及查詢和修改這些屬性所用的若干個(gè)函數(shù)。還要講述創(chuàng)建或生成系統(tǒng)中的輔助進(jìn)程所用的函數(shù)。當(dāng)然,如果不深入說明如何來結(jié)束進(jìn)程的運(yùn)行,那么這樣的介紹肯定是不完整的。現(xiàn)在就來介紹進(jìn)程的有關(guān)內(nèi)容。進(jìn)程通常被定義為一個(gè)正在運(yùn)行的程序的實(shí)例,它由兩個(gè)部分組成:
? 一個(gè)是操作系統(tǒng)用來管理進(jìn)程的內(nèi)核對(duì)象。內(nèi)核對(duì)象也是系統(tǒng)用來存放關(guān)于進(jìn)程的統(tǒng)計(jì)
信息的地方。
? 另一個(gè)是地址空間,它包含所有可執(zhí)行模塊或 D L L模塊的代碼和數(shù)據(jù)。它還包含動(dòng)態(tài)內(nèi)存分配的空間。如線程堆棧和堆分配空間。
? ? 進(jìn)程是不活潑的。若要使進(jìn)程完成某項(xiàng)操作,它必須擁有一個(gè)在它的環(huán)境中運(yùn)行的線程,該線程負(fù)責(zé)執(zhí)行包含在進(jìn)程的地址空間中的代碼。實(shí)際上,單個(gè)進(jìn)程可能包含若干個(gè)線程,所有這些線程都“同時(shí)”執(zhí)行進(jìn)程地址空間中的代碼。為此,每個(gè)線程都有它自己的一組C P U寄存器和它自己的堆棧。每個(gè)進(jìn)程至少擁有一個(gè)線程,來執(zhí)行進(jìn)程的地址空間中的代碼。如果沒有線程來執(zhí)行進(jìn)程的地址空間中的代碼,那么進(jìn)程就沒有存在的理由了,系統(tǒng)就將自動(dòng)撤消該進(jìn)程和它的地址空間。若要使所有這些線程都能運(yùn)行,操作系統(tǒng)就要為每個(gè)線程安排一定的 C P U時(shí)間。它通過以一種循環(huán)方式為線程提供時(shí)間片(稱為量程) ,造成一種假象,仿佛所有線程都是
同時(shí)運(yùn)行的一樣。圖4 - 1顯示了在單個(gè)C P U的計(jì)算機(jī)上是如何實(shí)現(xiàn)這種運(yùn)行方式的。如果計(jì)算機(jī)擁有多個(gè) C P U,那么操作系統(tǒng)就要使用復(fù)雜得多的算法來實(shí)現(xiàn) C P U上線程負(fù)載的平衡。
? ? 當(dāng)創(chuàng)建一個(gè)進(jìn)程時(shí),系統(tǒng)會(huì)自動(dòng)創(chuàng)建它的第一個(gè)線程,稱為主線程。然后,該線程可以創(chuàng)
建其他的線程,而這些線程又能創(chuàng)建更多的線程。

? ? Wi n d o w s 2 0 0 0 Micorsoft Windows 2000能夠在擁有多個(gè)C P U的計(jì)算機(jī)上運(yùn)行。 例如,我用來撰寫本書的計(jì)算機(jī)就包含兩個(gè)處理器。Windows 2000可以在每個(gè)C P U上運(yùn)行不同的線程,這樣,多個(gè)線程就真的在同時(shí)運(yùn)行了。Windows 2000的內(nèi)核能夠在這種類型的系統(tǒng)上進(jìn)行所有線程的管理和調(diào)度。不必在代碼中進(jìn)行任何特定的設(shè)置就能利用多處理器提供的各種優(yōu)點(diǎn)。
? ? Windows 98 Windows 98只能在單處理器計(jì)算機(jī)上運(yùn)行。即使計(jì)算機(jī)配有多個(gè)處理器,Wi n d o w s每次只能安排一個(gè)線程運(yùn)行,而其他的處理器則處于空閑狀態(tài)。

4.1 編寫第一個(gè)Wi n d o w s應(yīng)用程序

? ? Wi n d o w s支持兩種類型的應(yīng)用程序。一種是基于圖形用戶界面( G U I)的應(yīng)用程序,另一種是基于控制臺(tái)用戶界面(C U I)的應(yīng)用程序。基于G U I的應(yīng)用程序有一個(gè)圖形前端程序。它能創(chuàng)建窗口,擁有菜單,可以通過對(duì)話框與用戶打交道,并可使用所有的標(biāo)準(zhǔn)“ Wi n d o w s”組件。Wi n d o w s配備的所有應(yīng)用程序附件(如N o t e p a d、C a l c u l a t o r和Wo r d P a d) ,幾乎都是基于G U I的應(yīng)用程序。基于控制臺(tái)的應(yīng)用程序?qū)儆谖谋静僮鞯膽?yīng)用程序。它們通常不能用于創(chuàng)建窗口或處理消息,并且它們不需要圖形用戶界面。雖然基于 C U I的應(yīng)用程序包含在屏幕上的窗口中,但是窗口只包含文本。命令外殼程序 C M D . E X E(用于Windows 2000)和COMMAND.COM (用于Windows 98)都是典型的基于C U I的應(yīng)用程序。
? ? 這兩種類型的應(yīng)用程序之間的界限是非常模糊的。可以創(chuàng)建用于顯示對(duì)話框的 C U I應(yīng)用程序。例如,命令外殼程序可能擁有一個(gè)特殊的命令,使它能夠顯示一個(gè)圖形對(duì)話框,在這個(gè)對(duì)話框中,可以選定你要執(zhí)行的命令,而不必記住該外殼程序支持的各個(gè)不同的命令。也可以創(chuàng)建一個(gè)基于G U I的應(yīng)用程序,它能將文本字符串輸出到一個(gè)控制臺(tái)窗口。我常常創(chuàng)建用于建立控制臺(tái)窗口的G U I應(yīng)用程序,在這個(gè)窗口中,我可以查看應(yīng)用程序執(zhí)行時(shí)的調(diào)試信息。當(dāng)然你也可以在應(yīng)用程序中使用圖形用戶界面,而不是老式的字符界面,因?yàn)樽址缑媸褂闷饋聿惶奖恪?br /> ? ? 當(dāng)使用Microsoft Visual C++來創(chuàng)建應(yīng)用程序時(shí),這種集成式環(huán)境安裝了許多不同的鏈接程序開關(guān),這樣,鏈接程序就可以將相應(yīng)的子系統(tǒng)嵌入產(chǎn)生的可執(zhí)行程序。用于 C U I應(yīng)用程序的鏈接程序開關(guān)是 / S U B S Y S T E M : C O N D O L E,而用于 G U I應(yīng)用程序的鏈接程序開關(guān)是S U B S Y S T E M : W I N D O W S。當(dāng)用戶運(yùn)行一個(gè)應(yīng)用程序時(shí),操作系統(tǒng)的加載程序就會(huì)查看可執(zhí)行圖形程序的標(biāo)題,并抓取該子系統(tǒng)的值。如果該值指明一個(gè) C U I應(yīng)用程序,那么加載程序就會(huì)自動(dòng)保證為該應(yīng)用程序創(chuàng)建文本控制臺(tái)窗口。
? ? 如果該值指明這是個(gè)G U I應(yīng)用程序,那么加載程序不創(chuàng)建控制臺(tái)窗口,而只是加載應(yīng)用程序。一旦應(yīng)用程序啟動(dòng)運(yùn)行,操作系統(tǒng)就不再考慮應(yīng)用程序擁有什么類型的用戶界面。Wi n d o w s應(yīng)用程序必須擁有一個(gè)在應(yīng)用程序啟動(dòng)運(yùn)行時(shí)調(diào)用的進(jìn)入點(diǎn)函數(shù)。可以使用的進(jìn)入點(diǎn)函數(shù)有4個(gè):


? ? 操作系統(tǒng)實(shí)際上并不調(diào)用你編寫的進(jìn)入點(diǎn)函數(shù)。它調(diào)用的是 C / C + +運(yùn)行期啟動(dòng)函數(shù)。該函數(shù)負(fù)責(zé)對(duì)C / C + +運(yùn)行期庫(kù)進(jìn)行初始化,這樣,就可以調(diào)用m a l l o c和f r e e之類的函數(shù)。它還能夠確保已經(jīng)聲明的任何全局對(duì)象和靜態(tài)C + +對(duì)象能夠在代碼執(zhí)行以前正確地創(chuàng)建。下面說明源代碼中可以實(shí)現(xiàn)哪個(gè)進(jìn)入點(diǎn)以及何時(shí)使用該進(jìn)入點(diǎn)(見表4 - 1 )。

? ? 鏈接程序負(fù)責(zé)在它連接可執(zhí)行文件時(shí)選擇相應(yīng)的 C / C + +運(yùn)行期啟動(dòng)函數(shù)。如果設(shè)定了/ S U B S Y S T E M : W I N D O W S鏈接程序開關(guān),那么該鏈接程序期望找到一個(gè) Wi n M a i n或w Wi n m a i n函數(shù)。如果這兩個(gè)函數(shù)都不存在,鏈接程序便返回一個(gè)“未轉(zhuǎn)換的外部符號(hào)”的錯(cuò)誤消息。否則,它可以分別選擇Wi n M a i n C RT S t a r t u p函數(shù)或w Wi n M a i n C RT S t a r t u p函數(shù)。
?同樣,如果設(shè)定了/ S U B S Y S T E M : C O N S O L E鏈接程序開關(guān),那么該鏈接程序便期望找到m a i n或w m a i n函數(shù),并且可以分別選擇 m a i n C RT S t a r t u p函數(shù)或w m a i n C RT S t a r t u p函數(shù)。
? ? 同樣,如果m a i n或w m a i n都不存在,那么鏈接程序返回一條“未轉(zhuǎn)換外部符號(hào)”的消息。 ? ? 但是,人們很少知道這樣一個(gè)情況,即可以從應(yīng)用程序中全部刪除 / S U B S Y S T E M鏈接程序開關(guān)。當(dāng)這樣做的時(shí)候,鏈接程序能夠自動(dòng)確定應(yīng)用程序應(yīng)該連接到哪個(gè)子系統(tǒng)。當(dāng)進(jìn)行鏈接時(shí),鏈接程序要查看代碼中存在 4個(gè)函數(shù)(Wi n M a i n、w Wi n M a i n、m a i n或w m a i n)中的哪一個(gè)。然后確定可執(zhí)行程序應(yīng)該是哪一個(gè)子系統(tǒng),并且確定可執(zhí)行程序中應(yīng)該嵌入哪個(gè) C / C + +啟動(dòng)函數(shù)。 ? ? Wi n d o w s / Visual C++編程新手常犯的錯(cuò)誤之一是,當(dāng)創(chuàng)建新的應(yīng)用程序時(shí),不小心選擇了錯(cuò)誤的應(yīng)用程序類型。例如,編程員可能創(chuàng)建一個(gè)新的 Wi n 3 2應(yīng)用程序項(xiàng)目,但是創(chuàng)建了一個(gè)進(jìn)入點(diǎn)函數(shù)m a i n。當(dāng)創(chuàng)建應(yīng)用程序時(shí),編程員會(huì)看到一個(gè)鏈接程序錯(cuò)誤消息,因?yàn)?w i n 3 2應(yīng)用程序項(xiàng)目設(shè)置了/ S U B S Y S T E M : W I N D O W S鏈接程序開關(guān),但是不存在Wi n M a i n或w Wi n M a i n函數(shù)。這時(shí),編程員可以有4個(gè)選擇:
? ? ? 將m a i n函數(shù)改為Wi n M a i n。通常這不是最佳的選擇,因?yàn)榫幊虇T可能想要?jiǎng)?chuàng)建一個(gè)控制臺(tái)應(yīng)用程序。
? ? ? 用Visual C++創(chuàng)建一個(gè)新的Win32 控制臺(tái)應(yīng)用程序,并將現(xiàn)有的源代碼添加給新應(yīng)用程序項(xiàng)目。這個(gè)選項(xiàng)冗長(zhǎng)而乏味,因?yàn)樗孟袷菑念^開始創(chuàng)建應(yīng)用程序,而且必須刪除原始的應(yīng)用程序文件。
? ? ? 單擊Project Settings對(duì)話框的 L i n k選項(xiàng)卡,將 / S U B S Y S T E M : W I N D O W S開關(guān)改為/ S U B S Y S T E M : C O N S O L E。這是解決問題的一種比較容易的方法,很少有人知道他們只需要進(jìn)行這項(xiàng)操作就行了。
? ? ? 單擊Project Settings對(duì)話框的L i n k選項(xiàng)卡,然后全部刪除/ S U B S Y S T E M : W I N D O W S開關(guān)。這是我喜歡選擇的方法,因?yàn)樗峁┝俗畲蟮撵`活性。現(xiàn)在,連接程序?qū)⒏鶕?jù)源代碼中實(shí)現(xiàn)的函數(shù)進(jìn)行正確的操作。

? ? 當(dāng)用Visual C++的Developer Studio創(chuàng)建新Wi n 3 2應(yīng)用程序或Wi n 3 2控制臺(tái)應(yīng)用程序項(xiàng)目時(shí),我不知道為什么這沒有成為默認(rèn)設(shè)置。
? ? 所有的C / C + +運(yùn)行期啟動(dòng)函數(shù)的作用基本上都是相同的。它們的差別在于,它們究竟是處理A N S I字符串還是U n i c o d e字符串,以及它們?cè)趯?duì)C運(yùn)行期庫(kù)進(jìn)行初始化后它們調(diào)用哪個(gè)進(jìn)入點(diǎn)函數(shù)。Visual C++配有C運(yùn)行期庫(kù)的源代碼。可以在CR t0.c文件中找到這4個(gè)啟動(dòng)函數(shù)的代碼。現(xiàn)在將啟動(dòng)函數(shù)的功能歸納如下:
? ? ? 檢索指向新進(jìn)程的完整命令行的指針。
? ? ? 檢索指向新進(jìn)程的環(huán)境變量的指針。
? ? ? 對(duì)C / C + +運(yùn)行期的全局變量進(jìn)行初始化。如果包含了 S t d L i b . h文件,代碼就能訪問這些變量。表4 - 1列出了這些變量。
? ? ? 對(duì)C運(yùn)行期內(nèi)存單元分配函數(shù)(m a l l o c和c a l l o c)和其他低層輸入/輸出例程使用的內(nèi)存棧進(jìn)行初始化。
? ? ? 為所有全局和靜態(tài)C + +類對(duì)象調(diào)用構(gòu)造函數(shù)。當(dāng)所有這些初始化操作完成后,C / C + +啟動(dòng)函數(shù)就調(diào)用應(yīng)用程序的進(jìn)入點(diǎn)函數(shù)。如果編寫了一個(gè)w Wi n M a i n函數(shù),它將以下面的形式被調(diào)用:

? ? 當(dāng)進(jìn)入點(diǎn)函數(shù)返回時(shí),啟動(dòng)函數(shù)便調(diào)用 C運(yùn)行期的e x i t函數(shù),將返回值(n M a i n R e t Va l)傳遞給它。E x i t函數(shù)負(fù)責(zé)下面的操作:
? ? ? 調(diào)用由_ o n e x i t函數(shù)的調(diào)用而注冊(cè)的任何函數(shù)。
? ? ? 為所有全局的和靜態(tài)的C + +類對(duì)象調(diào)用析構(gòu)函數(shù)。
? ? ? 調(diào)用操作系統(tǒng)的E x i t P r o c e s s函數(shù),將n M a i n R e t Va l傳遞給它。這使得該操作系統(tǒng)能夠撤消進(jìn)程并設(shè)置它的e x i t代碼。
? ? 表4 - 2顯示了程序能夠使用的C / C + +運(yùn)行期全局變量。

4.1.1 進(jìn)程的實(shí)例句柄

? ? 加載到進(jìn)程地址空間的每個(gè)可執(zhí)行文件或 D L L文件均被賦予一個(gè)獨(dú)一無二的實(shí)例句柄。可
執(zhí)行文件的實(shí)例作為( w ) Wi n M a i n的第一個(gè)參數(shù)h i n s t E x e來傳遞。對(duì)于加載資源的函數(shù)調(diào)用來說,
通常都需要該句柄的值。例如,若要從可執(zhí)行文件的映象來加載圖標(biāo)資源,需要調(diào)用下面這個(gè)
函數(shù):

? ? L o a d I c o n的第一個(gè)參數(shù)用于指明哪個(gè)文件(可執(zhí)行文件或D L L文件)包含你想加載的資源。許多應(yīng)用程序在全局變量中保存( w ) Wi n M a i n的h i n s t E x e參數(shù),這樣,它就很容易被所有可執(zhí)行文件的代碼訪問。
? ? Platform SDK文檔中說,有些函數(shù)需要H M O D U L E類型的一個(gè)參數(shù)。它的例子是下面所示
的G e t M o d u l e F i l e N a m e函數(shù):

? ? 注意 實(shí)際情況說明,H M O D U L E與H I N S TA N C E是完全相同的對(duì)象。如果函數(shù)的文檔指明需要一個(gè)H M O D U L E,那么可以傳遞一個(gè)H I N S TA N C E,反過來,如果需要一個(gè)H I N S TA N C E,也可以傳遞一個(gè)H M O D U L E。之所以存在兩個(gè)數(shù)據(jù)類型,原因是在1 6位Wi n d o w s中,H M O D U L E和H I N S TA N C E用于標(biāo)識(shí)不同的東西。 ? ? ( w ) Wi n M a i n的h i n s t E x e參數(shù)的實(shí)際值是系統(tǒng)將可執(zhí)行文件的映象加載到進(jìn)程的地址空間時(shí)使用的基本地址空間。例如,如果系統(tǒng)打開了可執(zhí)行文件并且將它的內(nèi)容加載到地址0 x 0 0 4 0 0 0 0 0中,那么( w ) Wi n M a i n的h i n s t E x e參數(shù)的值就是0 x 0 0 4 0 0 0 0 0。 ? ? 可執(zhí)行文件的映像加載到的基地址是由鏈接程序決定的。不同的鏈接程序可以使用不同的默認(rèn)基地址。Visual C++鏈接程序使用的默認(rèn)基地址是0 x 0 0 4 0 0 0 0 0,因?yàn)檫@是在運(yùn)行Wi n d o w s9 8時(shí)可執(zhí)行文件的映象可以加載到的最低地址。可以改變應(yīng)用程序加載到的基地址,方法是使用M i c r o s o f t的鏈接程序中的/ B A S E : a d d r e s s鏈接程序開關(guān)。
? ? 如果你想在Wi n d o w s上加載的可執(zhí)行文件的基地址小于0 x 0 0 4 0 0 0 0 0,那么Windows 98加載程序必須將可執(zhí)行文件重新加載到另一個(gè)地址。這會(huì)增加加載應(yīng)用程序所需的時(shí)間,不過,這樣一來,至少該應(yīng)用程序能夠運(yùn)行。如果開發(fā)的應(yīng)用程序?qū)⒁瑫r(shí)在 Windows 98和Wi n d o w s2 0 0 0上運(yùn)行,應(yīng)該確保應(yīng)用程序的基地址是0 x 0 0 4 0 0 0 0 0或者大于這個(gè)地址。
? ? 下面的G e t M o d u l e H a n d l e函數(shù)返回可執(zhí)行文件或D L L文件加載到進(jìn)程的地址空間時(shí)所用的句柄/基地址:
? ?? ? ? 當(dāng)調(diào)用該函數(shù)時(shí),你傳遞一個(gè)以 0結(jié)尾的字符串,用于設(shè)定加載到調(diào)用進(jìn)程的地址空間的可執(zhí)行文件或 D L L文件的名字。如果系統(tǒng)找到了指定的可執(zhí)行文件或 D L L文件名,G e t M o d u l e H a n d l e便返回該可執(zhí)行文件或D L L文件映象加載到的基地址。如果系統(tǒng)沒有找到該文件,則返回 N U L L。也可以調(diào)用 G e t M o d u l e H a n d l e,為 p s z M o d u l e參數(shù)傳遞 N U L L,G e t M o d u l e H a n d l e返回調(diào)用的可執(zhí)行文件的基地址。這正是 C運(yùn)行期啟動(dòng)代碼調(diào)用 ( w ) Wi n M a i n函數(shù)時(shí)該代碼執(zhí)行的操作。 ? ? 請(qǐng)記住G e t M o d u l e H a n d l e函數(shù)的兩個(gè)重要特性。首先,它只查看調(diào)用進(jìn)程的地址空間。如果調(diào)用進(jìn)程不使用常用的對(duì)話框函數(shù),那么調(diào)用G e t M o d u l e H a n d l e并為它傳遞“C o m D l g 3 2”后,就會(huì)返回 N U L L,盡管 C o m D l g 3 2 . d l l可能加載到了其他進(jìn)程的地址空間。第二,調(diào)用G e t M o d u l e H a n d l e并傳遞N U L L值,就會(huì)返回進(jìn)程的地址空間中可執(zhí)行文件的基地址。因此,即使通過包含在D L L中的代碼來調(diào)用(N U L L) ,返回的值也是可執(zhí)行文件的基地址,而不是D L L文件的基地址。

4.1.2 進(jìn)程的前一個(gè)實(shí)例句柄

? ? 如前所述,C / C + +運(yùn)行期啟動(dòng)代碼總是將N U L L傳遞給( w ) Wi n M a i n的h i n s t E x e P r e v參數(shù)。該參數(shù)用在1 6位Wi n d o w s中,并且保留了( w ) Wi n M a i n的一個(gè)參數(shù),目的僅僅是為了能夠容易地轉(zhuǎn)用1 6位Wi n d o w s應(yīng)用程序。決不應(yīng)該在代碼中引用該參數(shù)。由于這個(gè)原因,我總是像下面這樣編寫( w ) Wi n M a i n函數(shù):


4.1.3 進(jìn)程的命令行

? ? 當(dāng)一個(gè)新進(jìn)程創(chuàng)建時(shí),它要傳遞一個(gè)命令行。該命令行幾乎永遠(yuǎn)不會(huì)是空的,至少用于創(chuàng)建新進(jìn)程的可執(zhí)行文件的名字是命令行上的第一個(gè)標(biāo)記。但是在后面介紹 C r e a t e P r o c e s s函數(shù)時(shí)我們將會(huì)看到,進(jìn)程能夠接收由單個(gè)字符組成的命令行,即字符串結(jié)尾處的零。當(dāng) C運(yùn)行期的啟動(dòng)代碼開始運(yùn)行的時(shí)候,它要檢索進(jìn)程的命令行,跳過可執(zhí)行文件的名字,并將指向命令行其余部分的指針傳遞給Wi n M a i n的p s z C m d L i n e參數(shù)。值得注意的是,p s z C m d L i n e參數(shù)總是指向一個(gè)A N S I字符串。但是,如果將Wi n M a i n改為w Wi n M a i n,就能夠訪問進(jìn)程的U n i c o d e版本命令行。
? ? 應(yīng)用程序可以按照它選擇的方法來分析和轉(zhuǎn)換命令行字符串。實(shí)際上可以寫入 p s z C m d L i n e參數(shù)指向的內(nèi)存緩存,但是在任何情況下都不應(yīng)該寫到緩存的外面去。我總是將它視為只讀緩存。如果我想修改命令行,首先我要將命令行拷貝到應(yīng)用程序的本地緩存中,然后再修改本地緩存。
? ? 也可以獲得一個(gè)指向進(jìn)程的完整命令行的指針,方法是調(diào)用G e t C o m m a n d L i n e函數(shù):
? ? PTSTR GetCommandLine(); ? ? 該函數(shù)返回一個(gè)指向包含完整命令行的緩存的指針,該命令行包括執(zhí)行文件的完整路徑名。
? ? 許多應(yīng)用程序常常擁有轉(zhuǎn)換成它的各個(gè)標(biāo)記的命令行。使用全局性 _ _ a rg c(或_ _ w a rg v)變量,應(yīng)用程序就能訪問命令行的各個(gè)組成部分。下面這個(gè)函數(shù) C o m m a n d L i n e To A rg v W將U n i c o d e字符串分割成它的各個(gè)標(biāo)記:
? ? PWSTR CommandLineToArgvW(PWSTR pszCmdLine, int * pNumArgs); ? ? 正如該函數(shù)名的結(jié)尾處的 W所暗示的那樣,該函數(shù)只存在于 U n i c o d e版本中(W是英文單詞‘Wi d e’的縮寫) 。第一個(gè)參數(shù)p s z C m d L i n e指向一個(gè)命令行字符串。這通常是較早時(shí)調(diào)用G e t C o m m a n d L i n e W而返回的值。P N u m A rg s參數(shù)是個(gè)整數(shù)地址,該整數(shù)被設(shè)置為命令行中的參數(shù)的數(shù)目。 ? ? C o m m a n d L i n e To A rg v W將地址返回給一個(gè)U n i c o d e字符串指針的數(shù)組。C o m m a n e L i n e To A rg v W負(fù)責(zé)在內(nèi)部分配內(nèi)存。大多數(shù)應(yīng)用程序不釋放該內(nèi)存,它們?cè)谶M(jìn)程運(yùn)行終止時(shí)依靠操作系統(tǒng)來釋放內(nèi)存。這是完全可行的。但是如果想要自己來釋放內(nèi)存,正確的方法是像下面這樣調(diào)用H e a p F r e e函數(shù):

4.1.4 進(jìn)程的環(huán)境變量

? ? 每個(gè)進(jìn)程都有一個(gè)與它相關(guān)的環(huán)境塊。環(huán)境塊是進(jìn)程的地址空間中分配的一個(gè)內(nèi)存塊。每
個(gè)環(huán)境塊都包含一組字符串,其形式如下:

? ? 每個(gè)字符串的第一部分是環(huán)境變量的名字,后跟一個(gè)等號(hào),等號(hào)后面是要賦予變量的值。環(huán)境塊中的所有字符串都必須按環(huán)境變量名的字母順序進(jìn)行排序。 ? ? 由于等號(hào)用于將變量名與變量的值分開,因此等號(hào)不能是變量名的一部分。另外,變量中的空格是有意義的。例如,如果聲明下面兩個(gè)變量,然后將 X Y Z的值與A B C的值進(jìn)行比較,那么系統(tǒng)將報(bào)告稱,這兩個(gè)變量是不同的,因?yàn)榫o靠著等號(hào)的前面或后面的任何空格均作為比較時(shí)的條件被考慮在內(nèi)。
XYZ = Windows (Notice the space after the equal sign.) ABC = Windows 例如,如果將下面兩個(gè)字符串添加給環(huán)境塊,后面帶有空格的環(huán)境變量 X Y Z包含H o m e,而沒有空格的環(huán)境變量X Y Z則包含Wo r k。
? ? XYZ = Home(Notice the sapce before the equal sign.) ? ? XYZ = Word ? ? 最后,必須將一個(gè)0字符置于所有環(huán)境變量的結(jié)尾處,以表示環(huán)境塊的結(jié)束。
? ? Wi n d o w s 9 8 若要為 Windows 98創(chuàng)建一組初始環(huán)境變量,必須修改系統(tǒng)的A u t o E x e c . b a t文件,將一系列S E T行放入該文件。每個(gè)S E T行都必須采用下面的形式: ? ? SET VarName = VarValue ? ? 當(dāng)重新引導(dǎo)系統(tǒng)時(shí),A u t o E x e c . b a t文件的內(nèi)容被分析,設(shè)置的任何環(huán)境變量均可供在Windows 98會(huì)話期間啟動(dòng)的任何進(jìn)程使用。
? ? Windows 2000 ?當(dāng)用戶登錄到Windows 2000中時(shí),系統(tǒng)創(chuàng)建一個(gè)外殼進(jìn)程并將一組環(huán)境字符串與它相關(guān)聯(lián)。通過查看注冊(cè)表中的兩個(gè)關(guān)鍵字,系統(tǒng)可以獲得一組初始環(huán)境字符串。
? ? 第一個(gè)關(guān)鍵字包含一個(gè)適用于系統(tǒng)的所有環(huán)境變量的列表:

? ? 第二個(gè)關(guān)鍵字包含適用于當(dāng)前登錄的用戶的所有環(huán)境變量的列表:
? ? HKEY_CURRENT_USER\Envirment ? ? 用戶可以對(duì)這些項(xiàng)目進(jìn)行增加、刪除或修改,方法是選定控制面板的S y s t e m小應(yīng)用程序,單擊A d v a n c e d選項(xiàng)卡,再單擊Environment Va r i a b l e s按鈕,打開圖4 - 2所示的對(duì)話框:


? ? 只有擁有管理員權(quán)限的用戶才能修改系統(tǒng)變量列表中的變量。

????應(yīng)用程序也可以使用各種注冊(cè)表函數(shù)來修改這些注冊(cè)表項(xiàng)目。但是,若要使這些

修改在所有應(yīng)用程序中生效,用戶必須退出系統(tǒng),然后再次登錄。有些應(yīng)用程序,如

E x p l o r e rTask ManagerControl Panel等 , 在 它 們 的 主 窗 口 收 到 W M _

S E T T I N G C H A N G E消息時(shí),用新注冊(cè)表項(xiàng)目來更新它們的環(huán)境塊。例如,如果要更新

注冊(cè)表項(xiàng)目,并且想讓有關(guān)的應(yīng)用程序更新它們的環(huán)境塊,可以調(diào)用下面的代碼:

? ? SendMessage(HWND_BROADCAST ,WM_SETTINGCHANGE ,0 ,(LPARAM)TEXT(“Environment”));

????通常,子進(jìn)程可以繼承一組與父進(jìn)程相同的環(huán)境變量。但是,父進(jìn)程能夠控制子進(jìn)程繼承什么環(huán)境變量,后面介紹C r e a t e P r o c e s s函數(shù)時(shí)就會(huì)看到這個(gè)情況。所謂繼承,指的是子進(jìn)程獲得它自己的父進(jìn)程的環(huán)境塊拷貝,子進(jìn)程與父進(jìn)程并不共享相同的環(huán)境塊。這意味著子進(jìn)程能夠添加、刪除或修改它的環(huán)境塊中的變量,而這個(gè)變化在父進(jìn)程的環(huán)境塊中卻得不到反映。

????應(yīng)用程序通常使用環(huán)境變量來使用戶能夠調(diào)整它的行為特性。用戶創(chuàng)建一個(gè)環(huán)境變量并對(duì)它進(jìn)行初始化。然后,當(dāng)用戶啟動(dòng)應(yīng)用程序運(yùn)行時(shí),該應(yīng)用程序要查看環(huán)境塊,找出該變量。如果找到了變量,它就分析變量的值,調(diào)整自己的行為特性。

????環(huán)境變量存在的問題是,用戶難以設(shè)置或理解這些變量。用戶必須正確地拼寫變量的名字,而且必須知道變量值期望的準(zhǔn)確句法。另一方面,大多數(shù)圖形應(yīng)用程序允許用戶使用對(duì)話框來調(diào)整應(yīng)用程序的行為特性。這種方法對(duì)用戶來說更加友好。

???如果仍然想要使用環(huán)境變量,那么有幾個(gè)函數(shù)可供應(yīng)用程序調(diào)用。使用 G e t E n v i r o n m e n tVa r i a b l e函數(shù),就能夠確定某個(gè)環(huán)境變量是否存在以及它的值:

?

DWORD GetEnvironmentVariableW(

????_In_opt_ LPCWSTR lpName,

????_Out_writes_to_opt_(nSize, return + 1) LPWSTR lpBuffer,

????_In_ DWORD nSize

????);

TCHAR tcEnviromentVar[MAX_PATH] = {0};

GetEnvironmentVariable(_TEXT("TEMP") ,tcEnviromentVar ,MAX_PATH);

????當(dāng)調(diào)用G e t E n v i r o n m e n t Va r i a b l e時(shí),p s z N a m e指向需要的變量名,p s z Va l u e指向用于存放變量值的緩存,c c h Va l u e用于指明緩存的大小(用字符數(shù)來表示)。該函數(shù)可以返回拷貝到緩存的字符數(shù),如果在環(huán)境中找不到該變量名,也可以返回 0

許多字符串包含了里面可取代的字符串。例如,我在注冊(cè)表中的某個(gè)地方找到了下面的字符串:

%USERPROFILE%\My Documents

百分?jǐn)?shù)符號(hào)之間的部分表示一個(gè)可取代的字符串。在這個(gè)例子中,環(huán)境變量的值

USERPROFILE應(yīng)該被放入該字符串中。

由于這種類型的字符串替換是很常用的,因此Wi n d o w s提供了E x p a n d E n v i r o n m e n t S t r i n g s函數(shù):

DWORD ExpandEnvironmentStringsW(

????_In_ LPCWSTR lpSrc,

????_Out_writes_to_opt_(nSize, return) LPWSTR lpDst,

????_In_ DWORD nSize

????);

TCHAR tcFullEnviromentVar[MAX_PATH] = {0};

ExpandEnvironmentStrings(_TEXT("%TEMP%\\A") ,tcFullEnviromentVar ,MAX_PATH);

當(dāng)調(diào)用該函數(shù)時(shí),p s z S r c參數(shù)是包含可替換的環(huán)境變量字符串的這個(gè)字符串的地址。p s z D s t參數(shù)是接收已展開字符串的緩存的地址,n S i z e參數(shù)是該緩存的最大值(用字符數(shù)來表示)。

最后,可以使用S e t E n v i r o n m e n t Va r i a b l e函數(shù)來添加變量、刪除變量或者修改變量的值:

BOOL SetEnvironmentVariableW(

????_In_ LPCWSTR lpName,

????_In_opt_ LPCWSTR lpValue

????);

SetEnvironmentVariable(_TEXT("TTT") ,_TEXT("C:"));

該函數(shù)用于將p s z N a m e參數(shù)標(biāo)識(shí)的變量設(shè)置為p s z Va l u e參數(shù)標(biāo)識(shí)的值。如果帶有指定名字的變量已經(jīng)存在,S e t E n v i r o n m e n t Va r i a b l e就修改該值。如果指定的變量不存在,便添加該變量,如果p s z Va l u eN U L L,便從環(huán)境塊中刪除該變量。

應(yīng)該始終使用這些函數(shù)來操作進(jìn)程的環(huán)境塊。前面講過,環(huán)境塊中的字符串必須按變量名的字母順序來存放,這樣, S e t E n v i r o n m e n t Va r i a b l e就會(huì)很容易地找到它們。 S e t E n v i r o n m e n tVa r i a b l e函數(shù)具有足夠的智能,使環(huán)境變量保持有序排列。

4.1.5 進(jìn)程的親緣性

一般來說,進(jìn)程中的線程可以在主計(jì)算機(jī)中的任何一個(gè) C P U上執(zhí)行。但是一個(gè)進(jìn)程的線程可能被強(qiáng)制在可用C P U的子集上運(yùn)行。這稱為進(jìn)程的親緣性,將在第 7章詳細(xì)介紹。子進(jìn)程繼承了父進(jìn)程的親緣性。

4.1.6 進(jìn)程的錯(cuò)誤模式

????與每個(gè)進(jìn)程相關(guān)聯(lián)的是一組標(biāo)志,用于告訴系統(tǒng),進(jìn)程對(duì)嚴(yán)重的錯(cuò)誤應(yīng)該如何作出反映,

這包括磁盤介質(zhì)故障、未處理的異常情況、文件查找失敗和數(shù)據(jù)沒有對(duì)齊等。進(jìn)程可以告訴系統(tǒng)如何處理每一種錯(cuò)誤。方法是調(diào)用S e t E r r o r M o d e函數(shù):

??????????????????????UINT ?SetErrorMode(UINT fuErrorMode);

????f u E r r o r M o d e參數(shù)是下表的任何標(biāo)志按位用O R連接在一起的組合。

?

????默認(rèn)情況下,子進(jìn)程繼承父進(jìn)程的錯(cuò)誤模式標(biāo)志。換句話說,如果一個(gè)進(jìn)程的

S E M _ N O G P FA U LT E R R O R B O X標(biāo)志已經(jīng)打開,并且生成了一個(gè)子進(jìn)程,該子進(jìn)程也擁有這個(gè)打開的標(biāo)志。但是,子進(jìn)程并沒有得到這一情況的通知,它可能尚未編寫以便處理 G P故障的錯(cuò)誤。如果G P故障發(fā)生在子進(jìn)程的某個(gè)線程中,該子進(jìn)程就會(huì)終止運(yùn)行,而不通知用戶。父進(jìn) 程 可 以 防 止 子 進(jìn) 程 繼 承 它 的 錯(cuò) 誤 模 式 , 方 法 是 在 調(diào) 用 C r e a t e P r o c e s s 時(shí) 設(shè) 定C R E AT E _ D E FA U LT _ E R R O R _ M O D E標(biāo)志(本章后面部分的內(nèi)容將要介紹C r e a t e P r o c e s s函數(shù))

4.1.7 進(jìn)程的當(dāng)前驅(qū)動(dòng)器和目錄

????當(dāng)不提供全路徑名時(shí),Wi n d o w s的各個(gè)函數(shù)就會(huì)在當(dāng)前驅(qū)動(dòng)器的當(dāng)前目錄中查找文件和目錄。例如,如果進(jìn)程中的一個(gè)線程調(diào)用 C r e a t e F i l e來打開一個(gè)文件(不設(shè)定全路徑名) ,那么系統(tǒng)就會(huì)在當(dāng)前驅(qū)動(dòng)器和目錄中查找該文件。

????系統(tǒng)將在內(nèi)部保持對(duì)進(jìn)程的當(dāng)前驅(qū)動(dòng)器和目錄的跟蹤。 由于該信息是按每個(gè)進(jìn)程來維護(hù)的,因此改變當(dāng)前驅(qū)動(dòng)器或目錄的進(jìn)程中的線程,就可以為該進(jìn)程中的所有線程改變這些信息。

通過調(diào)用下面兩個(gè)函數(shù),線程能夠獲得和設(shè)置它的進(jìn)程的當(dāng)前驅(qū)動(dòng)器和目錄:

?

DWORD GetCurrentDirectoryW(

????_In_ DWORD nBufferLength,

????_Out_writes_to_opt_(nBufferLength, return + 1) LPWSTR lpBuffer

????);

TCHAR tcLocalAppPath[MAX_PATH] = {0};

GetCurrentDirectory(MAX_PATH ,tcLocalAppPath);

BOOL SetCurrentDirectoryW(

????_In_ LPCWSTR lpPathName

????);

SetCurrentDirectory(_TEXT("G:\\inetpub"));

4.1.8 進(jìn)程的當(dāng)前目錄

? ? 系統(tǒng)將對(duì)進(jìn)程的當(dāng)前驅(qū)動(dòng)器和目錄保持跟蹤,但是它不跟蹤每個(gè)驅(qū)動(dòng)器的當(dāng)前目錄。不過,有些操作系統(tǒng)支持對(duì)多個(gè)驅(qū)動(dòng)器的當(dāng)前目錄的處理。這種支持是通過進(jìn)程的環(huán)境字符串來提供的。例如,進(jìn)程能夠擁有下面所示的兩個(gè)環(huán)境變量:

=C:=C:\Utility\Bin

=D:=D:\Program FIles

? ? 這些變量表示驅(qū)動(dòng)器C的進(jìn)程的當(dāng)前目錄是\ U t i l i t y \ B i n,并且指明驅(qū)動(dòng)器D的進(jìn)程的當(dāng)前目錄是\Program Files

如果調(diào)用一個(gè)函數(shù),傳遞一個(gè)驅(qū)動(dòng)器全限定名,以表示一個(gè)驅(qū)動(dòng)器不是當(dāng)前驅(qū)動(dòng)器,那么系統(tǒng)就會(huì)查看進(jìn)程的環(huán)境塊,找出與指定驅(qū)動(dòng)器名相關(guān)的變量。如果該驅(qū)動(dòng)器的變量存在,系統(tǒng)將該變量的值用作當(dāng)前驅(qū)動(dòng)器。如果該變量不存在,系統(tǒng)將假設(shè)指定驅(qū)動(dòng)器的當(dāng)前目錄是它的根目錄。

例如,如果進(jìn)程的當(dāng)前目錄是 C : \ U t i l i t y | B i n,并且你調(diào)用C r e a t e F i l e來打開D : R e a d M e . T x t,那么系統(tǒng)查看環(huán)境變量 = D。因?yàn)?/span>= D變量存在,因此系統(tǒng)試圖從 D:\Program Files目錄打開該R e a d M e . T x t文件。如果= D變量不存在,系統(tǒng)將試圖從驅(qū)動(dòng)器 D的根目錄來打開 R e a d M e . T x tWi n d o w s的文件函數(shù)決不會(huì)添加或修改驅(qū)動(dòng)器名的環(huán)境變量,它們只是讀取這些變量。

注意 可以使用C運(yùn)行期函數(shù)_ c h d i r,而不是使用Wi n d o w sS e t C u r r e n t D i r e c t o r y函數(shù)來變更當(dāng)前目錄。_ c h d i r函數(shù)從內(nèi)部調(diào)用S e t C u r r e n t D i r e c t o r y,但是_chdir 也能夠添加或修改該環(huán)境變量,這樣,不同驅(qū)動(dòng)器的當(dāng)前目錄就可以保留。

如果父進(jìn)程創(chuàng)建了一個(gè)它想傳遞給子進(jìn)程的環(huán)境塊,子進(jìn)程的環(huán)境塊不會(huì)自動(dòng)繼承父進(jìn)程的當(dāng)前目錄。相反,子進(jìn)程的當(dāng)前目錄將默認(rèn)為每個(gè)驅(qū)動(dòng)器的根目錄。如果想要讓子進(jìn)程繼承父進(jìn)程的當(dāng)前目錄,該父進(jìn)程必須創(chuàng)建這些驅(qū)動(dòng)器名的環(huán)境變量。并在生成子進(jìn)程前將它們添加給環(huán)境塊。通過調(diào)用G e t F u l l P a t h N a m e,父進(jìn)程可以獲得它的當(dāng)前目錄:

TCHAR szCurDir[MAX_PATH] = {0};

GetFullPathName(_TEXT("C:") ,MAX_PATH ,szCurDir ,NULL);

記住,進(jìn)程的環(huán)境變量必須始終按字母順序來排序。因此驅(qū)動(dòng)器名的環(huán)境變量通常必須置于環(huán)境塊的開始處。

4.1.9 系統(tǒng)版本

? ? 應(yīng)用程序常常需要確定用戶運(yùn)行的是哪個(gè) Wi n d o w s版本。例如,通過調(diào)用安全性函數(shù),應(yīng)用程序就能利用它的安全特性。但是這些函數(shù)只有在Windows 2000上才能得到全面的實(shí)現(xiàn)。Windows API擁有下面的G e t Ve r s i o n函數(shù):

DWORD GetVersion();

????該函數(shù)已經(jīng)有相當(dāng)長(zhǎng)的歷史了。最初它是為 1 6Wi n d o w s設(shè)計(jì)的。它的作用很簡(jiǎn)單,在高位字中返回M S - D O S版本號(hào),在低位字中返回Wi n d o w s版本號(hào)。對(duì)于每個(gè)字來說,高位字節(jié)代表主要版本號(hào),低位字節(jié)代表次要版本號(hào)。

????但是,編寫該代碼的程序員犯了一個(gè)小小的錯(cuò)誤,函數(shù)的編碼結(jié)果使得 Wi n d o w s的版本號(hào)顛倒了,即主要版本號(hào)位于低位字節(jié),而次要版本號(hào)位于高位字節(jié)。由于許多程序員已經(jīng)開始使用該函數(shù),M i c r o s o f t不得不保持函數(shù)的原樣,并修改了文檔,以說明這個(gè)錯(cuò)誤。

由于圍繞著 G e t Ve r s i o n函數(shù)存在著各種混亂,因此 M i c r o s o f t增加了一個(gè)新函數(shù)G e t Ve r s i o n E x :

?

OSVERSIONINFO osvi;

ZeroMemory(&osvi ,sizeof(OSVERSIONINFO));

osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

GetVersionExW(&osvi);

O S V E R S I O N I N F O E X結(jié)構(gòu)在Windows 2000中是個(gè)新結(jié)構(gòu)。Wi n d o w s的其他版本使用較老的O S V E R S I O N I N F O結(jié)構(gòu),它沒有服務(wù)程序包、程序組屏蔽、產(chǎn)品類型和保留成員。

注意,對(duì)于系統(tǒng)的版本號(hào)中的每個(gè)成分來說,該結(jié)構(gòu)擁有不同的成員。這樣做的目的是,

程序員不必提取低位字、高位字、低位字節(jié)和高位字節(jié),因此應(yīng)用程序能夠更加容易地對(duì)它們期望的版本號(hào)與主機(jī)系統(tǒng)的版本號(hào)進(jìn)行比較。下表描述了O S V E R S I O N I N F O E X結(jié)構(gòu)的成員。

?


為了使操作更加容易,Windows 2000提供了一個(gè)新的函數(shù),即Ve r i f y Ve r s i o n I n f o,用于對(duì)主機(jī)系統(tǒng)的版本與你的應(yīng)用程序需要的版本進(jìn)行比較:

BOOL VerifyVersionInfoW(

????_Inout_ LPOSVERSIONINFOEXW lpVersionInformation,

????_In_ ???DWORD dwTypeMask,

????_In_ ???DWORDLONG dwlConditionMask

????);

若要使用該函數(shù),必須指定一個(gè)O S V E R S I O N I N F O E X結(jié)構(gòu),將它的d w O S Ve r s i o n I n f o S i z e成員初始化為該結(jié)構(gòu)的大小,然后對(duì)該結(jié)構(gòu)中的其他成員(這些成員對(duì)你的應(yīng)用程序來說很重要)進(jìn)行初始化。當(dāng)調(diào)用Ve r i f y Ve r s i o n I n f o時(shí),d w Ty p e M a s k參數(shù)用于指明該結(jié)構(gòu)的哪些成員已經(jīng)進(jìn)行了初始化。 d w Ty p e M a s k參數(shù)是用 O R連接在一起的下列標(biāo)志中的任何一個(gè)標(biāo)志:V E R _ M I N O RV E R S I O NV E R _ M A J O RV E R S I O NV E R _ B U I L D N U M B E RV E R _ P L AT F O R M I DVER_ SERV I C E PA C K M I N O RV E R _ S E RV I C E PA C K M A J O RV E R _ S U I T E N A M EVER_PRODUCT_ TYPE。最后一個(gè)參數(shù)d w l C o n d i t i o n M a s k是個(gè)6 4位值,用于控制該函數(shù)如何將系統(tǒng)的版本信息與需要的信息進(jìn)行比較。

d w l C o n d i t i o n M a s k描述了如何使用一組復(fù)雜的位組合進(jìn)行的比較。若要?jiǎng)?chuàng)建需要的位組合,可以使用V E R _ S E T _ C O N D I T I O N宏:

VER_SET_CONDITION(

DWORD dwlConditionMask,

? ULONG dwTypeBitMask,

ULONG dwConditionMask)

第一個(gè)參數(shù)d w l C o n d i t i o n M a s k用于標(biāo)識(shí)一個(gè)變量,該變量的位是要操作的那些位。請(qǐng)注意,不必傳遞該變量的地址,因?yàn)?V E R _ S E T _ C O N D I T I O N是個(gè)宏,不是一個(gè)函數(shù)。d w Ty p e B i t M a s k參數(shù)用于指明想要比較的O S V E R S I O N I N F O E X結(jié)構(gòu)中的單個(gè)成員。若要比較多個(gè)成員,必須多次調(diào)用 V E R _ S E T _ C O N D I T I O N宏,每個(gè)成員都要調(diào)用一次。傳遞給Ve r i f y Ve r s i o n I n f od w Ty p e M a s k參數(shù)(V E R _ M I N O RV E R S I O NV E R _ B U I L D N U M B E R等)的標(biāo)志與用于V E R _ S E T _ C O N D I T I O Nd w Ty p e B i t M a s k參數(shù)的標(biāo)志是相同的。

V E R _ S E T _ C O N D I T I O N的最后一個(gè)參數(shù)d w C o n d i t i o n M a s k用于指明想如何進(jìn)行比較。它可以是下列值之一:V E R _ E Q U A LV E R _ G R E AT E RV E R _ G R E AT E R _ E Q U A LV E R _ L E S SV E R _ L E S S _ E Q U A L。請(qǐng)注意,當(dāng)比較V E R _ P R O D U C T _ T Y P E信息時(shí),可以使用這些值。例如,V E R _ N T _ W O R K S TAT I O N小于V E R _ N T _ S E RV E R。但是對(duì)于V E R _ S U I T E N A M E信息來說,不能使用這些測(cè)試值。相反,必須使用 V E R _ A N D(所有程序組都必須安裝)或 V E R _ O R(至少必須安裝程序組產(chǎn)品中的一個(gè)產(chǎn)品) 。

當(dāng)建立一組條件后,可以調(diào)用 Ve r i f y Ve r s i o n I n f o函數(shù),如果調(diào)用成功(如果主機(jī)系統(tǒng)符合應(yīng)用程序的所有要求) ,則返回非零值。如果Ve r i f y Ve r s i o n I n f o返回0,那么主機(jī)系統(tǒng)不符合要求,或者表示對(duì)該函數(shù)的調(diào)用不正確。通過調(diào)用 G e t L a s t E r r o r函數(shù),就能確定該函數(shù)為什么返回0。如果G e t L a s t E r r o r返回E R R O R _ O L D _ W I N _ V E R S I O N,那么對(duì)該函數(shù)的調(diào)用是正確的,但是系統(tǒng)沒有滿足要求。

下面是如何測(cè)試主機(jī)系統(tǒng)是否正是Windows 2000的一個(gè)例子:



總結(jié)

以上是生活随笔為你收集整理的Windows核心编程 第四章 进程(上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。