批处理一行以使用文件中的参数调用可执行文件

Batch one line to call an executable using arguments from file

为方便起见,我已将所有文件重命名为我的示例的简单名称。

我正在尝试 运行 一个可执行文件 (test.exe),带有 C++ 入口点 int main(int argc, char* argv[]) 批处理文件 (test.bat),以及从文本文件 (test.txt) 传递参数。最终目标是 运行 使用测试软件 (test.exe) 在 SDK 上进行单元测试。

我的问题是 我不想在调用可执行文件时使用变量,因为它会使代码更难阅读:

rem This works
set /p test_input=<test.txt& call test.exe %test_input%

经过一些研究,我认为我应该像这样使用 输入重定向 :

rem This does not work
call test.exe < test.txt

这个不行,我不明白为什么。

这是我最初尝试的,之前在SO(here)上有人建议过。 我可以访问 test.exe 代码,所以我可以打印 argc 和 argv :

int main(int argc, char* argv[])
{
    if(new_argc >= 2)
    {
        if(strcmp("-help", argv[1]) ==0)
        {
            show_help();
            return 0;
        }
        for(int i=1; i < argc; i++)
        {
            if(strcmp("-framerate", argv[i]) ==0)
            {
                i++;
                if(i < argc)
                {
                    FrameRate = (float)atof(argv[i]);
                }
                else
                {
                    std::cerr << "Parameters error" << std::endl;
                    return 0;
                }
            } else if ...
            {
                ...
            }
        }
    }
}

如果我手动输入参数和参数,它会按预期工作。

test.txt

-arg1 param1 -arg2 param2 ...

test.bat

call test.exe < test.txt

输出:test.exe 运行s 好像没有参数或参数。

编辑: 添加了有关入口点的一些详细信息并重命名了批处理变量。

多亏了我问题下的评论,我被推向了正确的方向。

问题是我对<的理解。它的字面意思是“将文件读取到 STDIN”(如前所述 here). Many other documentation sites give vague definitions like (as mentionned here

command < filename : Type a text file and pass the text to command

我需要正确解析输入,因为 stdinargcargv 中不可用,但通过 std::cin.

我的批处理代码和文本文件保持不变,我想保持相同的解析形式以避免重写多个项目,所以我split输入字符串使用来自here的Solution 1.3 (稍作修改)并创建了一个 new_argv.

std::vector<char*> split(const std::string& s, char delimiter)
{
    std::vector<char*> tokens;
    std::string token;
    std::istringstream tokenStream(s);
    while (std::getline(tokenStream, token, delimiter))
    {
        tokens.push_back(_strdup(token.c_str()));
    }
    return tokens;
}

int main(int argc, char* argv[])
{
    std::string extra_input; // Variable to store the contents of test.txt
    std::getline(std::cin, extra_input); // Recuperate the contents of test.txt
    std::vector<char*> new_argv = split(extra_input, ' '); // Split the args
    for(int i = argc - 1; i >= 0; i--)
        new_argv.insert(new_argv.begin(), argv[i]); // Add the original args to the beginning
    const size_t new_argc = new_argv.size(); // Create the new argc based on the final argument list (vector)

    if(new_argc >= 2)
    {
        if(strcmp("-help", new_argv[1]) ==0)
        {
            show_help();
            return 0;
        }
        for(int i=1; i < new_argc; i++)
        {
            if(strcmp("-framerate", new_argv[i]) ==0)
            {
                i++;
                if(i < new_argc)
                {
                    FrameRate = (float)atof(new_argv[i]);
                }
                else
                {
                    std::cerr << "Parameters error" << std::endl;
                    return 0;
                }
            } else if ...
            {
                ...
            }
        }
    }
    // Important, don't forget to free the memory used by the _strdup
    for(int i=1; i < new_argc; i++)
    {
        if(i >= argc)
            free(new_argv[i]);
    }
}

test.bat

call test.exe < test.txt

test.txt

-arg1 param1 -arg2 param2 ...

当然,我需要添加一些检查以使其正确处理空格,但这就是它的要点。感谢您的帮助和外部观点。

编辑:修正了代码中的一个错误。