【问题标题】:Starting Speech Recognition with CreateProcess() in C++在 C++ 中使用 CreateProcess() 启动语音识别
【发布时间】:2016-05-23 13:17:45
【问题描述】:

我的简单程序需要帮助,该程序试图创建一个运行语音识别的新进程。 当我打开 cmd 并输入命令 C:\Windows\Speech\Common\sapisvr.exe -SpeechUX 时,语音识别将成功启动。即使通过基本上只是模仿 cmd 的system(C:\\Windows\\...) 运行,它也会启动。 但是,当使用 CreateProcess() 如下创建新进程时,该函数会失败。如果我将整个路径和参数放入第二个参数CreateProcess(NULL, TEXT("C:\\Windows...\\sapisvr.exe -SpeechUX"), ...),则会出现运行时异常:访问冲突写入位置

#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。

感谢您的帮助。

【问题讨论】:

  • CreateProcess 的第二个参数必须是可写缓冲区,而不是字符串字面量。
  • @PaulMcKenzie:仅在调用CreateProcessW() 时,而不是在调用CreateProcessA() 时。

标签: c++ windows winapi process accessibility


【解决方案1】:

CreateProcess 函数有第二个参数为LPTSTR。对于此函数的CreateProcessW 版本,这必须是可写缓冲区,而不是字符串文字。因此,您的程序的行为是未定义的。由于您在调用CreateProcess 时遇到了写入某个位置的访问冲突,因此我们假设CreateProcess 被映射到CreateProcessW

在发布的链接中,引用如下:

此函数的 Unicode 版本 CreateProcessW 可以修改此字符串的内容。因此,这个参数不能是指向只读内存的指针(比如const变量或文字串)。如果此参数是一个常量字符串,该函数可能会导致访问冲突。

所以解决方法是简单地定义一个数组,而不是文字:

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,以获取发生的错误,而不是简单地输出有错误。

【讨论】:

  • 谢谢,这是有道理的。但我仍然收到错误创建过程。即使尝试将整个路径和参数放入 commandParam,它也不起作用。
  • 错误是什么?你打电话给GetLastError了吗?您是否尝试将整个命令 放在一个数组中,而不是作为第二个参数的字符串文字(并将第一个参数保留为 NULL)?
  • 您确定这是正确的路径吗?另见stackoverflow.com/questions/9890746/…
  • 是的,我试着把它全部放到第二个参数中,没有用。我得到的错误是 2 - 找不到指定的文件。但是可执行文件确实存在。会不会是 32/64 位的问题?
  • @PaulMcKenzie 我得到的错误不是 2(路径中有错字),而是 740 - 需要提升。但它不应该。无需管理员权限即可运行语音识别。
猜你喜欢
  • 2018-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多