1. 程式人生 > >VC++呼叫EXE檔案的方法 (WinExc,ShellExcute,CreateProcess)

VC++呼叫EXE檔案的方法 (WinExc,ShellExcute,CreateProcess)

VC中呼叫其他程式的方法一般有三種,分別利用三個API函式WinExec,ShellExecute ,CreateProcess。其中WinExec最簡單,但較老;ShellExecute簡單靈活,較為實用; CreateProcess則控制比較全面,但是較為複雜。下面分別介紹一下這三種方法。

使用WinExec命令

  ⑴ 函式原型:

UINT WinExec(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命令

  1. 函式功能:

你可以給它任何檔案的名字,它都能識別出來並開啟它。

2.函式原型:


HINSTANCE ShellExecute(


HWND hwnd,


LPCTSTR lpOperation, 字串7


LPCTSTR lpFile,

LPCTSTR lpParameters,

LPCTSTR lpDirectory, 字串2

INT nShowCmd 字串5

); 字串5

3.引數說明:

hwnd: 字串3

用於指定父視窗控制代碼。當函式呼叫過程出現錯誤時,它將作為Windows訊息視窗的父視窗。

lpOperation:

用於指定要進行的操作。 字串4

“open”操作表示執行由lpFile引數指定的程式,或開啟由lpFile引數指定的檔案或資料夾;

“print”操作表示列印由lpFile引數指定的檔案;


“explore”操作表示瀏覽由lpFile引數指定的資料夾。


當引數設為NULL時,表示執行預設操作“open”。


lpFile:

用於指定要開啟的檔名、要執行的程式檔名或要瀏覽的資料夾名。





lpParameters: 字串6


若lpFile引數是一個可執行程式,則此引數指定命令列引數,否則此引數應為NULL.

lpDirectory: 字串3

用於指定預設目錄.





nShowCmd:

若lpFile引數是一個可執行程式,則此引數指定程式視窗的初始顯示方式,否則此引數應設定為0。





這個引數常用的常數:

SW_HIDE 隱藏視窗,活動狀態給令一個視窗 字串5

SW_MINIMIZE 最小化視窗,活動狀態給令一個窗




SW_RESTORE 用原來的大小和位置顯示一個視窗,同時令其進入活動狀態


SW_SHOW 用當前的大小和位置顯示一個視窗,同時令其進入活動狀態





SW_SHOWMAXIMIZED 最大化視窗,並將其啟用 字串6

SW_SHOWMINIMIZED 最小化視窗,並將其啟用 字串3

SW_SHOWMINNOACTIVE 最小化一個視窗,同時不改變活動視窗 字串7

SW_SHOWNA 用當前的大小和位置顯示一個視窗,不改變活動視窗 字串9

SW_SHOWNOACTIVATE 用最近的大小和位置顯示一個視窗,同時不改變活動視窗




SW_SHOWNORMAL 與SW_RESTORE相同


若ShellExecute函式呼叫成功,則返回值為被執行程式的例項控制代碼。若返回值小於32,則表示出現錯誤。

4.使用方法:


例如:


ShellExecute(NULL,"open","iloveu.bmp",NULL,NULL,SW_SHOWNORMAL);

用預設的點陣圖編輯器開啟一個叫iloveu.bmp的點陣圖檔案,這個預設的點陣圖編輯器可能是 Microsoft Paint, Adobe Photoshop, 或者 Corel PhotoPaint。

這個函式能開啟任何檔案,甚至是桌面和URL快捷方式( .ink或 .url)。ShellExecute解析系統登錄檔HKEY_CLASSES_ROOT中所有的內容,判斷啟動那一個執行程式,並且啟動一個新的例項或使用DDE將檔名連到一開啟的例項。然後,ShellExecute 返回開啟檔案的應用的例項控制代碼。 字串7

ShellExecute(NULL, "open", "http://www.microsoft.com", NULL, NULL, SW_SHOWNORMAL);





這個程式碼使你能訪問微軟的主頁。當ShellExecute遇到檔名前面的“http:”時,可以判斷出要開啟的檔案是Web檔案,隨之啟動Internet Explorer 或者 Netscape Navigator 或者任何你使用的別的瀏覽器開啟檔案。

ShellExecute還能識別其它協議,象FTP、GOPHER。甚至識別“mailto”,如果檔名指向“mailto:
[email protected]
”,它啟動電子郵件程式並開啟一個待編輯的新郵件,例如:字串8

ShellExecute(NULL, "open",“mailto:[email protected]”, NULL, NULL, SW_SHOWNORMAL);開啟新郵件視窗。




總之,ShellExecute函式就是如此簡單地開啟磁碟檔案和Internet檔案。如果將第二個引數“OPEN”改為“PRINT”或者“EXPLORE”,ShellExecute將能列印檔案和開啟資料夾。ShellExecute還有一個擴充套件函式ShellExecuteEx,所帶引數中有一個特殊的結構,功能更強,或者任何你使用的別的瀏覽器開啟檔案。

使用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。

  ShellExecute和WinExec命令用於簡單的作業。如果要完全控制一個新程序,就必須呼叫CreateProcess。

  在上述引數中,引數lpStartupInfo是STARTUPINFO結構。可以用來設定控臺的標題,新視窗的的初始大小和位置,及重定向標準輸入和輸出。新程式通常可以忽略多數這些資料項,如果選擇那樣做的話。可以規定該結構體中的標誌,已表明要設定的資料段。有時,不想設定任何資訊,也必須傳遞一個有效的指標給空結構(確定設定大小到cb,及設定dwFlags成員為0)。引數lpProcessInformation返回程序和執行緒控制代碼,還包括程序和執行緒ID。這些控制代碼擁有在引數lpProcessAttributes和lpThreadAttributes中規定的訪問。

  要注意,針對CreateProcess的一些引數對控制檯應用程式是特定的,而其它引數則對各種應用程式有用。大多數情況下,並不一定要填入STARTUPINFO結構,但無論如何必須提供它。其返回值是布林型的,而真正感興趣的返回值發生於作為引數傳送的結構中(PROCESS_INFORMATION)。CreateProcess返回該結構中的程序ID及其控制代碼,以及初始執行緒ID及其控制代碼。可以將ID傳送到其它程序,或使用控制代碼來控制新程序。

關於三個API函式: WinExec, ShellExecute,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、定義路徑
C++中所表示的路徑要用 " \\ "而不是平常所用的" \ ",所以以上三個函式表示路徑都為:
Disk:\\Directory\\...\\File name
WinExec("D:\\Program Files\\Test\\Test.exe",SW_SHOWMAXIMIZED);
ShellExecute(NULL,"open","C:\\Test.txt",NULL,NULL,SW_SHOWNORMAL);
bool fRet=CreateProcess("D:\\putty.exe",NULL,NULL,FALSE,NULL,NULL,NULL,NULL,&si,&pi);



例如,開啟一個圖片檔案test.jpg有幾種簡單的開啟方式。

::WinExec(

"D:\\ACDSee\\ACDSee9.exe \"F:\\code\\Visual C++\\Open_Exam1\\test.jpg\"",

//或者" ACDSee9.exe C:\\test.jpg",

SW_SHOW);



::ShellExecute(NULL,

"open",

"\"F:\\code\\Visual C++\\Open_Exam1\\test.jpg\"",

//或者” C:\\test.jpg”,

NULL,

NULL,

SW_SHOWNORMAL);



::ShellExecute(NULL,

"open",

" D:\\ACDSee\\ ",

//或者” ACDSee9.exe”,

"\"F:\\code\\Visual C++\\Open_Exam1\\test.jpg\"",

//或者” C:\\test.jpg”,

NULL,

SW_SHOWNORMAL);

注意:

1、 WinExec中第一個引數為ACDSee.exe的完全路徑,也可以直接用” ACDSee9.exe”做引數,因為它已經註冊到windows系統當中了。

2、 在寫要開啟的檔案的路徑時,如果路徑中有空格,應該用引號將其括起來,即再在外層包一層引號。

3、 ShellExecute可以有兩種方式開啟test.jpg檔案,一種是直接test.jpg開啟,它會預設用ACDSee開啟;另一種是先呼叫ACDSee軟體,再開啟檔案。這兩種方式在介面上有一點區別,視需求而定。

附:ShellExecute與ShellExecuteEx的用法

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);