1. 程式人生 > >C++呼叫系統中應用程式的方法的整理總結

C++呼叫系統中應用程式的方法的整理總結

一、三個SDK函式: 

WinExec,ShellExecute ,CreateProcess可以實現呼叫其他程式的要求,其中以WinExec最為簡單,ShellExecute比WinExec靈活一些,CreateProcess最為複雜。
WinExec 兩個引數,前一個指定路徑,後一個指定顯示方式。
ShellExecute 可以指定工作目錄,並且還可以尋找檔案的關聯直接開啟不用載入與檔案關聯的應用程式,ShellExecute還可以開啟網頁,啟動相應的郵件關聯傳送郵件等等。
CreateProcess 一共有十個引數,不過大部分都可以用NULL代替,它可以指定程序的安全屬性,繼承資訊,類的優先順序等等。如果我們要得到足夠多的關於新的程序的資訊,控制新的程序的細節屬性,若要達到這些目的,我們就需要使用CreateProcess函數了。

1.winexec(String lpCmdLine,Long nCmdShow);

引數說明:

引數 型別及說明
lpCmdLine String,包含要執行的命令列
nCmdShow Long,為視窗指定可視性方面的一個命令。請用下述任何一個常數
SW_HIDE 隱藏視窗,活動狀態給令一個視窗
SW_MINIMIZE 最小化視窗,活動狀態給令一個視窗
SW_RESTORE
用原來的大小和位置顯示一個視窗,同時令其進入活動狀態
SW_SHOW 用當前的大小和位置顯示一個視窗,同時令其進入活動狀態
SW_SHOWMAXIMIZED 最大化視窗,並將其啟用
SW_SHOWMINIMIZED 最小化視窗,並將其啟用
SW_SHOWMINNOACTIVE 最小化一個視窗,同時不改變活動視窗
SW_SHOWNA 用當前的大小和位置顯示一個視窗,不改變活動視窗
SW_SHOWNOACTIVATE
用最近的大小和位置顯示一個視窗,同時不改變活動視窗
SW_SHOWNORMAL 與SW_RESTORE相同

例: winexec("c:\\a.txt",SW_SHOW);

2.ShellExecute

引數 型別及說明
hwnd Long,指定一個視窗的控制代碼,有時候,windows程式有必要在建立自己的主視窗前顯示一個訊息框
lpOperation String,指定字串“open”來開啟lpFlie文件,或指定“Print”來列印它
lpFile String,想用關聯程式列印或開啟一個程式名或檔名
lpParameters String,如lpszFlie是可執行檔案,則這個字串包含傳遞給執行程式的引數
lpDirectory String,想使用的完整路徑
nShowCmd Long,定義瞭如何顯示啟動程式的常數值。參考上表.

使用方法如下:
例:ShellExecute(Handle, ''open'', PChar(''c:\test\readme.txt''), nil, nil, SW_SHOW);
ShellExecute(NULL,"open","C://Test.txt",NULL,NULL,SW_SHOWNORMAL); // 開啟C:/Test.txt 檔案
ShellExecute(NULL, "open", "http://www.google.com",/ NULL, NULL, SW_SHOWNORMAL); // 開啟網頁www.google.com
ShellExecute(NULL,"explore", "D://C++",NULL,NULL,SW_SHOWNORMAL); // 開啟目錄D:/C++
ShellExecute(NULL,"print","C://Test.txt",NULL,NULL, SW_HIDE); // 列印檔案C:/Test.txt

3.CreateProcess

引數 型別及說明
lpApplicationName String,要執行的應用程式的名字。可設為vbNullString;在這種情況下,應用程式的名字應在lpCommandLine引數的起始處出現
lpCommandLine String,要執行的命令列。可用GetCommandLine函式取得一個程序使用的命令列。Windows會盡可能地根據下述搜尋順序來查詢執行檔案:
(1)包含了父程序執行檔案的目錄
(2)父程序當前的目錄
(3)由GetSystemDirectory返回的系統目錄
(4)僅適於windows NT:16位系統目錄
(5)由GetWindowDirectory返回的Windows目錄
(6)由PATH環境變數指定的目錄
lpProcessAttributes SECURITY_ATTRIBUTES,指定一個SECURITY_ATTRIBUTES結構,或傳遞零值(將引數宣告為ByVal As Long,並傳遞零值)——表示採用不允許繼承的預設描述符。該引數定義了程序的安全特性
lpThreadAttributes SECURITY_ATTRIBUTES,指定一個SECURITY_ATTRIBUTES結構,或傳遞零值(將引數宣告為ByVal As Long,並傳遞零值)——表示採用不允許繼承的預設描述符。該引數定義了程序之主執行緒的安全特性
bInheritHandles Long,TRUE表示允許當前程序中的所有控制代碼都由新建的子程序繼承
dwCreationFlags Long,來自API32.TXT檔案的一個或多個下述常數之一,它們都帶有字首CREATE_。下面這些用於VB程式設計師:
CREATE_SEPARATE_WOW_VDM(僅適用於NT) 啟動一個16位的Windows應用程式時,強迫它在自己的記憶體空間執行
CREATE_SHARED_WOW_VDM(僅適用於NT) 啟動一個16位的Windows應用程式時,強迫它在共享的16位虛擬機器(VM)內執行
CREATE_SUSPENDED 立即掛起新程序。除非呼叫了ResumeThread函式函式,否則它不會恢復執行
也可能是下述常數之一,用於指定優先順序
IDLE_PRIORITY_CLASS 新程序應該有非常低的優先順序——只有在系統空閒的時候才能執行。基本值是4
HIGH_PRIORITY_CLASS 新程序有非常高的優先順序,它優先於大多數應用程式。基本值是13。注意儘量避免採用這個優先順序
NORMAL_PRIORITY_CLASS 標準優先順序。如程序位於前臺,則基本值是9;如在後臺,則優先值是7
不要在VB中使用REALTIME_PRIORITY_CLASS
lpEnvironment Any,指向一個環境塊的指標(環境緩衝區的頭一個字元,或者環境塊的地址)
lpCurrentDriectory String,新程序的當前目錄路徑。呼叫函式的時候,可用vbNullString指定當前目錄
lpStartupInfo STARTUPINFO,指定一個STARTUPINFO結構,其中包含了建立程序時使用的附加資訊
lpProcessInformation

PROCESS_INFORMATION,該結構用於容納新程序的程序和執行緒識別符號。大多數情況下,一旦這個函式返回,父應用程式都會關閉兩個控制代碼。


---------------------------------------------------------------------------------------------------------

二、WinExec、ShellExecute和CreateProcess及返回值判斷方式

有三個API函式可以執行可執行檔案WinExec、ShellExecute和CreateProcess。CreateProcess因為使用複雜,比較少用。
  WinExec主要執行EXE檔案。
  ⑴ 函式原型: UINT Win Exec(LPCSTR lpCmdLine, UINT uCmdShow); 
  ⑵ 引數: 
  lpCmdLine:指向一個空結束的字串,串中包含將要執行的應用程式的命令列(檔名加上可選引數)。 
  uCmdShow:定義Windows應用程式的視窗如何顯示,併為CreateProcess函式提供STARTUPINFO引數的wShowWindow成員的值。
  ⑶ 返回值: 
  若函式呼叫成功,則返回值大於31。若函式呼叫失敗,則返回值為下列之一: 
  ① 0:系統記憶體或資源已耗盡。 
  ② ERROR_BAD_FORMAT:EXE檔案無效(非Win32.EXE或.EXE影像錯誤)。 
  ③ ERROR_FILE_NOT_FOUND:指定的檔案未找到。 
  ④ ERROR_PATH_NOT_FOUND:指定的路徑未找到。 
  雖然Microsoft認為WinExec已過時,但是在許多時候,簡單的WinExec函式仍是執行新程式的最好方式。簡單地傳送作為第一個引數的 命令列,還需要決定如何顯示程式(該程式也許會忽視它)的第二個引數。通常,將其設定為SW_SHOW,也可嘗試SW_MINIMIZED或 SW_MAXIMIZED。WinExec不允許用CreateProcess獲得的所有選項,而它的確簡單。

  ShellExecute不僅可以執行EXE檔案,也可以執行已經關聯的檔案。 
1、標準用法
  ShellExecute函式原型及引數含義如下: 
HINSTANCE ShellExecute(HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd);
  ●hWnd:用於指定父視窗控制代碼。當函式呼叫過程出現錯誤時,它將作為Windows訊息視窗的父視窗。例如,可以將其設定為應用程式主視窗控制代碼,即Application.Handle,也可以將其設定為桌面視窗控制代碼(用GetDesktopWindow函式獲得)。
  ●lpOperation:用於指定要進行的操作。其中“open”操作表示執行由FileName引數指定的程式,或開啟由FileName引數指定的檔案或資料夾;“print”操作表示列印由FileName引數指定的檔案;“explore”操作表示瀏覽由FileName引數指定的資料夾。當引數設為nil時,表示執行預設操作“open”。
  ●lpFileName:用於指定要開啟的檔名、要執行的程式檔名或要瀏覽的資料夾名。 
  ●lpParameters:若FileName引數是一個可執行程式,則此引數指定命令列引數,否則此引數應為nil或PChar(0)。 
  ●lpDirectory:用於指定預設目錄。 
  ●lpShowCmd:若FileName引數是一個可執行程式,則此引數指定程式視窗的初始顯示方式,否則此引數應設定為0。 
  返回值:

[cpp]view plain copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <windows.h>  
  4. #include <shellapi.h>  
  5.   
  6. int main( void )  
  7. {  
  8. HINSTANCE hNewExe = ShellExecuteA(NULL, "open""d:\\tese.log", NULL, NULL, SW_SHOW);  
  9. if ((DWORD)hNewExe <= 32)  
  10. {  
  11. printf("return value:%d\n", (DWORD)hNewExe);  
  12. }  
  13. else  
  14. {  
  15. printf("successed!\n");  
  16. }  
  17.    printf("GetLastError: %d\n", GetLastError());  
  18. system("pause");  
  19. return 1;  
  20. }  
  21.    
[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <windows.h>  
  4. #include <shellapi.h>  
  5.   
  6. int main( void )  
  7. {  
  8. HINSTANCE hNewExe = ShellExecuteA(NULL, "open""d:\\tese.log", NULL, NULL, SW_SHOW);  
  9. if ((DWORD)hNewExe <= 32)  
  10. {  
  11. printf("return value:%d\n", (DWORD)hNewExe);  
  12. }  
  13. else  
  14. {  
  15. printf("successed!\n");  
  16. }  
  17.    printf("GetLastError: %d\n", GetLastError());  
  18. system("pause");  
  19. return 1;  
  20. }  
  21.    


 當“D:\\test.log”檔案不存在是,執行結果如下:
  這裡若函式執行錯誤, GetLastError()不一定能捕獲到錯誤程式碼,例如當“d:\\tese.log”檔案存在,將記事本"notepad.exe"命名為其他名字時:
  另外兩個函式的返回值就不列出了。
2、特殊用法
  1)如果將FileName引數設定為“http:”協議格式,那麼該函式將開啟預設瀏覽器並連結到指定的URL地址。若使用者機器中安裝了多個瀏覽器,則該函式將根據Windows 9x/NT登錄檔中http協議處理程式(Protocols Handler)的設定確定啟動哪個瀏覽器。
  格式一:http://網站域名。       如:ShellExecute(handle, “open”, “http://www.neu.edu.cn”, nil, nil, SW_SHOWNORMAL);
  格式二:http://網站域名/網頁檔名。  如:ShellExecute(handle, “open”, “http://www.neu.edu.cn/default.htm”, nil, nil, SW_SHOWNORMAL);
  2)如果將FileName引數設定為“mailto:”協議格式,那麼該函式將啟動預設郵件客戶程式,如Microsoft Outlook(也包括Microsoft Outlook Express)或Netscape Messanger。若使用者機器中安裝了多個郵件客戶程式,則該函式將根據Windows 9x/NT登錄檔中mailto協議處理程式的設定確定啟動哪個郵件客戶程式。
  格式一:mailto:     如:ShellExecute(handle, "open", "mailto:", nil, nil, SW_SHOWNORMAL);開啟新郵件視窗。
  格式二:mailto:使用者賬號@郵件伺服器地址 如:ShellExecute(handle, "open", "mailto:[email protected]", nil, nil, SW_SHOWNORMAL);
  開啟新郵件視窗,並自動填入收件人地址。若指定多個收件人地址,則收件人地址之間必須用分號或逗號分隔開(下同)
如:ShellExecute(this->m_hWnd, "open", "mailto:[email protected]", "", "", SW_SHOW);
  格式三:mailto:使用者賬號@郵件伺服器地址?subject=郵件主題&body=郵件正文 
  如:ShellExecute(handle, "open", "mailto:[email protected]?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相同
  3、深入淺出ShellExecute 譯者:徐景周(原作:Nishant S)
Q: 如何開啟一個應用程式? 正如您所看到的,我並沒有傳遞程式的完整路徑。
  ShellExecute(this->m_hWnd, "open", "calc.exe", "", "", SW_SHOW);
或ShellExecute(this->m_hWnd, "open", "notepad.exe", "c:\\MyLog.log", "", SW_SHOW);
Q: 如何開啟一個同系統程式相關連的文件?
ShellExecute(this->m_hWnd, "open", "c:\\abc.txt", "", "", SW_SHOW); 
Q: 如何開啟一個網頁?
ShellExecute(this->m_hWnd, "open", "http://www.google.com", "", "", SW_SHOW); 
Q: 如何啟用相關程式,傳送EMAIL?
ShellExecute(this->m_hWnd,"open", "mailto:[email protected]","","", SW_SHOW ); 
Q: 如何用系統印表機列印文件?
ShellExecute(this->m_hWnd, "print", "c:\\abc.txt", "", "", SW_HIDE); 
Q: 如何用系統查詢功能來查詢指定檔案?
ShellExecute(m_hWnd, "find", "d:\\nish", NULL, NULL, SW_SHOW); 
Q: 如何啟動一個程式,直到它執行結束?
    SHELLEXECUTEINFO ShExecInfo = {0}; 
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); 
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; 
ShExecInfo.hwnd = NULL; 
ShExecInfo.lpVerb = NULL; 
ShExecInfo.lpFile = "c:\\MyProgram.exe"; 
ShExecInfo.lpParameters = ""; 
ShExecInfo.lpDirectory = NULL; 
ShExecInfo.nShow = SW_SHOW; 
ShExecInfo.hInstApp = NULL; 
ShellExecuteEx(&ShExecInfo); 
WaitForSingleObject(ShExecInfo.hProcess,INFINITE); 
  或:
PROCESS_INFORMATION ProcessInfo; 
STARTUPINFO StartupInfo; //This is an [in] parameter 
ZeroMemory(&StartupInfo, sizeof(StartupInfo)); 
StartupInfo.cb = sizeof(StartupInfo); //Only compulsory field 
if(CreateProcess("c:\\winnt\\notepad.exe", NULL, NULL,NULL,FALSE,0,NULL, NULL,&StartupInfo,&ProcessInfo))

WaitForSingleObject(ProcessInfo.hProcess,INFINITE); 
CloseHandle(ProcessInfo.hThread); 
CloseHandle(ProcessInfo.hProcess); 

else 

MessageBox("The process could not be started..."); 

  Q: 如何顯示檔案或資料夾的屬性?
SHELLEXECUTEINFO ShExecInfo = {0}; 
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); 
ShExecInfo.fMask = SEE_MASK_INVOKEIDLIST; 
ShExecInfo.hwnd = NULL; 
ShExecInfo.lpVerb = "properties"; 
ShExecInfo.lpFile = "c:\\"; //can be a file as well 
ShExecInfo.lpParameters = ""; 
ShExecInfo.lpDirectory = NULL; 
ShExecInfo.nShow = SW_SHOW; 
ShExecInfo.hInstApp = NULL; 
ShellExecuteEx(&ShExecInfo); 

使用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:指向一個以空結尾的串,他指定了要執行的模組 
  lpCommandLine:指向一個以空結尾的串,該串定義了要執行的命令列。 
  lpProcessAttributes:指向一個SECURITY_ATTRIBUTES結構,該結構決定了返回的控制代碼是否可被子程序繼承。 
  lpThreadAttributes:指向一個SECURITY_ATTRIBUTES結構,該結構決定了返回的控制代碼是否可被子程序繼承。 
  bInheritHandles,:表明新程序是否從呼叫程序繼承控制代碼。 
  dwCreationFlags:定義控制優先類和程序建立的附加標誌。 
  lpEnvironment:指向一個新程序的環境塊。 
  lpCurrentDirectory:指向一個以空結尾的串,該串定義了子程序的當前驅動器和當前目錄。 
  lpStartupInfo:指向一個STARTUPINFO結構,該結構定義了新程序的主視窗將如何顯示。 
  lpProcessInformation:指向PROCESS_INFORMATION結構,該結構接受關於新程序的表示資訊。 
  ⑶ 返回值: 
  若函式呼叫成功,則返回值不為0;若函式呼叫失敗,返回值為0。 
  在上述引數中,引數lpStartupInfo是STARTUPINFO結構。可以用來設定控臺的標題,新視窗的的初始大小和位置,及重定向標準輸入 和輸出。新程式通常可以忽略多數這些資料項,如果選擇那樣做的話。可以規定該結構體中的標誌,已表明要設定的資料段。有時,不想設定任何資訊,也必須傳遞 一個有效的指標給空結構(確定設定大小到cb,及設定dwFlags成員為0)。引數lpProcessInformation返回程序和執行緒控制代碼,還包 括程序和執行緒ID。這些控制代碼擁有在引數lpProcessAttributes和lpThreadAttributes中規定的訪問。
  要注意,針對CreateProcess的一些引數對控制檯應用程式是特定的,而其它引數則對各種應用程式有用。大多數情況下,並不一定要填入 STARTUPINFO結構,但無論如何必須提供它。其返回值是布林型的,而真正感興趣的返回值發生於作為引數傳送的結構中 (PROCESS_INFORMATION)。CreateProcess返回該結構中的程序ID及其控制代碼,以及初始執行緒ID及其控制代碼。可以將ID傳送到 其它程序,或使用控制代碼來控制新程序。
  ShellExecute和WinExec命令用於簡單的作業。如果要完全控制一個新程序,就必須呼叫CreateProcess。 

---------------------------------------------------------------------------------------------------------

三、注意事項

1、定義標頭檔案

在標頭檔案stdafx.h中必須定義以下兩個標頭檔案:

#include <shlobj.h> // 可替換為 windows.h
#include <shellapi.h>
如果定義了標頭檔案 #include <windows.h>的話就不必定義 #include <shlobj.h>了,"windows.h" 不光是包含了"shellapi.h",它還定義了許多資料型別,如果沒有這些資料型別,shellapi.h本身會出錯。

2 ShellExecute是非同步執行的,也就是說,不管執行的程式是否成功執行,執行的時間是長是短,ShellExecute函式都會立即返回

3可以使用system()來執行cmd命令

4可以用ShellExecute 和 批處理完成同步執行。