【问题标题】:Start QProcess with absolute paths in argument list使用参数列表中的绝对路径启动 QProcess
【发布时间】:2014-03-14 13:36:13
【问题描述】:

问题

我正在尝试使用 QProcess 启动应用程序,但是我不知道如何在参数中提供带有空格的参数。我试过了

我的尝试

QString appPath = "\"C:/Users/USER/Google Drive/projects/qt_projects/someproject/
ghostpdl-8.71-win32/gxps-871.exe\"";

QStringList arguments;
arguments << "-sDEVICE=pdfwrite" << "-sOutputFile=\"C:/Users/USER/Google Drive/
projects/qt_projects/someproject/output.pdf\"" << "-dNOPAUSE \"C:/Users/USER/
Google Drive/projects/qt_projects/someproject/file.xps\"";

QProcess *converter = new QProcess();
converter->start(appPath, arguments);

我认为这与运行控制台命令相同(有效):

  "C:/Users/USER/Google Drive/projects/qt_projects/someproject/
  ghostpdl-8.71-win32/gxps-871.exe" -sDEVICE=pdfwrite
  -sOutputFile="C:/Users/USER/Google Drive/projects/qt_projects/
  someproject/output.pdf" -dNOPAUSE "C:/Users/USER/Google Drive/
  projects/qt_projects/someproject/file.xps"

谁能给我解释一下我是怎么做到的?

【问题讨论】:

    标签: c++ windows qt qprocess


    【解决方案1】:

    理解的关键是:Windows 上一般没有“多个命令行参数”这样的东西。命令行作为单个字符串传递给接收应用程序。在 Unices 上,命令行是作为多个参数传递的,所以它在那里更理智。

    本次讨论的其余部分是关于 Windows。

    将命令行拆分为字符串取决于您将参数传递到的应用程序的 C 运行时库。这种行为不是标准化的。您需要参考相关 C 运行时的文档来弄清楚它是如何做到的。是的,就是这么糟糕。

    是否有一些程序不能用Qt打开?

    一点也不。您需要知道的是,在开始该过程之前,Qt 将使用空格分隔符加入参数列表。如果参数包含空格并且既不以'"' 开头也不以结尾,它将被包含在'"' 中。如果参数包含 '"',它们将被转义。这是在qprocess_win.cpp, qt_create_commandline() 中完成的。这样做是为了与 MSVC 运行时兼容。应用程序当然可能更喜欢以自己的方式做事,例如,根本不使用 msvcrt。

    【讨论】:

      【解决方案2】:

      这里的问题是您通过将参数拆分为参数列表来分离参数。你可以这样做,但你只需要一个参数来传递给命令,它被封装在引号中。

      那么,让我们使用控制台命令:-

      "gxps-871.exe" -sDEVICE=pdfwrite -sOutputFile="C:/Users/USER/Google Drive/projects/qt_projects/someproject/output.pdf" -dNOPAUSE "C:/Users/USER/Google Drive/projects/qt_projects/someproject/file.xps"
      

      为了便于阅读,我删除了命令的路径。

      参数需要被视为传递给命令的一个参数

      所以我们可以创建一个参数字符串,但我们要创建一个参数,所以添加引号......

      QString arg("\"<args to go here>\"");
      

      现在我们添加参数,它们被添加到引号内以创建单个参数,但转义所有其他引号以保持空白...

      QString arg("\"-sDEVICE=pdfwrite -sOutputFile=\"C:/Users/USER/Google Drive/projects/qt_projects/someproject/output.pdf\" -dNOPAUSE \"C:/Users/USER/Google Drive/projects/qt_projects/someproject/file.xps\"\"");
      

      然后设置appPath...

      QString appPath = "\"C:/Users/USER/Google Drive/projects/qt_projects/someproject/ghostpdl-8.71-win32/gxps-871.exe\"";
      

      将参数添加到 QStringList..

      QStringList arguments;
      arguments << arg;
      

      开始进程...

      converter->start(appPath, arguments);
      

      这里的参数列表是不必要的,你可以在一行中完成所有这些:-

      converter->start("\"C:/Users/USER/Google Drive/projects/qt_projects/someproject/ghostpdl-8.71-win32/gxps-871.exe\" \"-sDEVICE=pdfwrite -sOutputFile=\"C:/Users/USER/Google Drive/projects/qt_projects/someproject/output.pdf\" -dNOPAUSE \"C:/Users/USER/Google Drive/projects/qt_projects/someproject/file.xps\"\"");
      

      但是很容易错过一个引用,或者一个引用的转义,它会变得相当混乱,你不觉得吗?!

      【讨论】:

      • 感谢您的详细解答。但是它仍然不起作用:(我有点没有想法......
      • 是否有一些程序不能用Qt打开?
      • 尝试运行两个不同的程序 - calc.exe 和 cmd.exe。 QProcess *converter = new QProcess(); QString cmdPath = "C:/WINDOWS/system32/cmd.exe"; QString calc = "C:/WINDOWS/system32/calc.exe";转换器->开始(cmdPath); // 不工作转换器->开始(计算); // 可以工作
      • 对不起,我没有看到 QProcess 失败,除非命令的路径错误,您没有运行指定命令的访问权限,或者参数错误。如果只是运行 cmd.exe 失败,那么我怀疑 QProcess 以外的其他问题是这里的问题。您是否尝试过调用 waitForFinished 并查看它是否立即返回。另外,将插槽连接到错误信号并检查是否有任何错误消息。
      • 这可能是您建议的许可事项。如果我写:转换器->setProcessChannelMode(QProcess::MergedChannels);转换器->开始(程序,参数); if (!converter->waitForFinished()) qDebug() errorString(); else qDebug() readAll();我收到错误消息:输出:“无法打开 [....] 进行阅读”
      【解决方案3】:

      据此this blog postQProcess 内部调用createProcess。如果从非提升进程调用 createProcess 会失败,如果它尝试启动需要提升的可执行文件,则会出现 ERROR_ELEVATION_REQUIRED。

      在博客文章中,他通过调用 shellexecute 解决了这个问题,但是我也无法完成这项工作。我的最终解决方案是使用 windows.h 中的 system() 函数。使用 system(),您可以执行与 cmd.exe 相同的命令。用法示例:

      #include <windows.h>
      ...
      system(""C:\\test_folder\\ghostpdl-8.71-win32\\gxps-871.exe -sDEVICE=pdfwrite -
      sOutputFile=\"C:\\test_folder\\output.pdf\" -dNOPAUSE \"C:\\test_folder\\file.xps\"
      ");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-15
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多