2016-02-12 59 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 –