標籤:des style blog http io color ar os 使用
[轉]WinExec、ShellExecute和CreateProcess及傳回值判斷方式
http://www.cnblogs.com/ziwuge/archive/2012/03/12/2392472.html
有三個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。
傳回值:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <shellapi.h>
int main( void )
{
HINSTANCE hNewExe = ShellExecuteA(NULL, "open", "d:\\tese.log", NULL, NULL, SW_SHOW);
if ((DWORD)hNewExe <= 32)
{
printf("return value:%d\n", (DWORD)hNewExe);
}
else
{
printf("successed!\n");
}
printf("GetLastError: %d\n", GetLastError());
system("pause");
return 1;
}
當“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、WinExec、ShellExecute和CreateProcess
2、WINEXEC, SHELLEXECUTE, CREATEPROCESS
[轉]WinExec、ShellExecute和CreateProcess及傳回值判斷方式