[轉]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。 

  返回值:

#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:who@mail.neu.edu.cn", nil, nil, SW_SHOWNORMAL);
  打開新郵件窗口,並自動填入收件人地址。若指定多個收件人地址,則收件人地址之間必須用分號或逗號分隔開(下同)
如:ShellExecute(this->m_hWnd, "open", "mailto:nishinapp@yahoo.com", "", "", SW_SHOW);
  格式三: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相同

  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:nishinapp@yahoo.com","","",       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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM