1. 程式人生 > >Win32 API程式設計:使用CreateProcess建立新程序

Win32 API程式設計:使用CreateProcess建立新程序

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

#include <windows.h>

#include <tchar.h>

#include <stdio.h>

int main(int argc, char* argv[])

{

TCHAR szCommandLine[] = TEXT(

"NOTEPAD");//或者WCHAR

//LPWSTR szCommandLine = TEXT("NOTEPAD");//錯誤

//STARTUPINFO si = { sizeof(si) };

STARTUPINFO si;

PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));

si.cb = sizeof(si);

ZeroMemory(&pi, sizeof(pi));

si.dwFlags = STARTF_USESHOWWINDOW;  

// 指定wShowWindow成員有效

si.wShowWindow = TRUE;          // 此成員設為TRUE的話則顯示新建程序的主視窗,

// 為FALSE的話則不顯示

BOOL bRet = ::CreateProcess (

NULL,           // 不在此指定可執行檔案的檔名

szCommandLine,      // 命令列引數

NULL,           // 預設程序安全性

NULL,           // 預設執行緒安全性

FALSE,          // 指定當前程序內的控制代碼不可以被子程序繼承

CREATE_NEW_CONSOLE, // 為新程序建立一個新的控制檯視窗

NULL,           // 使用本程序的環境變數

NULL,           // 使用本程序的驅動器和目錄

&si,

&pi);

if(bRet)

{

WaitForSingleObject(pi.hProcess, INFINITE);

// 既然我們不使用兩個控制代碼,最好是立刻將它們關閉

::CloseHandle (pi.hThread);

::CloseHandle (pi.hProcess);

printf(" 新程序的程序ID號:%d \n", pi.dwProcessId);

printf(" 新程序的主執行緒ID號:%d \n", pi.dwThreadId);

}

return 0;

}

在呼叫CreatePricess的前兩個引數:pszApplicationName和pszCommandLine時可能崩潰的問題:

pszApplicationName和pszCommandLine引數分別指定新程序要使用的執行體檔案的名稱,以及要傳給新程序的命令列字串。先來談談pszCommandLine引數。 注意,pszCommandLine引數被原型化為一個PTSTR。這意味著CreateProces期望你傳入的是一個非“常量字串”的地址。在內部,CreateProcess實際上會修改你傳給它的命令列字串。但在CreateProcess返回之前,它會將這個字串還原為原來的形式。 這是很重要的,因為如果命令列字串包含在你的檔案映像的只讀部分,就會引起訪問衝突(違例)。例如,以下程式碼就會導致衝突,因為Microsoft的C/C++編譯器把"NOTEPAD"字串放在只讀記憶體中:

1

2

3

4

STARTUPINFO si = { sizeof(si) };

PROCESS_INFORMATION pi;

CreateProcess(NULL, TEXT("NOTEPAD"), NULL, NULL,

FALSE, 0, NULL, NULL, &si, &pi);

CreateProcess試圖修改字串時,會引起一個訪問衝突(Microsoft C/C++編譯器的早期版本把字串放在可讀/寫記憶體中。所以對CreateProcess函式的呼叫不會引起訪問衝突)。

解決這個問題的最佳方式是:在呼叫CreateProcess之前,把常量字串複製到一個臨時緩衝區,如下所示:  

1

2

3

TCHAR szCommandLine[] = TEXT("NOTEPAD");

CreateProcess(NULL, szCommandLine, NULL, NULL,

FALSE, 0, NULL, NULL, &si, &pi);

涉及的字元關係:

char* 替換: LPSTRconst char* 替換: LPCSTRWCHAR* 替換: LPWSTRconst WCHAR* 替換: LPCWSTR (C在W之前, 因為 const 在 WCHAR之前)TCHAR* 替換: LPTSTRconst TCHAR* 替換: LPCTSTR

在呼叫CreatePricess的前兩個引數:pszApplicationName和pszCommandLine時可能崩潰的問題:

pszApplicationName和pszCommandLine引數分別指定新程序要使用的執行體檔案的名稱,以及要傳給新程序的命令列字串。先來談談pszCommandLine引數。 注意,pszCommandLine引數被原型化為一個PTSTR。這意味著CreateProces期望你傳入的是一個非“常量字串”的地址。在內部,CreateProcess實際上會修改你傳給它的命令列字串。但在CreateProcess返回之前,它會將這個字串還原為原來的形式。 這是很重要的,因為如果命令列字串包含在你的檔案映像的只讀部分,就會引起訪問衝突(違例)。例如,以下程式碼就會導致衝突,因為Microsoft的C/C++編譯器把"NOTEPAD"字串放在只讀記憶體中:

1

2

3

4

STARTUPINFO si = { sizeof(si) };

PROCESS_INFORMATION pi;

CreateProcess(NULL, TEXT("NOTEPAD"), NULL, NULL,

FALSE, 0, NULL, NULL, &si, &pi);

CreateProcess試圖修改字串時,會引起一個訪問衝突(Microsoft C/C++編譯器的早期版本把字串放在可讀/寫記憶體中。所以對CreateProcess函式的呼叫不會引起訪問衝突)。

解決這個問題的最佳方式是:在呼叫CreateProcess之前,把常量字串複製到一個臨時緩衝區,如下所示:  

1

2

3

TCHAR szCommandLine[] = TEXT("NOTEPAD");

CreateProcess(NULL, szCommandLine, NULL, NULL,

FALSE, 0, NULL, NULL, &si, &pi);

涉及的字元關係:

char* 替換: LPSTRconst char* 替換: LPCSTRWCHAR* 替換: LPWSTRconst WCHAR* 替換: LPCWSTR (C在W之前, 因為 const 在 WCHAR之前)TCHAR* 替換: LPTSTRconst TCHAR* 替換: LPCTSTR

關閉 TerminateProcess(pi.hProcess,0);