0x01 ShellExecutehtml
ShellExecute的功能是運行一個外部程序(或者是打開一個已註冊的文件、打開一個目錄、打印一個文件等等),並對外部程序有必定的控制。
函數原型:chrome
ShellExecute( hWnd: HWND; //父窗口句柄 Operation: PChar; //動做, 譬如: open、print FileName: PChar; //要打開的文件或程序 Parameters: PChar; //當lpOperation爲「explore」時指定要傳遞的參數,一般設爲NULL Directory: PChar; //缺省目錄 ShowCmd: Integer //文件打開的方式,以一般方式仍是最大化或最小化顯示,通常爲SW_SHOWNORMAL ): HINST; {執行成功會返回應用程序句柄; 若是這個值 <= 32, 表示執行錯誤}
參數說明:
●hWnd:用於指定父窗口句柄。當函數調用過程出現錯誤時,它將做爲Windows消息窗口的父窗口。例如,能夠將其設置爲應用程序主窗口句柄,即Application.Handle,也能夠將其設置爲桌面窗口句柄(用GetDesktopWindow函數得到)。shell
●Operation:用於指定要進行的操做。其中「open」操做表示執行由FileName參數指定的程序,或打開由FileName參數指定的文件或文件夾;「print」操做表示打印由FileName參數指定的文件;「explore」操做表示瀏覽由FileName參數指定的文件夾。當參數設爲nil時,表示執行默認操做「open」。windows
●FileName:用於指定要打開的文件名、要執行的程序文件名或要瀏覽的文件夾名。瀏覽器
●Parameters:若FileName參數是一個可執行程序,則此參數指定命令行參數,不然此參數應爲nil或PChar(0)。緩存
●Directory:用於指定默認目錄。安全
●ShowCmd:若FileName參數是一個可執行程序,則此參數指定程序窗口的初始顯示方式,不然此參數應設置爲0。服務器
//ShowCmd 參數可選值: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}
若ShellExecute函數調用成功,則返回值爲被執行程序的實例句柄。若返回值小於32,則表示出現錯誤。多線程
//返回值可能的錯誤有: = 0 {內存不足} ERROR_FILE_NOT_FOUND = 2; {文件名錯誤} ERROR_PATH_NOT_FOUND = 3; {路徑名錯誤} ERROR_BAD_FORMAT = 11; {EXE 文件無效} SE_ERR_SHARE = 26; {發生共享錯誤} SE_ERR_ASSOCINCOMPLETE = 27; {文件名不徹底或無效} SE_ERR_DDETIMEOUT = 28; {超時} SE_ERR_DDEFAIL = 29; {DDE 事務失敗} SE_ERR_DDEBUSY = 30; {正在處理其餘 DDE 事務而不能完成該 DDE 事務} SE_ERR_NOASSOC = 31; {沒有相關聯的應用程序}
使用:
//啓動計算器 ShellExecute(NULL,"open","calc.exe",NULL,NULL,SW_SHOWNORMAL);
特殊用法:
若是將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’,NULL, NULL, SW_SHOWNORMAL);打開新郵件窗口,並自動填入收件人地址、郵件主題和郵件正文。若郵件正文包括多行文本,則必須在每行文本之間加入換行轉義字符%0a。 例子(delphi): 在一個應用程序調用c:\Project1.exe; ShellExecute(handle, 'open',"c:\Project1.exe",'字串內容',NULL, 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相同
#include<windows.h> #include<stdio.h> int main() { //打開記事本 //ShellExecuteA(NULL, "open", "notepad.exe", NULL, NULL, SW_SHOWNORMAL); //使用notepad.exe 打開指定文本,參數不要忘記加'\' //ShellExecute(NULL, "open", "notepad.exe", "F:\\雜文件\\test.txt", NULL, SW_SHOWNORMAL); //Unicode版本 //ShellExecute(NULL, TEXT("open"),TEXT( "notepad.exe"), TEXT("F:\\雜文件\\test.txt"), NULL, SW_SHOWNORMAL); ShellExecute(NULL, TEXT("open"), TEXT("C:\\Program Files\\Internet Explorer\\iexplore.exe"), TEXT("https://www.cnblogs.com/"), NULL, SW_SHOWNORMAL); //ShellExecute(NULL, TEXT("open"), TEXT("C:\\Program Files (x86)\\Google\Chrome\\Application\\chrome.exe"), TEXT("bbs.cnhonker.com"), NULL, SW_SHOWNORMAL); scanf("%*d"); return 0; }
0x01 WinExec
函數原型:
WinExec( lpCmdLine: LPCSTR; {文件名和參數; 如沒指定路徑會按如下順序查找: 程序目錄/當前目錄/System32/Windows/PATH環境變量} uCmdShow: UINT {啓動選項} ): UINT; //運行指定的程序
函數參數:
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}
0x03 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可執行文件的參數。
區別:
winexec() 只用於可執行文件,是一個老函數啦,雖然使用方便,但不推薦!(兼容性也很差)
shellexcute()是經過windows外殼打開任意文件,非可執行文件自動經過關聯的程序打開對於可執行文件,區別不大,不過shellexcute能夠指定運行時的工做路徑
winexec() 必須有GetMessage或超時以後才返回!CreateProcess和ShellExecute都是直接返回的!
參考:https://www.cnblogs.com/Lthis/p/4245341.html https://www.cnblogs.com/xubin0523/archive/2012/11/01/2749729.html