




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、VC+中進(jìn)程與多進(jìn)程管理的方法進(jìn)程是當(dāng)前操作系統(tǒng)下一個被加載到內(nèi)存的、正在運(yùn)行的應(yīng)用程序的實例。每一個進(jìn)程都是由內(nèi)核對象和地址空間所組成的,內(nèi)核對象可以讓系統(tǒng)在其內(nèi)存放有關(guān)進(jìn)程的統(tǒng)計信息并使系統(tǒng)能夠以此來管理進(jìn)程,而地址空間則包括了所有程序模塊的代碼和數(shù)據(jù)以及線程堆棧、堆分配空間等動態(tài)分配的空間。進(jìn)程僅僅是一個存在,是不能獨(dú)自完成任何操作的,必須擁有至少一個在其環(huán)境下運(yùn)行的線程,并由其負(fù)責(zé)執(zhí)行在進(jìn)程地址空間內(nèi)的代碼。在進(jìn)程啟動的同時即同時啟動了一個線程,該線程被稱作主線程或是執(zhí)行線程,由此線程可以繼續(xù)創(chuàng)建子線程。如果主線程退出,那么進(jìn)程也就沒有存在的可能了,系統(tǒng)將自動撤消該進(jìn)程并完成對其地址空
2、間的釋放。加載到進(jìn)程地址空間的每一個可執(zhí)行文件或動態(tài)鏈接庫文件的映象都會被分配一個與之相關(guān)聯(lián)的全局唯一的實例句柄(Hinstance)。該實例句柄實際是一個記錄有進(jìn)程加載位置的基本內(nèi)存地址。進(jìn)程的實例句柄在程序入口函數(shù)WinMain()中通過第一個參數(shù)HINSTANCE hinstExe傳遞,其實際值即為進(jìn)程所使用的基本地址空間的地址。對于VC+鏈接程序所鏈接產(chǎn)生的程序,其默認(rèn)的基本地址空間地址為0x,如沒有必要一般不要修改該值。在程序中,可以通過GetModuleHandle()函數(shù)得到指定模塊所使用的基本地址空間。子進(jìn)程的創(chuàng)建進(jìn)程的創(chuàng)建通過CreateProcess()函數(shù)來實現(xiàn),Crea
3、teProcess()通過創(chuàng)建一個新的進(jìn)程及在其地址空間內(nèi)運(yùn)行的主線程來啟動并運(yùn)行一個新的程序。具體的,在執(zhí)行CreateProcess()函數(shù)時,首先由操作系統(tǒng)負(fù)責(zé)創(chuàng)建一個進(jìn)程內(nèi)核對象,初始化計數(shù)為1,并立即為新進(jìn)程創(chuàng)建一塊虛擬地址空間。隨后將可執(zhí)行文件或其他任何必要的動態(tài)鏈接庫文件的代碼和數(shù)據(jù)裝載到該地址空間中。在創(chuàng)建主線程時,也是首先由系統(tǒng)負(fù)責(zé)創(chuàng)建一個線程內(nèi)核對象,并初始化為1。最后啟動主線程并執(zhí)行進(jìn)程的入口函數(shù)WinMain(),完成對進(jìn)程和執(zhí)行線程的創(chuàng)建。CreateProcess()函數(shù)的原型聲明如下:BOOL CreateProcess(LPCTSTR lpApplication
4、Name, / 可執(zhí)行模塊名LPTSTR lpCommandLine, / 命令行字符串LPSECURITY_ATTRIBUTES lpProcessAttributes, / 進(jìn)程的安全屬性LPSECURITY_ATTRIBUTES lpThreadAttributes, / 線程的安全屬性BOOL bInheritHandles, / 句柄繼承標(biāo)志DWORD dwCreationFlags, / 創(chuàng)建標(biāo)志LPVOID lpEnvironment, / 指向新的環(huán)境塊的指針LPCTSTR lpCurrentDirectory, / 指向當(dāng)前目錄名的指針LPSTARTUPINFO lpStar
5、tupInfo, / 指向啟動信息結(jié)構(gòu)的指針LPPROCESS_INFORMATION lpProcessInformation / 指向進(jìn)程信息結(jié)構(gòu)的指針); 在程序設(shè)計時,某一個具體的功能模塊可以通過函數(shù)或是線程等不同的形式來實現(xiàn)。對于同一進(jìn)程而言,這些函數(shù)、線程都是存在于同一個地址空間下的,而且在執(zhí)行時,大多只對與其相關(guān)的一些數(shù)據(jù)進(jìn)行處理。如果算法存在某種錯誤,將有可能破壞與其同處一個地址空間的其他一些重要內(nèi)容,這將造成比較嚴(yán)重的后果。為保護(hù)地址空間中的內(nèi)容可以考慮將那些需要對地址空間中的數(shù)據(jù)進(jìn)行訪問的操作部分放到另外一個進(jìn)程的地址空間中運(yùn)行,并且只允許其訪問原進(jìn)程地址空間中的相關(guān)數(shù)據(jù)。
6、具體的,可在進(jìn)程中通過CreateProcess()函數(shù)去創(chuàng)建一個子進(jìn)程,子進(jìn)程在全部處理過程中只對父進(jìn)程地址空間中的相關(guān)數(shù)據(jù)進(jìn)行訪問,從而可以保護(hù)父進(jìn)程地址空間中與當(dāng)前子進(jìn)程執(zhí)行任務(wù)無關(guān)的全部數(shù)據(jù)。對于這種情況,子進(jìn)程所體現(xiàn)出來的作用同函數(shù)和線程比較相似,可以看成是父進(jìn)程在運(yùn)行期間的一個過程。為此,需要由父進(jìn)程來掌握子進(jìn)程的啟動、執(zhí)行和退出。下面這段代碼即展示了此過程:/ 臨時變量CString sCommandLine;char cWindowsDirectoryMAX_PATH;char cCommandLineMAX_PATH;DWORD dwExitCode;PROCESS_INFO
7、RMATION pi;STARTUPINFO si = sizeof(si);/ 得到Windows目錄GetWindowsDirectory(cWindowsDirectory, MAX_PATH);/ 啟動記事本程序的命令行sCommandLine = CString(cWindowsDirectory) + NotePad.exe;:strcpy(cCommandLine, sCommandLine);/ 啟動記事本作為子進(jìn)程BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si
8、, &pi);if (ret) / 關(guān)閉子進(jìn)程的主線程句柄CloseHandle(pi.hThread);/ 等待子進(jìn)程的退出WaitForSingleObject(pi.hProcess, INFINITE);/ 獲取子進(jìn)程的退出碼GetExitCodeProcess(pi.hProcess, &dwExitCode);/ 關(guān)閉子進(jìn)程句柄CloseHandle(pi.hProcess); 此段代碼首先通過CreateProcess()創(chuàng)建Windows自帶的“記事本”程序為子進(jìn)程,子進(jìn)程啟動后父進(jìn)程通過WaitForSingleObject()函數(shù)等待其執(zhí)行的結(jié)束,在子進(jìn)程沒有退出前父進(jìn)程是
9、一直處于阻塞狀態(tài)的,這里子進(jìn)程的作用同單線程中的函數(shù)類似。一旦子進(jìn)程退出,WaitForSingleObject()函數(shù)所等待的pi.hProcess對象將得到通知,父進(jìn)程將得以繼續(xù),如有必要可以通過GetExitCodeProcess()來獲取子進(jìn)程的退出代碼。相比而言,更多的情況是父進(jìn)程在啟動完子進(jìn)程后就再不與其進(jìn)行任何數(shù)據(jù)交換和通訊,由其創(chuàng)建的子進(jìn)程的執(zhí)行成功與否均與父進(jìn)程無關(guān)。許多大型軟件在設(shè)計時也多采用了這類思想,將某些功能完全通過獨(dú)立的應(yīng)用程序來完成,當(dāng)需要執(zhí)行某操作時只要通過主程序啟動相應(yīng)的子進(jìn)程即可,具體的處理工作均由子進(jìn)程去完成。這類子進(jìn)程的創(chuàng)建過程更為簡單,例如對于上面那段
10、代碼只需去除對子進(jìn)程句柄pi.hProcess的等待即可:BOOL ret = CreateProcess(NULL, cCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);if (ret) / 關(guān)閉子進(jìn)程的主線程句柄CloseHandle(pi.hThread);/ 關(guān)閉子進(jìn)程句柄CloseHandle(pi.hProcess); 可以通過dwCreationFlags參數(shù)在創(chuàng)建進(jìn)程時設(shè)置子進(jìn)程的優(yōu)先級。前面的示例代碼在創(chuàng)建子進(jìn)程時使用的均是默認(rèn)的優(yōu)先級,如果要將優(yōu)先級設(shè)置為高,可以修改如下:BOOL ret = CreatePr
11、ocess(NULL, cCommandLine, NULL, NULL, FALSE, HIGH_PRIORITY_CLASS, NULL, NULL, &si, &pi); 如果在進(jìn)程創(chuàng)建時沒有特別設(shè)置優(yōu)先級,可以通過SetPriorityClass()函數(shù)來動態(tài)設(shè)定,該函數(shù)需要待操作進(jìn)程的句柄和優(yōu)先級標(biāo)識符作為入口參數(shù),函數(shù)原型為:BOOL SetPriorityClass(HANDLE hProcess, DWORD dwPriorityClass); 對于前面沒有設(shè)定優(yōu)先級的例子代碼,可以在子進(jìn)程啟動后由父進(jìn)程來動態(tài)改變其優(yōu)先級設(shè)置:SetPriorityClass(pi.hProc
12、ess, HIGH_PRIORITY_CLASS); 或是由子進(jìn)程在其啟動后自行改變優(yōu)先級設(shè)置,需要注意的是這時進(jìn)程句柄應(yīng)設(shè)置為子進(jìn)程自身的句柄,可通過GetCurrentProcess()函數(shù)來獲?。篐ANDLE hProcess = GetCurrentProcess();SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS); 進(jìn)程的互斥運(yùn)行正常情況下,一個進(jìn)程的運(yùn)行一般是不會影響到其他正在運(yùn)行的進(jìn)程的。但是對于某些有特殊要求的如以獨(dú)占方式使用串行口等硬件設(shè)備的程序就要求在其進(jìn)程運(yùn)行期間不允許其他試圖使用此端口設(shè)備的程序運(yùn)行的,而且此類程序通常也不
13、允許運(yùn)行同一個程序的多個實例。這就引出了進(jìn)程互斥的問題。實現(xiàn)進(jìn)程互斥的核心思想比較簡單:進(jìn)程在啟動時首先檢查當(dāng)前系統(tǒng)是否已經(jīng)存在有此進(jìn)程的實例,如果沒有,進(jìn)程將成功創(chuàng)建并設(shè)置標(biāo)識實例已經(jīng)存在的標(biāo)記。此后再創(chuàng)建進(jìn)程時將會通過該標(biāo)記而知曉其實例已經(jīng)存在,從而保證進(jìn)程在系統(tǒng)中只能存在一個實例。具體可以采取內(nèi)存映射文件、有名事件量、有名互斥量以及全局共享變量等多種方法來實現(xiàn)。下面就分別對其中具有代表性的有名互斥量和全局共享變量這兩種方法進(jìn)行介紹:/ 創(chuàng)建互斥量HANDLE m_hMutex = CreateMutex(NULL, FALSE, Sample07);/ 檢查錯誤代碼if (GetLast
14、Error() = ERROR_ALREADY_EXISTS) / 如果已有互斥量存在則釋放句柄并復(fù)位互斥量CloseHandle(m_hMutex);m_hMutex = NULL;/ 程序退出return FALSE; 上面這段代碼演示了有名互斥量在進(jìn)程互斥中的用法。代碼的核心是CreateMutex()對有名互斥量的創(chuàng)建。CreateMutex()函數(shù)可用來創(chuàng)建一個有名或無名的互斥量對象,其函數(shù)原型為:HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, / 指向安全屬性的指針BOOL bInitialOwner, / 初
15、始化互斥對象的所有者LPCTSTR lpName / 指向互斥對象名的指針); 如果函數(shù)成功執(zhí)行,將返回一個互斥量對象的句柄。如果在CreateMutex()執(zhí)行前已經(jīng)存在有相同名字的互斥量,函數(shù)將返回這個已經(jīng)存在互斥量的句柄,并且可以通過GetLastError()得到錯誤代碼ERROR_ALREADY_EXIST。可見,通過對錯誤代碼ERROR_ALREADY_EXIST的檢測可以實現(xiàn)CreateMutex()對進(jìn)程的互斥。使用全局共享變量的方法則主要是在MFC框架程序中通過編譯器來實現(xiàn)的。通過#pragma data_seg預(yù)編譯指令創(chuàng)建一個新節(jié),在此節(jié)中可用volatile關(guān)鍵字定義一
16、個變量,而且必須對其進(jìn)行初始化。Volatile關(guān)鍵字指定了變量可以為外部進(jìn)程訪問。最后,為了使該變量能夠在進(jìn)程互斥過程中發(fā)揮作用,還要將其設(shè)置為共享變量,同時允許具有讀、寫訪問權(quán)限。這可以通過#pragma comment預(yù)編譯指令來通知編譯器。下面給出使用了全局變量的進(jìn)程互斥代碼清單:#pragma data_seg(Shared) int volatile g_lAppInstance =0;#pragma data_seg()#pragma comment(linker,/section:Shared,RWS)if(+g_lAppInstance1)return FALSE; 此段代碼
17、的作用是在進(jìn)程啟動時對全局共享變量g_nAppInstancd 加1 ,如果發(fā)現(xiàn)其值大于1,那么就返回FALSE以通知進(jìn)程結(jié)束。這里需要特別指出的是,為了使以上兩段代碼能夠真正起到對進(jìn)程互斥的作用,必須將其放置在應(yīng)用程序的入口代碼處,即應(yīng)用程序類的初始化實例函數(shù)InitInstance()的開始處。結(jié)束進(jìn)程進(jìn)程只是提供了一段地址空間和內(nèi)核對象,其運(yùn)行是通過在其地址空間內(nèi)的主線程來體現(xiàn)的。當(dāng)主線程的進(jìn)入點函數(shù)返回時,進(jìn)程也就隨之結(jié)束。這種進(jìn)程的終止方式是進(jìn)程的正常退出,進(jìn)程中的所有線程資源都能夠得到正確的清除。除了這種進(jìn)程的正常推出方式外,有時還需要在程序中通過代碼來強(qiáng)制結(jié)束本進(jìn)程或其他進(jìn)程的運(yùn)
18、行。ExitProcess()函數(shù)即可在進(jìn)程中的某個線程中使用,并將立即終止本進(jìn)程的運(yùn)行。ExitProcess()函數(shù)原型為:VOID ExitProcess(UINT uExitCode); 其參數(shù)uExitCode為進(jìn)程設(shè)置了退出代碼。該函數(shù)具有強(qiáng)制性,在執(zhí)行完畢后進(jìn)程即已經(jīng)被結(jié)束,因此位于其后的任何代碼將不能被執(zhí)行。雖然ExitProcess()函數(shù)可以在結(jié)束進(jìn)程的同時通知與其相關(guān)聯(lián)的動態(tài)鏈接庫,但是由于它的這種執(zhí)行的強(qiáng)制性,使得ExitProcess()函數(shù)在使用上將存在有安全隱患。例如,如果在程序調(diào)用ExitProcess()函數(shù)之前曾用new操作符申請過一段內(nèi)存,那么將會由于Ex
19、itProcess()函數(shù)的強(qiáng)制性而無法通過delete操作符將其釋放,從而造成內(nèi)存泄漏。有鑒于ExitProcess()函數(shù)的強(qiáng)制性和不安全性,在使用時一定要引起注意。ExitProcess()只能強(qiáng)制執(zhí)行本進(jìn)程的退出,如果要在一個進(jìn)程中強(qiáng)制結(jié)束其他的進(jìn)程就要用TerminateProcess()來實現(xiàn)。與ExitProcess()不同,TerminateProcess()函數(shù)執(zhí)行后,被終止的進(jìn)程是不會得到任何關(guān)于程序退出的通知的。也就是說,被終止的進(jìn)程是無法在結(jié)束運(yùn)行前進(jìn)行退出前的收尾工作的。所以,通常只有在其他任何方法都無法迫使進(jìn)程退出時才會考慮使用TerminateProcess()去
20、強(qiáng)制結(jié)束進(jìn)程的。下面給出TerminateProcess()的函數(shù)原型:BOOL TerminateProcess(HANDLE hProcess, UINT uExitCode); 參數(shù)hProcess和uExitCode分別為進(jìn)程句柄和退出代碼。如果被結(jié)束的是本進(jìn)程,可以通過GetCurrentProcess()獲取到句柄。TerminateProcess()是異步執(zhí)行的,在調(diào)用返回后并不能確定被終止進(jìn)程是否已經(jīng)真的退出,如果調(diào)用TerminateProcess()的進(jìn)程對此細(xì)節(jié)關(guān)心,可以通過WaitForSingleObject()來等待進(jìn)程的真正結(jié)束。小結(jié)多進(jìn)程是多任務(wù)管理中的重要內(nèi)容
21、,文中上述部分對其基本概念和主要的技術(shù)如子進(jìn)程的創(chuàng)建與結(jié)束、進(jìn)程間的互斥運(yùn)行等做了較詳細(xì)的介紹。通過本文讀者應(yīng)能對多進(jìn)程管理有一個初步的認(rèn)識。 進(jìn)程控制簡單的說相當(dāng)于在一個程序中執(zhí)行另一個程序,你可以把它想象成在 Dos 下用 int 21h/4bh 功能來執(zhí)行另外一個程序,如果單從執(zhí)行另一個程序的目的來講,在 Windows 中有不少方法,如使用 ShellExecute 等,但這些 Api 僅僅是“執(zhí)行”而已,進(jìn)程控制的意義在于可以創(chuàng)建一個進(jìn)程,并可以通過進(jìn)程句柄結(jié)束進(jìn)程,同樣你也可以通過進(jìn)程句柄來跟蹤程序,還可以用 ReadProcessMemory 和 WriteProcessMemo
22、ry 來讀寫子進(jìn)程的內(nèi)存空間。進(jìn)程控制要使用的相關(guān) API 有下面這些:創(chuàng)建進(jìn)程的函數(shù)為CreateProcess,該函數(shù)比較復(fù)雜,共有十個參數(shù),但有個好消息是使用時大部分可以用 NULL。BOOL CreateProcess( LPCTSTR lpApplicationName, / 執(zhí)行程序文件名LPTSTR lpCommandLine, / 參數(shù)行 LPSECURITY_ATTRIBUTES lpProcessAttributes, / 進(jìn)程安全參數(shù)LPSECURITY_ATTRIBUTES lpThreadAttributes, / 線程安全參數(shù)BOOL bInheritHandles
23、, / 繼承標(biāo)記DWORD dwCreationFlags, / 創(chuàng)建標(biāo)記LPVOID lpEnvironment, / 環(huán)境變量LPCTSTR lpCurrentDirectory, / 運(yùn)行該子進(jìn)程的初始目錄LPSTARTUPINFO lpStartupInfo, / 創(chuàng)建該子進(jìn)程的相關(guān)參數(shù) LPPROCESS_INFORMATION lpProcessInformation / 創(chuàng)建后用于被創(chuàng)建子進(jìn)程的信息);各個參數(shù)的說明如下:lpApplicationName:為執(zhí)行程序的文件名,你也可以把執(zhí)行文件名包括在下一個參數(shù) lpCommandLine 中,然后把該參數(shù)置為NULL。lpCo
24、mmandLine:為參數(shù)行,如果無參數(shù)可以為NULL,在有參數(shù)傳遞給進(jìn)程時可以如下設(shè)置:lpApplicationName=文件名;lpCommandLine=參數(shù),或者 lpApplicationName=NULL;lpCommandLine=文件名 + 參數(shù)。lpProcessAttributes,lpThreadAttributes:分別描述了創(chuàng)建的進(jìn)程和線程安全屬性,如果使用NULL表示使用默認(rèn)的安全描述。bInheritHandles:表示當(dāng)前進(jìn)程中的打開的句柄是否能夠被創(chuàng)建的子進(jìn)程所繼承。dwCreationFlags:表示創(chuàng)建標(biāo)記,通過該標(biāo)記可以設(shè)置進(jìn)程的創(chuàng)建狀態(tài)和優(yōu)先級別。常
25、用的有下面的標(biāo)記: CREATE_NEW_CONSOLE:為子進(jìn)程創(chuàng)建一個新的控制臺。 CREATE_SUSPENDED:子進(jìn)程在創(chuàng)建時為掛起狀態(tài)。如果指定了這個參數(shù),那么執(zhí)行 CreateProcess 后進(jìn)程只是被裝入內(nèi)存,但不是馬上開始執(zhí)行,而是必須等主程序調(diào)用 ResumeThread 后才繼續(xù)執(zhí)行。HIGH_PRIORITY_CLASS/NORMAL_PRIORITY_CLASS:高/普通優(yōu)先級別。lpEnvironment:表示子進(jìn)程所使用的環(huán)境變量,如果為NULL,則表示與當(dāng)前進(jìn)程使用相同的環(huán)境變量。lpCurrentDirectory:表示子進(jìn)程運(yùn)行的初始目錄。lpStartu
26、pInfo:STARTUPINFO 結(jié)構(gòu),用于在創(chuàng)建子進(jìn)程時設(shè)置各種屬性。lpProcessInformation:PROCESS_INFORMATION 結(jié)構(gòu),用來在進(jìn)程創(chuàng)建后接收相關(guān)信息,該結(jié)構(gòu)由系統(tǒng)填寫。調(diào)用 CreateProcess 函數(shù)有三個參數(shù)是必需的,一在 lpApplicationName 或 lpCommandLine 指定文件名,二是 lpStartupInfo 結(jié)構(gòu),三是 PROCESS_INFORMATION 結(jié)構(gòu),因為 PROCESS_INFORMATION 結(jié)構(gòu)返回了進(jìn)程建立后的句柄,以后的一切操作將要用到這些返回的句柄,它是由系統(tǒng)填寫的,結(jié)構(gòu)說明如下:typed
27、ef struct _PROCESS_INFORMATION HANDLE hProcess; /進(jìn)程句柄HANDLE hThread; /進(jìn)程的主線程句柄DWORD dwProcessId; /進(jìn)程IDDWORD dwThreadId; /進(jìn)程的主線程ID PROCESS_INFORMATION;另外還有一個關(guān)鍵的結(jié)構(gòu) STARTUPINFO,該結(jié)構(gòu)定義如下:typedef struct STARTUPINFO DWORD cb; /結(jié)構(gòu)長度LPTSTR lpReserved; /保留LPTSTR lpDesktop; /保留LPTSTR lpTitle; /如果為控制臺進(jìn)程則為顯示的標(biāo)題D
28、WORD dwX; /窗口位置DWORD dwY; /窗口位置DWORD dwXSize; /窗口大小DWORD dwYSize; /窗口大小DWORD dwXCountChars; /控制臺窗口字符號寬度DWORD dwYCountChars; /控制臺窗口字符號高度DWORD dwFillAttribute; /控制臺窗口填充模式DWORD dwFlags; /創(chuàng)建標(biāo)記WORD wShowWindow; /窗口顯示標(biāo)記,如同ShowWindow中的標(biāo)記WORD cbReserved2; /LPBYTE lpReserved2; /HANDLE hStdInput; /標(biāo)準(zhǔn)輸入句柄HANDL
29、E hStdOutput; /標(biāo)準(zhǔn)輸出句柄HANDLE hStdError; /標(biāo)準(zhǔn)錯誤句柄 STARTUPINFO, *LPSTARTUPINFO;結(jié)構(gòu)中 dwFlags 指定了其它的一些字段是否有效,如:dwFlags包含 STARTF_USESIZE 表示dwXSize和dwYSize有效,包含STARTF_USEPOSITION表示dwX和dwY有效,等等。如果不是有特殊的要求,我們不用自己去填寫這個結(jié)構(gòu),只需用 GetStartupInfo 讓 Windows 為你填寫好了,這樣,建立一個進(jìn)程的語句就是:.stStartUp STARTUPINFO stProcInfo PROCES
30、S_INFORMATION stProcInfo PROCESS_INFORMATION .invoke GetStartupInfo,addr stStartUpinvoke CreateProcess,NULL,addr szFileName,NULL,NULL,NULL,NORMAL_PRIORITY_CLASS,NULL,NULL,offset stStartUp,offset stProcInfo.如果成功的話,eax 將返回非零值,注意返回在 PROCESS_INFORMATION 結(jié)構(gòu)中的 hProcess,以后很多的操作都要用到它。強(qiáng)制結(jié)束一個進(jìn)程的 API 為 Termina
31、teProcessBOOL TerminateProcess(HANDLE hProcess, / 進(jìn)程句柄UINT uExitCode / 退出代碼 );你可以使用語句 invoke TerminateProcess,structProcInfo.hProcess,0 來結(jié)束進(jìn)程,要注意的是如果可能的話,盡量不要在程序中強(qiáng)制結(jié)束別的進(jìn)程,因為使用 TerminateProcess 結(jié)束的進(jìn)程,它裝載的 dll 不能被正確卸載。這樣可能會引起系統(tǒng)資源的無效占用。最好的辦法在進(jìn)程中自己使用 ExitProcess 退出。查詢一個進(jìn)程狀態(tài)的 API 為 GetExitCodeProcess。BOO
32、L GetExitCodeProcess(HANDLE hProcess, / handle to the process LPDWORD lpExitCode / address to receive termination status );如果進(jìn)程尚未退出,函數(shù)將會返回STILL_ACTIVE。這個 API 是馬上返回的。等待進(jìn)程執(zhí)行可以用 WaitForSingleObject這個 API 并不是單用于進(jìn)程的等待,其它還可以用在線程等操作,但我們一般用它來等待進(jìn)程的執(zhí)行,它的申明是:DWORD WaitForSingleObject(HANDLE hHandle, / handle o
33、f object to wait forDWORD dwMilliseconds / time-out interval in milliseconds );如果我們要等待進(jìn)程執(zhí)行 1 秒鐘,可以 invoke WaitForSingleObject,stProcInfo.hProcess,1000 如果要等到進(jìn)程結(jié)束,可以用 WaitForSingleObject,stProcInfo.hProcess,INFINITE ,參數(shù) 2 中的 INFINITE 在 Windows.inc 中有定義,意思是無窮等待。最后,當(dāng)不再使用進(jìn)程句柄的時候,不要忘了使用 CloseHandle 關(guān)閉 hPr
34、ocess 和 hThread,否則會浪費(fèi)系統(tǒng)句柄的資源。源程序 - 匯編源文件 .386 .model flat, stdcall option casemap :none ; case sensitive; Include 數(shù)據(jù);include windows.incinclude user32.incinclude kernel32.incinclude comctl32.incinclude comdlg32.incinclude gdi32.incincludelib user32.libincludelib kernel32.libincludelib comctl32.libin
35、cludelib comdlg32.libincludelib gdi32.lib; Equ 數(shù)據(jù);DLG_MAIN equ 3000;ID_BROWSE equ 3001ID_RUN equ 3002ID_EXIT equ 3003ID_TEXT equ 3004F_RUNNING equ 0001h ;進(jìn)程在運(yùn)行中; 數(shù)據(jù)段; .data?stStartUp STARTUPINFO stProcInfo PROCESS_INFORMATION stOpenFileName OPENFILENAME hRunThread dd ?hInstance dd ?hWinMain dd ?hIco
36、n dd ?szBuffer db 512 dup (?)dwFlag dd ?; .dataszExcute db 執(zhí)行(&E),0 ;按鈕文字szKill db 終止(&E),0szExcuteError db 啟動應(yīng)用程序錯誤!,0szTitleOpen db Open executable file.,0szExt db *.exe,0szFilter db Excutable Files,0,*.exe;*.com,0 db 0; 代碼段; .codeif DEBUG include Debug.asmendifinclude Win.asm;*; 執(zhí)行程序用的線程; 1. 用 Cr
37、eateProcess 建立進(jìn)程; 2. 用 WaitForSingleOject 等待進(jìn)程結(jié)束;*_RunThread proc uses ebx ecx edx esi edi, dwParam:DWORD or dwFlag,F_RUNNING;*; 取消“退出”按鈕并把“執(zhí)行”按鈕改為“中止”;* invoke GetDlgItem,hWinMain,ID_EXIT invoke EnableWindow,eax,FALSE invoke SendDlgItemMessage,hWinMain,ID_RUN,WM_SETTEXT,0,offset szKill;*; 執(zhí)行文件,如果成功
38、則等待程序結(jié)束;* invoke GetStartupInfo,addr stStartUp invoke CreateProcess,NULL,addr szBuffer,NULL,NULL, NULL,NORMAL_PRIORITY_CLASS,NULL,NULL,offset stStartUp,offset stProcInfo .if eax != 0 invoke WaitForSingleObject,stProcInfo.hProcess,INFINITE invoke CloseHandle,stProcInfo.hProcess invoke CloseHandle,stP
39、rocInfo.hThread .else invoke MessageBox,hWinMain,addr szExcuteError,NULL,MB_OK or MB_ICONERROR .endif;*; Enable “退出”按鈕并把“中止”按鈕改為“執(zhí)行”;* invoke GetDlgItem,hWinMain,ID_EXIT invoke EnableWindow,eax,TRUE invoke SendDlgItemMessage,hWinMain,ID_RUN,WM_SETTEXT,0,offset szExcute and dwFlag,not F_RUNNING ret_R
40、unThread endp;*; 窗口程序;*DialogMainProc proc uses ebx edi esi, hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD mov eax,wMsg;* .if eax = WM_INITDIALOG mov eax,hWnd mov hWinMain,eax call _Init;* .elseif eax = WM_CLOSE invoke EndDialog,hWinMain,NULL;* .elseif eax = WM_COMMAND mov eax,wParam .if ax = ID_B
41、ROWSE call _BrowseFile call _CheckText .elseif ax = ID_TEXT invoke GetDlgItemText,hWinMain,ID_TEXT,addr szBuffer,512 call _CheckText .elseif ax = ID_RUN;*; 如果沒有在執(zhí)行中(dwFlag 沒有置位) 則建立線程,在線程中執(zhí)行程序; 如果已經(jīng)在執(zhí)行中,則用 TerminateProcess 終止執(zhí)行;* test dwFlag,F_RUNNING .if ZERO? invoke CreateThread,NULL,NULL,offset _
42、RunThread, NULL,NULL,offset hRunThread .else invoke TerminateProcess,stProcInfo.hProcess,-1 .endif .elseif ax = ID_EXIT invoke EndDialog,hWinMain,NULL .endif .else;*; 注意:對話框的消息處理后,要返回 TRUE,對沒有處理的消息; 要返回 FALSE;* mov eax,FALSE ret .endif mov eax,TRUE retDialogMainProc endp;*; 程序入口;*start: invoke InitCommonControls invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset DialogMainProc,0 invoke ExitProcess
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025-2030年中國食品級磷酸鹽行業(yè)投資規(guī)劃及發(fā)展前景研究報告
- 2025-2030年中國雕塑工藝品行業(yè)發(fā)展趨勢及投資戰(zhàn)略研究報告
- 2025-2030年中國金屬酸洗行業(yè)發(fā)展趨勢及前景調(diào)研分析報告
- 2025-2030年中國辣椒紅色素市場運(yùn)行態(tài)勢及投資戰(zhàn)略研究報告
- 2025年河北建筑安全員考試題庫
- 2025-2030年中國花露水運(yùn)行趨勢及發(fā)展前景分析報告
- 2025-2030年中國磷酸二氫鉀行業(yè)運(yùn)營狀況及發(fā)展趨勢分析報告
- 2025-2030年中國男士香水行業(yè)運(yùn)營狀況及投資策略研究報告
- 唐山職業(yè)技術(shù)學(xué)院《國際人才管理》2023-2024學(xué)年第二學(xué)期期末試卷
- 2025人教版一年級下冊數(shù)學(xué)教學(xué)進(jìn)度表
- DeepSeek教案寫作指令
- 休學(xué)復(fù)學(xué)申請書
- 2025年四川司法警官職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性測試近5年??及鎱⒖碱}庫含答案解析
- 新建污水處理廠工程EPC總承包投標(biāo)方案(技術(shù)標(biāo))
- 山東省德州市2024-2025學(xué)年高三上學(xué)期1月期末生物試題(有答案)
- 本人報廢車輛委托書
- 雙減政策與五項管理解讀
- 2025年道德與法治小學(xué)六年級下冊教學(xué)計劃(含進(jìn)度表)
- 過橋資金操作流程
- 貨物學(xué) 課件1.2貨物的特性
評論
0/150
提交評論