【问题标题】:passing arguments to cmd using CreateProcess function [duplicate]使用 CreateProcess 函数将参数传递给 cmd [重复]
【发布时间】:2021-08-29 07:27:32
【问题描述】:

我正在使用 Visual Studio 2019 社区在 Windows 上工作。我正在用 C++ 编写一个 MFC 应用程序,我正在尝试将以下命令行 txt2pdf -i\".\textfile.txt\" -o\".\pdfout.pdf\" 传递给 cmd。

为此,我使用CreateProcess() 函数,文档是herethis 是一个使用示例。我的代码如下:

void CMFCApplication4Dlg::OnBnClickedButton1()
{
    PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter

    STARTUPINFO StartupInfo; //This is an [in] parameter

    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    StartupInfo.cb = sizeof StartupInfo; //Only compulsory field

    LPWSTR cmd_args = (LPWSTR)"txt2pdf.exe - i\".textfile.txt\" -o\".pdfout.pdf\"";

    if (!CreateProcess(NULL, cmd_args, NULL, NULL, FALSE, 0, NULL,
        NULL, &StartupInfo, &ProcessInfo))
    {
        WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);

        MessageBox(L"Success");
    }
    else
    {
        MessageBox(L"The process could not be started...");
    }
}

我已经看到很多关于如何调用CreateProcess() 函数的解决方案和示例,我在下面列出了它们,但由于某种原因,它们都不起作用,我总是收到相同的错误消息:

Exception thrown at 0x759FF4BB (KernelBase.dll) in MFCApplication4.exe: 0xC0000005: Access violation writing location 0x00257960.

当我在网上查找时,我没有找到任何与我的代码相关的内容。

我尝试过的其他解决方案:

  1. solution01
  2. solution02
  3. solution03
  4. solution04

如何修复我的代码?

【问题讨论】:

  • 您似乎不了解您的代码。与你的问题相反,你实际上并没有将任何东西传递给命令处理器(你也不应该)。无论如何,“它不起作用” 不是可操作的问题陈述。请注意,您对CreateProcess 的呼叫是错误的。第二个参数需要是一个指向 non-const 字符串的指针。
  • 你观察到的错误是违反documented合约的结果:"lpCommandLine: [...] 这个函数的Unicode版本,CreateProcessW,可以修改内容此字符串。因此,此参数不能是指向只读内存的指针(如 const 变量或文字字符串)。如果此参数为常量字符串,则函数可能会导致访问冲突。"
  • 还有很多个问题,比如使用\t(编码TAB字符),或者依赖当前的工作目录。
  • @IInspectable 谢谢你的评论,我已经更新了代码,但我仍然得到同样的错误。我在传递参数时遇到问题,也许我不完全理解如何使字符串成为非 const 以及如何编码 cmd 所需但在代码中使用时出现问题的 " 字符。你有没有机会告诉我如何传递这些参数?谢谢
  • 盲目地抛弃 const-ness 并不能解决任何问题。它只是让编译器沉默,欺骗它接受谎言。这仍然是一个谎言,操作系统会让你知道。此外,将.\t 更改为.t 并不是您的本意。您应该转义反斜杠,例如.\\t。不过,再一次,依赖当前的工作目录不会成为解决任何问题的易处理的解决方案。如果您想解决访问违规问题,这里已经有很多问答。

标签: c++ visual-studio cmd mfc child-process


【解决方案1】:

作为documented,如果lpApplicationName为空,则在lpCommandLine中提供
它是用空格分隔的

CreateProcess(NULL, _T(" txt2pdf -i\".\textfile.txt\" -o\".\pdfout.pdf\""), // <-- white space is the first char

这意味着 appName 仅缺少参数
从 args 的开头删除空格
先提供lpApplicationName,然后提供空格,然后提供如下参数:

CreateProcess(NULL, _T("txt2pdf.exe -i\".\textfile.txt\" -o\".\pdfout.pdf\""),
// lpApplicationName----^^^^^^^^^  ^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// white space delimiter-----------|  |
// arguments--------------------------|

确保lpCommandLine 是非常量的,因为函数可以修改它

TCHAR cmd_args[] = _T("txt2pdf.exe -i\".\textfile.txt\" -o\".\pdfout.pdf\"");
CreateProcess(NULL, cmd_args,

【讨论】:

  • 感谢您的回答,不幸的是,我遇到了与Exception thrown at 0x759FF4BB (KernelBase.dll) in MFCApplication4.exe: 0xC0000005: Access violation writing location 0x00098F4E. 相同类型的错误,也许您知道这是什么意思?
  • @E.Ginzburg 你在为 UNICODE 编译吗?鉴于您的原始示例是类型转换为LPWSTR,我怀疑您是,在这种情况下,Errorist 的示例甚至不应该在 C++ 中编译,因为CreateProcess() 的第二个参数需要是指向 可写 内存缓冲区,而不是字符串文字。
  • @E.Ginzburg 阅读documentation: "这个函数的Unicode版本,CreateProcessW,可以修改这个[lpCommandLine]字符串的内容。因此,这个[lpCommandLine ] 参数不能是指向只读内存的指针(例如 const 变量或文字字符串)。 如果此 [lpCommandLine] 参数是常量字符串,则该函数可能会导致访问冲突。”
猜你喜欢
  • 2022-01-26
  • 2014-06-23
  • 2013-07-09
  • 2012-11-13
  • 1970-01-01
  • 2022-01-05
  • 2018-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多