ShellExecute
ShellExecute的功能是運行一個外部程式(或者是開啟一個登入的檔案、開啟一個目錄、列印一個檔案等等),並對外部程式有一定的控制。
有幾個API函數都可以實現這些功能,但是在大多數情況下ShellExecute是更多的被使用的,同時它並不是太複雜。
ShellExecute函數原型及參數含義如下:
ShellExecute(
HWND hwnd, //父視窗控制代碼 (如:NULL,Handle等)
LPCSTR lpOperation, //操作類型 (如:"open")*要加英文雙引號
LPCSTR lpFile, //要進行操作的檔案或路徑
LPCSTR lpParameters, //當lpOperation為“explore”時指定要傳遞的參數,通常設為NULL
LPCSTR lpDirectory, //指定預設目錄,通常設為NULL
INT nShowCmd //檔案開啟的方式,以通常方式還是最大化或最小化顯示,一般為SW_SHOWNORMAL
)
參數說明:
●hWnd:用於指定父視窗控制代碼。當函數調用過程出現錯誤時,它將作為Windows訊息視窗的父視窗。例如,可以將其設定為應用程式主視窗控制代碼,即Application.Handle,也可以將其設定為桌面視窗控制代碼(用GetDesktopWindow函數獲得)。
●Operation:用於指定要進行的操作。其中“open”動作表示執行由FileName參數指定的程式,或開啟由FileName參數指定的檔案或檔案夾;“print”動作表示列印由FileName參數指定的檔案;“explore”動作表示瀏覽由FileName參數指定的檔案夾。當參數設為nil時,表示執行預設操作“open”。
●FileName:用於指定要開啟的檔案名稱、要執行的程式檔案名稱或要瀏覽的檔案夾名。
●Parameters:若FileName參數是一個可執行程式,則此參數指定命令列參數,否則此參數應為nil或PChar(0)。
●Directory:用於指定預設目錄。
●ShowCmd:若FileName參數是一個可執行程式,則此參數指定程式視窗的初始顯示方式,否則此參數應設定為0。
若ShellExecute函數調用成功,則傳回值為被執行程式的執行個體控制代碼。若傳回值小於32,則表示出現錯誤。
上述僅僅是ShellExecute函數的標準用法,下面將介紹它的特殊用法。
例子如下:
//調用記事本
ShellExecute(NULL,"open","NOTEPAD.EXE",NULL,NULL,SW_SHOWNORMAL);
2.特殊用法
如果將FileName參數設定為“http:”協議格式,那麼該函數將開啟預設瀏覽器並連結到指定的URL地址。若使用者機器中安裝了多個瀏覽器,則該函數將根據Windows 9x/NT註冊表中http通訊協定處理常式(Protocols Handler)的設定確定啟動哪個瀏覽器。
格式一:http://網站網域名稱。
如:ShellExecute(Handle, "open", http:// ;
www.neu.edu.cn’, NULL, NULL, SW_SHOWNORMAL);
格式二:http://網站網域名稱/網頁檔案名稱。
如:ShellExecute(Handle, "open", http:// ;
www.neu.edu.cn/default.htm',NULL,NULL,
SW_SHOWNORMAL);
如果將FileName參數設定為“mailto:”協議格式,那麼該函數將啟動預設郵件客戶程式,如Microsoft Outlook(也包括Microsoft Outlook Express)或Netscape Messanger。若使用者機器中安裝了多個郵件客戶程式,則該函數將根據Windows 9x/NT註冊表中mailto通訊協定處理常式的設定確定啟動哪個郵件客戶程式。
格式一:mailto:
如:ShellExecute(Handle,"open", "mailto:", NULL, NULL, SW_SHOWNORMAL);開啟新郵件視窗。
格式二:mailto:使用者帳號@郵件伺服器地址
如:ShellExecute(Handle, "open"," mailto:who@mail.neu.edu.cn", NULL, NULL, SW_SHOWNORMAL);開啟新郵件視窗,並自動填入收件者地址。若指定多個收件者地址,則收件者地址之間必須用分號或逗號分隔開(下同)。
格式三:mailto:使用者帳號@郵件伺服器地址?subject=郵件主題&body=郵件內文
如:ShellExecute(handle, ‘open’, ‘ mailto:who@mail.neu.edu.cn?subject=Hello&Body=This is a test’, nil, nil, SW_SHOWNORMAL);開啟新郵件視窗,並自動填入收件者地址、郵件主題和郵件內文。若郵件內文包括多行文本,則必須在每行文本之間加入換行逸出字元%0a。
例子(delphi):
在一個應用程式調用c:/Project1.exe;
ShellExecute(handle, 'open','c:/Project1.exe','字串內容',nil, SW_SHOWNORMAL);
在Project1.exe裡可以調用:
procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin
for i:=1 to paramcount do
if ParamStr(i)<>'' then showmessage(ParamStr(i));
end;
最後的那個參數,為視窗指定可視性方面的一個命令。
請用下述任何一個常數
SW_HIDE 隱藏視窗,活動狀態給另一個視窗
SW_MINIMIZE 已最小化的視窗,活動狀態給另一個視窗
SW_RESTORE 用原來的大小和位置顯示一個視窗,同時令其進入活動狀態
SW_SHOW 用當前的大小和位置顯示一個視窗,同時令其進入活動狀態
SW_SHOWMAXIMIZED 已最大化的視窗,並將其啟用
SW_SHOWMINIMIZED 已最小化的視窗,並將其啟用
SW_SHOWMINNOACTIVE 最小化一個視窗,同時不改變使用中視窗
SW_SHOWNA 用當前的大小和位置顯示一個視窗,不改變使用中視窗
SW_SHOWNOACTIVATE 用最近的大小和位置顯示一個視窗,同時不改變使用中視窗
SW_SHOWNORMAL 與SW_RESTORE相同
WinExec
//聲明
WinExec(
lpCmdLine: LPCSTR; {檔案名稱和參數; 如沒指定路徑會按以下順序尋找: 程式目錄/目前的目錄/System32/Windows/PATH環境變數}
uCmdShow: UINT {啟動選項}
): UINT;
//說明 :運行指定的程式
//傳回值
大於 31 {調用成功}
等於 0 {記憶體不足}
ERROR_FILE_NOT_FOUND = 2; {檔案名稱錯誤}
ERROR_PATH_NOT_FOUND = 3; {路徑名錯誤}
ERROR_BAD_FORMAT = 11; {EXE 檔案無效}
(請參考FindExecutable函數)
//參數表:
參數 類型及說明
lpCmdLine String,包含要執行的命令列
uCmdShow Long,定義了以怎樣的形式啟動程式的常數值。
//uCmdShow 參數可選值:
SW_HIDE = 0; {隱藏, 並且工作列也沒有最小化表徵圖} SW_SHOWNORMAL = 1; {用最近的大小和位置顯示, 啟用}
SW_NORMAL = 1; {同 SW_SHOWNORMAL}
SW_SHOWMINIMIZED = 2; {最小化, 啟用}
SW_SHOWMAXIMIZED = 3; {最大化, 啟用}
SW_MAXIMIZE = 3; {同 SW_SHOWMAXIMIZED}
SW_SHOWNOACTIVATE = 4; {用最近的大小和位置顯示, 不啟用}
SW_SHOW = 5; {同 SW_SHOWNORMAL}
SW_MINIMIZE = 6; {最小化, 不啟用}
SW_SHOWMINNOACTIVE = 7; {同 SW_MINIMIZE}
SW_SHOWNA = 8; {同 SW_SHOWNOACTIVATE}
SW_RESTORE = 9; {同 SW_SHOWNORMAL}
SW_SHOWDEFAULT = 10; {同 SW_SHOWNORMAL}
SW_MAX = 10; {同 SW_SHOWNORMAL}
CreateProcess
說明:
WIN32API函數CreateProcess用來建立一個新的進程和它的主線程,這個新進程運行指定的可執行檔。
函數原型:
BOOL CreateProcess
(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes。
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
參數:
lpApplicationName:指向一個NULL結尾的、用來指定可執行模組的字串。
這個字串可以使可執行模組的絕對路徑,也可以是相對路徑,在後一種情況下,函數使用當前磁碟機和目錄建立可執行模組的路徑。
這個參數可以被設為NULL,在這種情況下,可執行模組的名字必須處於 lpCommandLine 參數的最前面並由空格符與後面的字元分開。
這個被指定的模組可以是一個Win32應用程式。如果適當的子系統在當前電腦上可用的話,它也可以是其他類型的模組(如MS-DOS 或 OS/2)。
在Windows NT中,如果可執行模組是一個16位的應用程式,那麼這個參數應該被設定為NULL並且因該在lpCommandLine參數中指定可執行模組的名稱。16位的應用程式是以DOS虛擬機器或Win32上的Windows(WOW) 為進程的方式運行。
lpCommandLine:指向一個NULL結尾的、用來指定要啟動並執行命令列。
這個參數可以為空白,那麼函數將使用參數指定的字串當作要啟動並執行程式的命令列。
如果lpApplicationName和lpCommandLine參數都不為空白,那麼lpApplicationName參數指定將要被啟動並執行模組,lpCommandLine參數指定將被啟動並執行模組的命令列。新啟動並執行進程可以使用GetCommandLine函數獲得整個命令列。C語言程式可以使用argc和argv參數。
如果lpApplicationName參數為空白,那麼這個字串中的第一個被空格分隔的要素指定可執行模組名。如果檔案名稱不包含副檔名,那麼.exe將被假定為預設的副檔名。如果檔案名稱以一個點(.)結尾且沒有副檔名,或檔案名稱中包含路徑,.exe將不會被加到後面。如果檔案名稱中不包含路徑,Windows將按照如下順序尋找這個可執行檔:
1.當前應用程式的目錄。
2.父進程的目錄。
3.Windows 95:Windows系統目錄,可以使用GetSystemDirectory函數獲得。
Windows NT:32位Windows系統目錄。可以使用GetSystemDirectory函數獲得,目錄名是SYSTEM32。
4.在Windows NT中:16位Windows系統目錄。不可以使用Win32函數獲得這個目錄,但是它會被搜尋,目錄名是SYSTEM。
5.Windows目錄。可以使用GetWindowsDirectory函數獲得這個目錄。
6.列在PATH環境變數中的目錄。
如果被建立的進程是一個以MS-DOS或16位Windows為基礎的應用程式,lpCommandLine參數應該是一個以可執行檔的檔案名稱作為第一個要素的絕對路徑,因為這樣做可以使32位Windows程式工作的很好,這樣設定lpCommandLine參數是最強壯的。
lpProcessAttributes:指向一個SECURITY_ATTRIBUTES結構體,這個結構體決定是否返回的控制代碼可以被子進程繼承。如果lpProcessAttributes參數為空白(NULL),那麼控制代碼不能被繼承。
在Windows NT中:SECURITY_ATTRIBUTES結構的lpSecurityDescriptor成員指定了新進程的安全性描述元,如果參數為空白,新進程使用預設的安全性描述元。
在Windows95中:SECURITY_ATTRIBUTES結構的lpSecurityDescriptor成員被忽略。
lpThreadAttributes:指向一個SECURITY_ATTRIBUTES結構體,這個結構體決定是否返回的控制代碼可以被子進程繼承。如果lpThreadAttributes參數為空白(NULL),那麼控制代碼不能被繼承。
在Windows NT中,SECURITY_ATTRIBUTES結構的lpSecurityDescriptor成員指定了主線程的安全性描述元,如果參數為空白,主線程使用預設的安全性描述元。
在Windows95中:SECURITY_ATTRIBUTES結構的lpSecurityDescriptor成員被忽略。
bInheritHandles:指示新進程是否從調用進程處繼承了控制代碼。如果參數的值為真,調用進程中的每一個可繼承的開啟控制代碼都將被子進程繼承。被繼承的控制代碼與原進程擁有完全相同的值和存取權限。
dwCreationFlags:指定附加的、用來控制優先類和進程的建立的標誌。以下的建立標誌可以以除下面列出的方式外的任何方式組合後指定。
值:CREATE_DEFAULT_ERROR_MODE
含義:新的進程不繼承調用進程的錯誤模式。CreateProcess函數賦予新進程當前的預設錯誤模式作為替代。應用程式可以調用SetErrorMode函數設定當前的預設錯誤模式。
這個標誌對於那些運行在沒有硬體錯誤環境下的多線程外殼程式是十分有用的。
對於CreateProcess函數,預設的行為是為新進程繼承調用者的錯誤模式。設定這個標誌以改變預設的處理方式。
值:CREATE_NEW_CONSOLE
含義:新的進程將使用一個新的控制台,而不是繼承父進程的控制台。這個標誌不能與DETACHED_PROCESS標誌一起使用。
值:CREATE_NEW_PROCESS_GROUP
含義:新進程將使一個進程樹的根進程。進程樹種的全部進程都是根進程的子進程。新進程樹的使用者識別碼與這個進程的標識符是相同的,由lpProcessInformation參數返回。進程樹經常使用GenerateConsoleCtrlEvent函數允許發送CTRL+C或CTRL+BREAK訊號到一組控制台進程。
值:CREATE_SEPARATE_WOW_VDM
含義:(只適用於Windows NT)這個標誌只有當運行一個16位的Windows應用程式時才是有效。如果被設定,新進程將會在一個私人的虛擬DOS機(VDM)中運行。另外,預設情況下所有的16位Windows應用程式都會在同一個共用的VDM中以線程的方式運行。單獨運行一個16位程式的優點是一個應用程式的崩潰只會結束這一個VDM的運行;其他那些在不同VDM中啟動並執行程式會繼續正常的運行。同樣的,在不同VDM中啟動並執行16位Windows應用程式擁有不同的輸入隊列,這意味著如果一個程式暫時失去響應,在獨立的VDM中的應用程式能夠繼續獲得輸入。
值:CREATE_SHARED_WOW_VDM
含義:(只適用於Windows NT)這個標誌只有當運行一個16位的Windows應用程式時才是有效。如果WIN.INI中的Windows段的DefaultSeparateVDM選項被設定為真,這個標識使得CreateProcess函數越過這個選項並在共用的虛擬DOS機中運行新進程。
值:CREATE_SUSPENDED
含義:新進程的主線程會以暫停狀態被建立,直到調用ResumeThread函數被調用時才運行。
值:CREATE_UNICODE_ENVIRONMENT
含義:如果被設定,由lpEnvironment參數指定的環境塊使用Unicode字元,如果為空白,環境塊使用ANSI字元。
值:DEBUG_PROCESS
含義:如果這個標誌被設定,調用進程將被當作一個偵錯工具,並且新進程會被當作被調試的進程。系統把被偵錯工具發生的所有調試事件通知給調試器。
如果你使用這個標誌建立進程,只有調用進程(調用CreateProcess函數的進程)可以調用WaitForDebugEvent函數。
值:DEBUG_ONLY_THIS_PROCESS
含義:如果此標誌沒有被設定且調用進程正在被調試,新進程將成為調試調用進程的調試器的另一個偵錯項目。如果調用進程沒有被調試,有關調試的行為就不會產生。
值:DETACHED_PROCESS
含義:對於控制台進程,新進程沒有訪問父進程式控制制台的許可權。新進程可以通過AllocConsole函數自己建立一個新的控制台。這個標誌不可以與CREATE_NEW_CONSOLE標誌一起使用。
dwCreationFlags參數還用來控制新進程的優先類,優先類用來決定此進程的線程調度的優先順序。如果下面的優先順序類標誌都沒有被指定,那麼預設的優先類是NORMAL_PRIORITY_CLASS,除非被建立的進程是IDLE_PRIORITY_CLASS。在這種情況下子進程的預設優先類是IDLE_PRIORITY_CLASS。
可以下面的標誌中的一個:
優先順序:HIGH_PRIORITY_CLASS
含義:指示這個進程將執行時間臨界的任務,所以它必須被立即運行以保證正確。這個優先順序的程式優先於正常優先順序或空閑優先順序的程式。一個例子是Windows工作清單,為了保證當使用者調用時可以立刻響應,放棄了對系統負荷的考慮。確保在使用高優先順序時應該足夠謹慎,因為一個高優先順序的CPU分支機構應用程式可以佔用幾乎全部的CPU可用時間。
優先順序:IDLE_PRIORITY_CLASS
含義:指示這個進程的線程只有在系統空閑時才會運行並且可以被任何高優先順序的任務打斷。例如螢幕保護裝置程式。空閑優先順序會被子進程繼承。
優先順序:NORMAL_PRIORITY_CLASS
含義:指示這個進程沒有特殊的任務調度要求。
優先順序:REALTIME_PRIORITY_CLASS
含義:指示這個進程擁有可用的最高優先順序。一個擁有即時優先順序的進程的線程可以打斷所有其他進程線程的執行,包括正在執行重要任務的系統進程。例如,一個執行時間稍長一點的即時進程可能導致磁碟緩衝不足或滑鼠反映遲鈍。
lpEnvironment:指向一個新進程的環境塊。如果此參數為空白,新進程使用調用進程的環境。
一個環境塊存在於一個由以NULL結尾的字串組成的塊中,這個塊也是以NULL結尾的。每個字串都是name=value的形式。
因為相等標誌被當作分隔字元,所以它不能被環境變數當作變數名。
與其使用應用程式提供的環境塊,不如直接把這個參數設為空白,系統磁碟機上的目前的目錄資訊不會被自動傳遞給新建立的進程。對於這個情況的探討和如何處理,請參見注釋一節。
環境塊可以包含Unicode或ANSI字元。如果lpEnvironment指向的環境塊包含Unicode字元,那麼dwCreationFlags欄位的CREATE_UNICODE_ENVIRONMENT標誌將被設定。如果塊包含ANSI字元,該標誌將被清空。
請注意一個ANSI環境塊是由兩個零位元組結束的:一個是字串的結尾,另一個用來結束這個快。一個Unicode環境塊石油四個零位元組結束的:兩個代表字串結束,另兩個用來結束塊。
lpCurrentDirectory:指向一個以NULL結尾的字串,這個字串用來指定子進程的工作路徑。這個字串必須是一個包含磁碟機名的絕對路徑。如果這個參數為空白,新進程將使用與調用進程相同的磁碟機和目錄。這個選項是一個需要啟動啟動應用程式並指定它們的磁碟機和工作目錄的外殼程式的主要條件。
lpStartupInfo:指向一個用於決定新進程的主表單如何顯示的STARTUPINFO結構體。
lpProcessInformation:指向一個用來接收新進程的識別資訊的PROCESS_INFORMATION結構體。
傳回值:
如果函數執行成功,返回非零值。
如果函數執行失敗,返回零,可以使用GetLastError函數獲得錯誤的附加資訊。
注釋:
CreateProcess函數用來運行一個新程式。WinExec和LoadModule函數依舊可用,但是它們同樣通過調用CreateProcess函數實現。
另外CreateProcess函數除了建立一個進程,還建立一個線程對象。這個線程將連同一個已初始化了的堆棧一起被建立,堆棧的大小由可執行檔的檔案頭中的描述決定。線程由檔案頭處開始執行。
新進程和新線程的控制代碼被以全域存取權限建立。對於這兩個控制代碼中的任一個,如果沒有安全性描述元,那麼這個控制代碼就可以在任何需要控制代碼類型作為參數的函數中被使用。當提供安全性描述元時,在接下來的時候當控制代碼被使用時,總是會先進行存取權限的檢查,如果存取權限檢查拒絕訪問,請求的進程將不能使用這個控制代碼訪問這個進程。
這個進程會被分配給一個32位的進程標識符。直到進程中止這個標識符都是有效。它可以被用來標識這個進程,或在OpenProcess函數中被指定以開啟這個進程的控制代碼。進程中被初始化了的線程一樣會被分配一個32位的線程標識符。這個標識符直到縣城中止都是有效且可以用來在系統中唯一標識這個線程。這些標識符在PROCESS_INFORMATION結構體中返回。
當在lpApplicationName或lpCommandLine參數中指定應用程式名稱時,應用程式名稱中是否包含副檔名都不會影響運行,只有一種情況例外:一個以.com為副檔名的MS-DOS程式或Windows程式必須包含.com副檔名。
調用進程可以通過WaitForInputIdle函數來等待新進程完成它的初始化並等待使用者輸入。這對於父進程和子進程之間的同步是極其有用的,因為CreateProcess函數不會等待新進程完成它的初始化工作。舉例來說,在試圖與新進程關聯的視窗之前,進程應該先調用WaitForInputIdle。
首選的結束一個進程的方式是調用ExitProcess函數,因為這個函數通知這個進程的所有動態連結程式庫(DLLs)程式已進入結束狀態。其他的結束進程的方法不會通知關聯的動態連結程式庫。注意當一個進程調用ExitProcess時,這個進程的其他縣城沒有機會運行其他任何代碼(包括關聯動態連結程式庫的終止代碼)。
ExitProcess, ExitThread, CreateThread, CreateRemoteThread,當一個進程啟動時(調用了CreateProcess的結果)是在進程中序列化進行的。在一段地址空間中,同一時間內這些事件中只有一個可以發生。這意味著下面的限制將保留:
*在進程啟動和DLL初始化階段,新的線程可以被建立,但是直到進程的DLL初始化完成前它們都不能開始運行。
*在DLL初始化或卸下常式中進程中只能有一個線程。
*直到所有的線程都完成DLL初始化或卸下後,ExitProcess函數才返回。
在進程中的所有線程都終止且進程所有的控制代碼和它們的線程被通過調用CloseHandle函數終止前,進程會留在系統中。進程和主線程的控制代碼都必須通過調用CloseHandle函數關閉。如果不再需要這些控制代碼,最好在建立進程後立刻關閉它們。
當進程中最後一個線程終止時,下列的事件發生:
*所有由進程開啟的對象都會關閉。
*進程的終止狀態(由GetExitCodeProcess函數返回)從它的初始值STILL_ACTIVE變為最後一個結束的線程的結束狀態。
*主線程的線程對象被設定為標誌狀態,供其他等待這個對象的線程使用。
*進程對象被設定為標誌狀態,供其他等待這個對象的線程使用。
假設當前在C盤上的目錄是/MSVC/MFC且有一個環境變數叫做C:,它的值是C:/MSVC/MFC,就像前面lpEnvironment中提到過的那樣,這樣的系統磁碟機上的目錄資訊在CreateProcess函數的lpEnvironment參數不為空白時不會被自動傳遞到新進程裡。一個應用程式必須手動地把目前的目錄資訊傳遞到新的進程中。為了這樣做,應用程式必須直接建立環境字串,並把它們按字母順序排列(因為Windows NT和Windows 95使用一種簡略的環境變數),並把它們放進lpEnvironment中指定的環境塊中。類似的,他們要找到環境塊的開頭,又要重複一次前面提到的環境塊的排序。
一種獲得磁碟機X的目前的目錄變數的方法是調用GetFullPathName("x:",..)。這避免了一個應用程式必須去掃描環境塊。如果返回的絕對路徑是X:/,就不需要把這個值當作一個環境資料去傳遞了,因為根目錄是磁碟機X上的新進程的預設目前的目錄。
由CreateProcess函數返回的控制代碼對於進程對象具有PROCESS_ALL_ACCESS的存取權限。
由lpcurrentDirectory參數指定的目前的目錄室子進程對象的目前的目錄。lpCommandLine參數指定的第二個項目是父進程的目前的目錄。
對於Windows NT,當一個進程在指定了CREATE_NEW_PROCESS_GROUP的情況下被建立時,一個對於SetConsoleCtrlHandler(NULL,True)的調用被用在新的進程上,這意味著對新進程來說CTRL+C是無效的。這使得上層的外科程式可以自己處理CTRL+C資訊並有選擇的把這些訊號傳遞給子進程。CTRL+BREAK依舊有效,並可被用來中斷進程/進程樹的執行。
安全注釋:
第一個參數lpApplicationName可能是空,這種情況下,可執行檔的名字必須在lpCommandLine中,lpCommandLine參數中可以包含空格。如果可執行檔或路徑中包含空格,那麼就會有執行不正確檔案的風險,這是由於這個函數解析空格的方法引起的。例如:下邊這個例子就很危險,因為它試圖運行Program.exe檔案,如果這個檔案存在,它就會代替MyApp.exe檔案的運行。
CreateProcess(NULL,”C://Program Files//MyApp.exe”,…….)
如果有惡意的使用者在系統編寫了一個名為Program.exe的檔案,那麼任何調用CreateProcess函數,且在檔案路徑中使用Program Files檔案夾的參數,都有可能會運行Program.exe檔案,而不是運行本來打算啟動並執行檔案。
要避免這個問題,可以不要將NULL值傳遞給lpApplicationName參數,或者在lpCommandLine中使用雙引號(轉義符)括起可執行檔的全路徑名,如下所示:
CreateProcess(NULL,”/”C://Program Files//MyApp.exe/” -L -S”,…….)
-L和-S是MyApp.exe可執行檔的參數。
最後要說明的一點是:在lpApplicationName中的參數和lpCommandLine中的第一個參數是一樣的,有人說顯得有些重複,其實這樣做純粹是一種被公認化了習慣!
參見
AllocConsole, CloseHandle, CreateRemoteThread, CreateThread, ExitProcess, ExitThread, GenerateConsoleCtrlEvent, GetCommandLine, GetEnvironmentStrings, GetExitCodeProcess, GetFullPathName, GetStartupInfo, GetSystemDirectory, GetWindowsDirectory, LoadModule, OpenProcess, PROCESS_INFORMATION, ResumeThread, SECURITY_ATTRIBUTES, SetConsoleCtrlHandler, SetErrorMode, STARTUPINFO, TerminateProcess, WaitForInputIdle, WaitForDebugEvent, WinExec
快捷資訊:
匯入庫:kernel32.lib
標頭檔:Winbase.h
簡單例子:
#include <iostream>
#include<windows.h>
using namespace std;
int main()
{
TCHAR szCmdLine[]={TEXT("d://test//te.exe")};//added by 江湖三腳貓 2009-4-28
STARTUPINFO si; //一些必備參數設定
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi; //必備參數設定結束
//lpCommandLine不能寫成"d://test//te.exe"常量形式 ,改成 TCHAR szCmdLine[]={"d://test//te.exe"}
//lpCommandLine需要改成 TCHAR szCmdLine[]={TEXT("d://test//te.exe")};
if(!CreateProcess(NULL,szCmdLine/*"d://test//te.exe"*/,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
//if(!CreateProcess(NULL,"d://test//te.exe",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) //"d://test//te.exe"是您要啟動並執行程式//的路徑
{
cout<<"Create Fail!"<<endl;
exit(1);
}
else
{
cout<<"Sucess!"<<endl;
}
return 0;
}
區別:
功能上: createprocess > shellexecute > winexec 複雜程度也是!
winexec() 只用於可執行檔,是一個老函數啦,雖然使用方便,但不推薦!(相容性也不好)
shellexcute()是通過windows外殼開啟任意檔案,非可執行檔自動通過關聯的程式開啟對於可執行檔,區別不大,不過shellexcute可以指定運行時的工作路徑
winexec() 必須有GetMessage或逾時之後才返回!CreateProcess和ShellExecute都是直接返回的!
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/duck04551/archive/2009/07/01/4312260.aspx