#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"字符串放在只讀內存中:
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之前,把常量字符串復制到一個臨時緩沖區,如下所示:
TCHAR szCommandLine[] = TEXT("NOTEPAD"); CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
涉及的字符關系:
char* 替換: LPSTR
const char* 替換: LPCSTR
WCHAR* 替換: LPWSTR
const WCHAR* 替換: LPCWSTR (C在W之前, 因為 const 在 WCHAR之前)
TCHAR* 替換: LPTSTR
const TCHAR* 替換: LPCTSTR