2016-02-12 61 views
3

我需要我的簡單程序幫助,該程序試圖創建運行語音識別的新進程。 當我打開cmd並輸入命令C:\Windows\Speech\Common\sapisvr.exe -SpeechUX時,語音識別將成功啓動。它即使在通過system(C:\\Windows\\...)運行時也會啓動,它基本上只是模仿cmd。 但是,如下所示使用CreateProcess()創建新進程時,該函數失敗。如果我把整個路徑和參數到第二個參數CreateProcess(NULL, TEXT("C:\\Windows...\\sapisvr.exe -SpeechUX"), ...),然後我得到一個運行時異常:訪問衝突寫入位置使用C++中的CreateProcess()啓動語音識別

#include <windows.h> 
int main() 
{ 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    ZeroMemory(&si, sizeof(si)); 
    si.cb = sizeof(si); 
    ZeroMemory(&pi, sizeof(pi)); 

    if (!CreateProcess(
    TEXT("C:\\Windows\\Speech\\Common\\sapisvr.exe"), //Module name 
    TEXT(" -SpeechUX"),  //command line params 
    NULL,  //Process attributes 
    NULL,  //Thread attributes 
    FALSE,  //Handle inheritance 
    0,   //No creation flags 
    NULL,  //Use parent's environment 
    NULL,  //Use parent's starting directory 
    &si,  //Pointer to STARTUPINFO structure 
    &pi))  //Pointer to PROCESS_INFORMATION structure 
    { 
     printf("error creating process\n"); 
     return 1; 
    } 

    WaitForSingleObject(pi.hProcess, INFINITE); 

    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread); 

    return 0; 
} 

首先,我試圖測試CreateProcess函數與參數運行記事本打開現有的文件。當我把notepad.exe的路徑放到命令行參數的第一個參數和文件名時,它沒有識別它,而是打開了一個新文件。

這整個適用於試圖從我的程序運行msconfig.exe,它不採取任何參數,所以我想這個問題是在別的地方,我只是不知道在哪裏。 我搜索了網頁,但沒有任何答案對我有用。我正在Windows 8.1上使用Visual Studio 2015。

感謝您的幫助。

+1

CreateProcess的第二個參數必須是可寫的緩衝區,而不是字符串文字。 – PaulMcKenzie

+0

@PaulMcKenzie:只有在調用'CreateProcessA()'時纔會調用'CreateProcessA()',而不是調用'CreateProcessA()'時調用。 –

回答

5

CreateProcess函數有第二個參數爲LPTSTR。對於該函數的CreateProcessW版本,這必須是可寫緩衝區,而不是字符串文字。因此你的程序的行爲是不確定的。由於您在致電CreateProcess時遇到寫入位置的訪問衝突,因此我們將假定CreateProcess正被映射到CreateProcessW

在張貼,這裏的鏈接是報價:

該函數的Unicode版本,CreateProcessW,可以修改這個字符串的內容。因此,此參數不能是指向只讀存儲器(例如常量變量或文字串)的指針。如果此參數是一個常量字符串,則該函數可能會導致訪問衝突。

所以修復被簡單地定義一個數組,而不是一個字面:

TCHAR commandParam[] = TEXT(" -SpeechUX"); 

if (!CreateProcess(TEXT("C:\\Windows\\Speech\\Common\\sapisvr.exe"), 
        commandParam, 
        ... 
    } 

,或者如果傳遞NULL作爲第一個參數:

TCHAR commandParam[] = TEXT("C:\\Windows\\Speech\\Common\\sapisvr.exe"); 
//... 
if (!CreateProcess(NULL, commandParam, ... 

此外,如果CreateProcess返回一個錯誤,你應該調用GetLastError和可選的FormatMessage,以獲得發生的錯誤,而不是簡單地輸出錯誤。

+0

謝謝,這是有道理的。但是我仍然在創建process_。即使試圖將整個路徑和參數放入commandParam,它也不起作用。 – MiragePV

+1

什麼是錯誤?你叫'GetLastError'嗎?你是否嘗試將整個命令*放在一個數組中*而不是作爲第二個參數的字符串文本(並將第一個參數保留爲NULL)? – PaulMcKenzie

+0

你確定這是正確的路徑嗎?另請參閱此http:// stackoverflow。com/questions/9890746/how-to-use-or-expand-environment-variables-in -a-command-instantiated-by-createpr –