【问题标题】:How do I convert argv to lpCommandLine parameter of CreateProcess?如何将 argv 转换为 CreateProcess 的 lpCommandLine 参数?
【发布时间】:2015-08-05 16:52:21
【问题描述】:

让我想编写一个启动另一个应用程序的应用程序。像这样:

# This will launch another_app.exe
my_app.exe another_app.exe 
# This will launch another_app.exe with arg1, arg and arg3 arguments
my_app.exe another_app.exe arg1 arg2 arg3

这里的问题是我在我的main 函数中得到了char* argv[],但我需要将它合并到LPTSTR 以便将它传递给CreateProcess

有一个 GetCommandLine 函数,但我不能使用它,因为我从 Linux 移植代码并绑定到 argc/argv(否则,这对我来说是一个非常丑陋的 hack)。

我不能轻松地手动合并参数,因为argv[i] 可能包含空格。

基本上,我想要CommandLineToArgvW 的反面。有没有标准方法可以做到这一点?

【问题讨论】:

  • 你觉得这个问题的哪个方面很难?
  • @DavidHeffernan 我希望你是在开玩笑。代码审查不能容忍这种情况。
  • @DavidHeffernan:然后首先要求 OP 发布工作代码,同时确保某些代码确实存在。在问题准备就绪之前,不要推荐其他网站。
  • @Jamal 这显然是不同网站上的不同问题。我没有说“在那里问这个问题”,我说“在那里问”。
  • @RossRidge 工作代码的问题是“现在我需要逆,那是什么?”很可能在这里和那里无关紧要(功能请求在代码审查中是无关紧要的)。默认情况下,并非所有 SO 上的工作代码都是题外话。

标签: c++ c windows winapi createprocess


【解决方案1】:

Daniel Colascione 的博客上有关于如何引用论点的明确答案:

https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/

我不愿意在这里引用代码,因为我不知道许可证。基本思路是:

for each single argument:
    if it does not contain  \t\n\v\", 
        just use as is
    else
        output "
        for each character
            backslashes = 0
            if character is backslash
                count how many successive backslashes there are
            fi
            if eow
                output the backslashs doubled
                break
            else if char is "
                output the backslashs doubled
                output \"
            else
                output the backslashes (*not* doubled)
                output character
            fi
        rof
        output "
    fi // needs quoting
rof // each argument

如果需要将命令行传递给cmd.exe,请看文章(不一样)。

我认为 Microsoft C 运行时库没有执行此操作的函数,这太疯狂了。

【讨论】:

    【解决方案2】:

    没有与CommandLineToArgvW() 相反的 Win32 API。您必须自己格式化命令行字符串。这只不过是基本的字符串连接。

    Microsoft 记录了命令行参数的格式(或者至少是 VC++ 编写的应用程序所期望的格式):

    Parsing C++ Command-Line Arguments

    Microsoft C/C++ 启动代码在以下情况下使用以下规则: 解释在操作系统命令行上给出的参数:

    • 参数由空格分隔,空格可以是空格,也可以是 标签。

    • 插入字符 (^) 未被识别为转义字符或 分隔符。字符完全由命令行处理 在传递给 argv 数组之前,操作系统中的解析器 在程序中。

    • 用双引号 ("string") 括起来的字符串是 解释为单个参数,而不管包含的空格 之内。带引号的字符串可以嵌入到参数中。

    • 解释前面有反斜杠 (\") 的双引号 作为文字双引号字符 (")。

    • 反斜杠按字面意思解释,除非它们立即 在双引号之前。

    • 如果偶数个反斜杠后跟双引号 标记,每对在 argv 数组中放置一个反斜杠 反斜杠,双引号被解释为字符串 分隔符。

    • 如果奇数个反斜杠后跟双引号 标记,每对在 argv 数组中放置一个反斜杠 反斜杠,双引号被“转义” 剩余的反斜杠,导致文字双引号 (") 放在argv中。

    您应该不难编写一个函数,该函数接受一个字符串数组并将它们连接在一起,将上述规则的相反规则应用于数组中的每个字符串。

    【讨论】:

      【解决方案3】:

      您需要重新创建命令行,注意将所有程序名称和参数包含在" 中。这是通过将\" 连接到这些字符串来完成的,一个在开头,一个在结尾。

      假设要创建的程序名是argv[1],第一个参数argv[2]等...

      char command[1024]; // size to be adjusted
      int i;
      for (*command=0, i=1 ; i<argc ; i++) {
         if (i > 1) strcat(command, " ");
         strcat(command, "\"");
         strcat(command, argv[i]);
         strcat(command, "\"");
      }
      

      使用 CreateProcess 的 2nd 参数

      CreateProcess(NULL, command, ...);
      

      【讨论】:

      • 好吧,您还必须转义所有存在的"\ ^ 字符。如果strchr(argv[i], ' ')strchr(argv[i], '\t'),也可以使引用成为可选
      • @lockcmpxchg8b :问题询问“CreateProcess”。除非通过 Cmd.exe,否则不需要引用 '^'。
      • 你是对的。我在实现时发现了这一点。
      【解决方案4】:

      如果适合你的需要,你可以查看下面的代码,txt 数组 sz 可以用作字符串指针。我添加了对 Unicode 和 MBCS 的代码支持,

                  #include <string>
                  #include <vector>
      
                  #ifdef _UNICODE
                      #define String std::wstring
                  #else
                      #define String std::string
                  #endif 
      
                  int _tmain(int argc, _TCHAR* argv[])
                  {
                      TCHAR sz[1024] = {0};
                      std::vector<String> allArgs(argv, argv + argc);
      
                      for(unsigned i=1; i < allArgs.size(); i++)
                      {
                          TCHAR* ptr = (TCHAR*)allArgs[i].c_str();
                          _stprintf_s(sz, sizeof(sz), _T("%s %s"), sz, ptr);
                      }
      
                      return 0;
                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-28
        • 2015-09-10
        • 2011-12-08
        • 1970-01-01
        • 2012-09-27
        • 2018-01-14
        • 1970-01-01
        相关资源
        最近更新 更多