最近項目中踩到了兩個坑:
一個是CreateProcess中參數含有路徑,但是沒有使用雙引號引起來。
一個是CreateProcess中路徑沒有使用4個反斜槓,只是用了2個導致命令行解析錯誤。
(1)路徑含有空格
這個問題應該比較簡單的,也很好測試出來,在XP系統上很多路徑都會帶有空格,只需要在含有路徑的參數上加上雙引號即可。
const int cmdlineBufferMaxLength = 8190;
WCHAR szCmdLine[cmdlineBufferMaxLength + 1] = { 0 };
std::wstring strPathParam = L"C:\\Program Files\\Windows NT\\";
StringCchPrintf(szCmdLine, cmdlineBufferMaxLength, L"d:\\CreateProcessDemo.exe --pathparam=\"%s\"", strPathParam.c_str());
CreateProcessW(NULL, (LPTSTR)szCmdLine, NULL, NULL, TRUE, NULL, NULL, NULL, &startupinfo, &pinfo));
注意上方代碼標紅的雙引號。
(2)參數中含有路徑,導致命令行解析錯誤
const int cmdlineBufferMaxLength = 8190;
WCHAR szCmdLine[cmdlineBufferMaxLength + 1] = { 0 };
std::wstring strPathParam = L"D:\\unit_tests\\";
StringCchPrintf(szCmdLine, cmdlineBufferMaxLength, L"d:\\CreateProcessDemo.exe --pathparam=\"%s\" --otherparam=xxx", strPathParam.c_str());
CreateProcessW(NULL, (LPTSTR)szCmdLine, NULL, NULL, TRUE, NULL, NULL, NULL, &startupinfo, &pinfo);
你們看這個代碼有問題嗎?可以自己寫代碼驗證一下,確實是有問題的。
問題就在於代碼代碼最終生成的szCmdLine是這樣子的:
d:\CreateProcessDemo.exe --pathparam="D:\unit_tests\" --otherparam=xxx
這個命令行中最後的一個反斜槓在CreateProcessDemo進程中會當做代碼使用,最終就變成了下面這樣
\" 就被轉移成雙引號,作爲整個字符串的一部分了,導致後面的參數--otherparam=xxx沒有被解析出來。
CreateProcessDemo中是這樣寫代碼驗證的:
int num_args = 0;
wchar_t** args = NULL;
args = ::CommandLineToArgvW(GetCommandLineW(), &num_args);
所以正確的做法是把strPathParam變量定義改成這樣:
std::wstring strPathParam = L"D:\\\\unit_tests\\\\";
bug就這樣解決了。
後面自己又測試了下,發現如果路徑中沒有最後一個反斜槓也是沒有問題的,類似這樣:
std::wstring strPathParam = L"D:\\unit_tests";
因爲沒有那個轉移雙引號的邏輯了。
雖然可以成功,但是嚴謹,確保萬無一失還是在路徑中加入四個反斜槓吧。